搜尋
首頁系統教程LinuxLinux IPC System V 訊息佇列:實現可靠訊息傳遞的經典方式

Linux IPC System V 訊息佇列:實現可靠訊息傳遞的經典方式

Feb 12, 2024 pm 03:33 PM
linuxlinux教程linux系統linux指令shell腳本typedeflsp嵌入式linuxlinux入門linux學習

Linux系統是一種支援多任務並發執行的作業系統,它可以同時運行多個進程,從而提高系統的使用率和效率。但是,如果這些進程之間需要進行資料交換和協作,就需要使用一些進程間通訊(IPC)的方式,例如訊號、共享記憶體、信號量等。其中,System V 訊息佇列是一種比較經典且可靠的IPC方式,它可以讓兩個或多個進程透過一個佇列來進行訊息傳遞,而無需關心訊息的內容和格式。本文將介紹Linux系統中System V 訊息佇列的方法,包括訊息佇列的建立、開啟、傳送、接收、關閉和刪除等面向。

Linux IPC System V 消息队列:一种实现可靠消息传递的经典方式

#模型

#include 
#include 
#include 
ftok()               //获取key值                               
msgget()             //创建/获取消息队列                        
msgsnd()/msgrcv()    //发消息到消息队列/从消息队列收信息        
msgctl()             //删除消息队列                           

ftok()

#
//获取key值, key值是System V IPC的标识符,成功返回key,失败返回-1设errno
//同pathname+同 proj_id==>同key_t;
key_t ftok(const char *pathname, int proj_id);

pathname :檔名
proj_id: 1~255的一個數,表示project_id

#
key_t key=ftok(".",100);    //“.”就是一个存在且可访问的路径, 100是假设的proj_id
    if(-1==key)
        perror("ftok"),exit(-1);

msgget()

#
//创建/获取消息队列,成功返回shmid,失败返回-1
int msgget(key_t key, int msgflg);  //ATTENTION:用int msqid=msgget()比较好看

msgflg:具體的操作標誌

  • IPC_CREAT 若不存在則建立, 需要在msgflg中"|權限資訊"; 若存在則開啟
  • IPC_EXCL若存在則建立失敗
  • #0 取得已經存在的訊息佇列

訊息佇列的容量由msg_qbytes控制,在訊息佇列被建立的過程中,這個大小被初始化為MSGMNB,這個限制可以透過msgctl()修改

int msqid=msgget(key,IPC_CREAT|IPC_EXCL|0664);
if(-1==msqid)
    perror("msgget"),exit(-1);

msgsnd()

#
//向指定的消息队列发送指定的消息,如果消息队列已经满了,默认的行为是堵塞,直到队列有空间容纳新的消息,成

功返回0,失败返回-1设errno
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

msqid msgget()傳回的訊息佇列的ID
msgp訊息的的首位址, 訊息的參考資料類型如下

struct msgbuf {
    long mtype;       /* message type, must be > 0 */   //消息的类型
    char mtext[1];    /* message data */                //消息的内容
};
ATTENTION:The  mtext field is an array (or other structure) whose size is
 specified by msgsz, a nonnegative integer value. 

msgsz訊息的大小, 此參數用於指定訊息內容的大小, 不包括訊息的類型。只能sizeof(Msgbuf.mtext),不能sizeof(Msgbuf)
msgflg發送的標誌, 預設給0即可

Msg msg1={1,"hello"};//消息的类型是1,内容是hello
int res=msgsnd(msqid,&msg2,sizeof(msg2.buf),0);
if(-1==res)
    perror("msgsnd"),exit(-1);

msgrcv()

#
//向指定的消息队列取出指定的消息,成功返回实际接受到的byte数,失败返回-1设errno
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);

msqid: 訊息佇列的ID(returned by msgget)
msgp: 存放接收到訊息的緩衝區首位址
msgsz : 訊息的最大大小, 不包含訊息的類型==>只能sizeof(Msgbuf.mtext),不能sizeof(Msgbuf)

  • 如果訊息的長度>msgsz且msgflg裡有MSG_NOERROR,則訊息會被截斷,被截斷的部分會遺失
  • # 如果訊息的長度>msgsz且msgflg裡沒有MSG_NOERROR,那麼會出錯,報E2BIG。

msgtyp: 訊息的類型

  • 0:讀取訊息佇列中的第一個訊息
  • >0:讀取訊息佇列中第一個type為msgtype的訊息, 除非msg_flg裡有MSG_EXCEPT,此時佇列中第一個type為msgtype的訊息, 除非msg_flg裡有MSG_EXCEPT,此時佇列中的第一個不是msgtyp的訊息會被讀取
  • #讀取訊息佇列中type

