Linux 中的訊息佇列是一種程序間通訊(IPC)機制,允許不同程序之間透過訊息進行通訊。
訊息佇列中的相關函式:
msgget:建立或開啟一個訊息佇列。 函式原型:int msgget(key_t key, int msgflg); 引數: key:訊息佇列的鍵值,用於標識訊息佇列。 msgflg:標誌引數,用於指定訊息佇列的建立方式和許可權。 返回值:成功時返回訊息佇列的識別符號(非負整數),失敗時返回 -1。 msgctl:對訊息佇列進行控制。 函式原型:int msgctl(int msqid, int cmd, struct msqid_ds *buf); 引數: msqid:訊息佇列的識別符號。 cmd:控制命令,用於指定執行的操作。 buf:指向 struct msqid_ds 結構的指標,用於傳遞或接收訊息佇列的狀態資訊。 返回值:成功時返回0,失敗時返回 -1。 msgsnd:向訊息佇列傳送訊息。 函式原型:int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); 引數: msqid:訊息佇列的識別符號。 msgp:指向要傳送的訊息的指標。 msgsz:訊息的大小(以位元組為單位)。 msgflg:標誌引數,用於指定傳送訊息的行為。 返回值:成功時返回0,失敗時返回 -1。 msgrcv:從訊息佇列接收訊息。 函式原型:ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); 引數: msqid:訊息佇列的識別符號。 msgp:指向儲存接收訊息的緩衝區的指標。 msgsz:緩衝區的大小(以位元組為單位)。 msgtyp:指定所接收訊息的型別。 msgflg:標誌引數,用於指定接收訊息的行為。 返回值:成功時返回接收到的訊息的大小(以位元組為單位),失敗時返回 -1。
對於ftok補充一點,ftok 函式是一個用於生成 System V IPC(Inter-Process Communication,程序間通訊)中鍵值的函式。在 System V IPC 中,諸如訊息佇列、共享記憶體和訊號量等資源都需要一個唯一的鍵值來標識。
ftok 函式的原型如下:
key_t ftok(const char *pathname, int proj_id); 它接受兩個引數: pathname:一個指向檔案的路徑名的指標。通常情況下,你可以選擇一個現有的檔案,該檔案的存在與否對 ftok 函式的結果不會產生影響,因為它只關注檔案的索引節點號(inode number)和專案 ID(proj_id)。 proj_id:一個使用者定義的整數,用於生成鍵值的低8位。通常情況下,你可以為不同的 IPC 資源設定不同的專案 ID,以確保它們的鍵值不衝突。
ftok 函式將 pathname 引數指定的檔案的索引節點號和 proj_id 引數合併起來,然後透過一系列位操作生成一個唯一的鍵值。這個鍵值將作為 System V IPC 中資源的識別符號,用於建立或獲取相應的資源。
需要注意的是,ftok 函式的返回值是一個鍵值 key_t,這個鍵值會傳遞給 msgget、shmget 或 semget 等函式,用於建立或獲取對應的訊息佇列、共享記憶體或訊號量。
更多關於ftok函式的解析可見:ftok()函式深度解析
說白了ftok函式就是根據檔案生成一個key_t型別的值,key_t一般是一個長整型,那完全可用用一個長整型的數進行替換即可,前提是該長整型數沒有作為key_t使用
傳送訊息的程式msg1.c
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include <string.h> #define MAX_MSG_SIZE 1024 #define MSG_TYPE 1 // 定義訊息結構體 struct msg_buffer { long msg_type; char msg_text[MAX_MSG_SIZE]; }; int main() { int i; int msg_id; key_t key; struct msg_buffer message; // 生成一個唯一的鍵值 if ((key = ftok("lethe1203", 'B')) == -1) { perror("ftok"); exit(EXIT_FAILURE); } // 建立一個訊息佇列,如果不存在則建立,否則開啟 if ((msg_id = msgget(key, 0666 | IPC_CREAT)) == -1) { // 這裡完全可用把key替換為12345678等,去掉"生成一個唯一的鍵值"的步驟 perror("msgget"); exit(EXIT_FAILURE); } printf("Sending multiple messages to the queue...\n"); // 傳送多條訊息到佇列 for (i = 1; i <= 5; ++i) { // 設定訊息的型別為 MSG_TYPE message.msg_type = MSG_TYPE; // 構造訊息內容 sprintf(message.msg_text, "This is message %d from sender", i); // 傳送訊息 if (msgsnd(msg_id, &message, sizeof(message.msg_text), 0) == -1) { perror("msgsnd"); exit(EXIT_FAILURE); } printf("Message %d sent to queue.\n", i); // 為了演示,傳送完一條訊息後暫停五秒 sleep(5); } printf("All messages sent to the queue.\n"); return 0; }
接收訊息的程式msg2.c:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include <string.h> #define MAX_MSG_SIZE 1024 #define MSG_TYPE 1 // 定義訊息結構體 struct msg_buffer { long msg_type; char msg_text[MAX_MSG_SIZE]; }; int main() { int msg_id; key_t key; struct msg_buffer message; // 生成一個唯一的鍵值 if ((key = ftok("lethe1203", 'B')) == -1) { perror("ftok"); exit(EXIT_FAILURE); } // 獲取現有的訊息佇列,如果不存在則建立 if ((msg_id = msgget(key, 0666 | IPC_CREAT)) == -1) { // 這裡完全可用把key替換為12345678等,去掉"生成一個唯一的鍵值"的步驟 perror("msgget"); exit(EXIT_FAILURE); } printf("Receiving messages from the queue...\n"); // 從佇列中接收訊息 while (1) { // 接收訊息 if (msgrcv(msg_id, &message, sizeof(message.msg_text), MSG_TYPE, 0) == -1) { perror("msgrcv"); exit(EXIT_FAILURE); } // 列印接收到的訊息 printf("Message received: %s\n", message.msg_text); } return 0; }