Linux IPC System V 訊息佇列:實現可靠訊息傳遞的經典方式
Linux系統是一種支援多任務並發執行的作業系統,它可以同時運行多個進程,從而提高系統的使用率和效率。但是,如果這些進程之間需要進行資料交換和協作,就需要使用一些進程間通訊(IPC)的方式,例如訊號、共享記憶體、信號量等。其中,System V 訊息佇列是一種比較經典且可靠的IPC方式,它可以讓兩個或多個進程透過一個佇列來進行訊息傳遞,而無需關心訊息的內容和格式。本文將介紹Linux系統中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中文網其他相關文章!

熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

VS Code 系統要求:操作系統:Windows 10 及以上、macOS 10.12 及以上、Linux 發行版處理器:最低 1.6 GHz,推薦 2.0 GHz 及以上內存:最低 512 MB,推薦 4 GB 及以上存儲空間:最低 250 MB,推薦 1 GB 及以上其他要求:穩定網絡連接,Xorg/Wayland(Linux)

Linux系統的五個基本組件是:1.內核,2.系統庫,3.系統實用程序,4.圖形用戶界面,5.應用程序。內核管理硬件資源,系統庫提供預編譯函數,系統實用程序用於系統管理,GUI提供可視化交互,應用程序利用這些組件實現功能。

雖然 Notepad 無法直接運行 Java 代碼,但可以通過借助其他工具實現:使用命令行編譯器 (javac) 編譯代碼,生成字節碼文件 (filename.class)。使用 Java 解釋器 (java) 解釋字節碼,執行代碼並輸出結果。

VS Code擴展安裝失敗的原因可能包括:網絡不穩定、權限不足、系統兼容性問題、VS Code版本過舊、殺毒軟件或防火牆干擾。通過檢查網絡連接、權限、日誌文件、更新VS Code、禁用安全軟件以及重啟VS Code或計算機,可以逐步排查和解決問題。

要查看 Git 倉庫地址,請執行以下步驟:1. 打開命令行並導航到倉庫目錄;2. 運行 "git remote -v" 命令;3. 查看輸出中的倉庫名稱及其相應的地址。

vscode 內置終端是一個開發工具,允許在編輯器內運行命令和腳本,以簡化開發流程。如何使用 vscode 終端:通過快捷鍵 (Ctrl/Cmd ) 打開終端。輸入命令或運行腳本。使用熱鍵 (如 Ctrl L 清除終端)。更改工作目錄 (如 cd 命令)。高級功能包括調試模式、代碼片段自動補全和交互式命令歷史。

在 Visual Studio Code(VSCode)中編寫代碼簡單易行,只需安裝 VSCode、創建項目、選擇語言、創建文件、編寫代碼、保存並運行即可。 VSCode 的優點包括跨平台、免費開源、強大功能、擴展豐富,以及輕量快速。

VS Code 可以在 Mac 上使用。它具有強大的擴展功能、Git 集成、終端和調試器,同時還提供了豐富的設置選項。但是,對於特別大型項目或專業性較強的開發,VS Code 可能會有性能或功能限制。