msgflg: 發送的標誌, 預設給0即可

Msg msg1;
int res=msgrcv(msqid,&msg1,sizeof(msg1.buf),1,0);
if(-1==res)
    perror("msgrcv"),exit(-1);

msgctl()

// 消息操作,成功返回0,失败返回-1设errno
int msgctl(int msqid, int cmd, struct msqid_ds *buf);

msqid :消息队列的ID,由msgget()
buf 结构体指针

struct msqid_ds {
    struct ipc_perm msg_perm;       /* Ownership and permissions */
    time_t          msg_stime;      /*Time of last msgsnd(2) */
    time_t          msg_rtime;      /* Time of last msgrcv(2) */
    time_t          msg_ctime;      /* Time of last change */
    unsigned long   __msg_cbytes;   /* Current number of bytes in queue (nonstandard) */
    msgqnum_t       msg_qnum;       /* Current number of messages in queue */
    msglen_t        msg_qbytes;     /* Maximum number of bytes allowed in queue */
    pid_t           msg_lspid;      /* PID of last msgsnd(2) */
    pid_t           msg_lrpid;      /* PID of last msgrcv(2) */
};
struct ipc_perm {
    key_t           __key;      /* Key supplied to msgget(2) */
    uid_t           uid;        /* Effective UID of owner */
    gid_t           gid;        /* Effective GID of owner */
    uid_t           cuid;       /* Effective UID of creator */
    gid_t           cgid;       /* Effective GID of creator */
    unsigned short  mode;       /* Permissions */
    unsigned short  __seq;      /* Sequence number */
};

cmd

  • IPC_STAT从内核相关结构体中拷贝消息队列相关的信息到buf指向的结构体中

  • IPC_SET把buf指向的结构体的内容写入到内核相关的结构体中,同时更显msg_ctimer成员,同时以下成员也会被更新:msg_qbytes, msg_perm.uid, msg_perm.gid, msg_perm.mode。调用队列的进程的effective UID必须匹配队列所有者或创建者的msg_perm.uid或msg_perm.cuid或者该进程拥有特权级别,

  • IPC_RMID立即销毁消息队列,唤醒所有正在等待读取或写入该消息队列进程,调用的进程的UID必须匹配队列所有者或创建者或者该进程拥有足够的特权级别

  • IPC_INFO (Linux-specific)返回整个系统对与消息队列的限制信息到buf指向的结构体中

    //_GNU_SOURCE
    //
    struct msginfo {
        int msgpool;/*Size in kibibytes of buffer pool used to hold message
     data; unused within kernel*/
        int msgmap; /*Maximum number of entries in message map; unused within 
    kernel*/
        int msgmax; /*Maximum number of bytes that can be written in a single
     message*/
        int msgmnb; /*Maximum number of bytes that can be written to queue; 
    used to initialize msg_qbytes  during queue creation*/
        int msgmni; /*Maximum number of message queues*/
        int msgssz; /*Message segment size; unused within kernel*/
        int msgtql; /*Maximum number of messages on all queues in system; unused
     within kernel*/
        unsigned short int  msgseg; /*Maximum number of segments; unused
     within kernel*/
    };
    
    int res=msgctl(msqid,IPC_RMID,NULL);
    if(-1==res)
    perror("msgctl"),exit(-1);
    

例子

//Sys V IPC msg
#include
#include
#include
#include
#include
typedef struct{
    long mtype;     //消息的类型
    char buf[20];       //消息的内容
}Msg;
int msqid;          //使用全局变量,这样就可以在fa中使用msqid了
void fa(int signo){
    printf("deleting..\n");
    sleep(3);
    int res=msgctl(msqid,IPC_RMID,NULL);
    if(-1==res)
        perror("msgctl"),exit(-1);
    exit(0);
}
int main(){
    //ftok()
    key_t key=ftok(".",150);
    if(-1==key)
        perror("ftok"),exit(-1);
    printf("key%#x\n",key);
    //msgget()
    msqid=msgget(key,IPC_CREAT|IPC_EXCL|0664);
    if(-1==msqid)
        perror("msgget"),exit(-1);
    printf("msqid%d\n",msqid);
    //msgsnd()
    Msg msg1={1,"hello"};//消息的类型是1,内容是hello
    Msg msg2={2,"world"};
    int res=msgsnd(msqid,&msg2,sizeof(msg2.buf),0);
    if(-1==res)
        perror("msgsnd"),exit(-1);
    res=msgsnd(msqid,&msg1,sizeof(msg1.buf),0);
    if(-1==res)
        perror("msgsnd"),exit(-1);
    //msgctl()
    //Ctrl+C delete msq
    printf("Press CTRL+C to delete msq\n");
    if(SIG_ERR==signal(SIGINT,fa))
        perror("signal"),exit(-1);
    while(1);
    return 0;
}

本文介绍了Linux系统中System V 消息队列的方法,包括消息队列的创建、打开、发送、接收、关闭和删除等方面。通过了解和掌握这些知识,我们可以更好地使用System V 消息队列来实现进程间通信,提高系统的稳定性和效率。当然,Linux系统中System V 消息队列还有很多其他的特性和用法,需要我们不断地学习和研究。希望本文能给你带来一些启发和帮助。

以上是Linux IPC System V 訊息佇列:實現可靠訊息傳遞的經典方式的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文轉載於:良许Linux教程网。如有侵權,請聯絡admin@php.cn刪除
如何學習Linux基礎知識?如何學習Linux基礎知識?Apr 10, 2025 am 09:32 AM

Linux基礎學習從零開始的方法包括:1.了解文件系統和命令行界面,2.掌握基本命令如ls、cd、mkdir,3.學習文件操作,如創建和編輯文件,4.探索高級用法如管道和grep命令,5.掌握調試技巧和性能優化,6.通過實踐和探索不斷提陞技能。

Linux最有用的是什麼?Linux最有用的是什麼?Apr 09, 2025 am 12:02 AM

Linux在服務器、嵌入式系統和桌面環境中的應用廣泛。 1)在服務器領域,Linux因其穩定性和安全性成為託管網站、數據庫和應用的理想選擇。 2)在嵌入式系統中,Linux因其高度定制性和高效性而受歡迎。 3)在桌面環境中,Linux提供了多種桌面環境,滿足不同用戶需求。

Linux的缺點是什麼?Linux的缺點是什麼?Apr 08, 2025 am 12:01 AM

Linux的缺點包括用戶體驗、軟件兼容性、硬件支持和學習曲線。 1.用戶體驗不如Windows或macOS友好,依賴命令行界面。 2.軟件兼容性不如其他系統,缺乏許多商業軟件的原生版本。 3.硬件支持不如Windows全面,可能需要手動編譯驅動程序。 4.學習曲線較陡峭,掌握命令行操作需要時間和耐心。

Linux難以學習嗎?Linux難以學習嗎?Apr 07, 2025 am 12:01 AM

Linuxisnothardtolearn,butthedifficultydependsonyourbackgroundandgoals.ForthosewithOSexperience,especiallycommand-linefamiliarity,Linuxisaneasytransition.Beginnersmayfaceasteeperlearningcurvebutcanmanagewithproperresources.Linux'sopen-sourcenature,bas

Linux的5個基本組件是什麼?Linux的5個基本組件是什麼?Apr 06, 2025 am 12:05 AM

Linux的五個基本組件是:1.內核,管理硬件資源;2.系統庫,提供函數和服務;3.Shell,用戶與系統交互的接口;4.文件系統,存儲和組織數據;5.應用程序,利用系統資源實現功能。

Ubuntu Home Automation:使用開源工具建立智能的居住空間Ubuntu Home Automation:使用開源工具建立智能的居住空間Apr 05, 2025 am 09:19 AM

開啟智能家居新篇章:基於Ubuntu的開源家庭自動化系統 智能家居技術徹底改變了我們與生活空間的互動方式,為日常生活帶來了便利、安全和能源效率。從遠程控制燈光和電器,到監控安全攝像頭和自動化氣候控制,智能家居技術變得越來越普及。 然而,許多商業智能家居系統存在局限性:高昂的成本、隱私問題以及有限的兼容性。幸運的是,開源軟件解決方案結合Ubuntu的強大功能,提供了一種替代方案——允許用戶創建可定制、經濟高效且安全的智能家居生態系統。 本指南將探討如何使用Ubuntu和開源工具設置家庭自動化系統。

Linux vs. Windows:什麼是2025年的差異?Linux vs. Windows:什麼是2025年的差異?Apr 05, 2025 am 09:05 AM

Linux與Windows:2025比較 考慮從MacOS或Windows切換? Linux可能是答案。 儘管MacOS用戶會發現相對平滑的過渡(由於MacOS的UNIX Core),但Windows用戶需要適應。此指南HIG

什麼是Linux設備?什麼是Linux設備?Apr 05, 2025 am 12:04 AM

Linux設備是運行Linux操作系統的硬件設備,包括服務器、個人電腦、智能手機和嵌入式系統。它們利用Linux的強大功能執行各種任務,如網站託管和大數據分析。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
3 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

mPDF

mPDF

mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。