消息队列 消息队列是一种进程间通信(IPC)机制,允许进程以消息的形式传递数据。它通过在内核中维护的队列实现,提供了异步通信的能力。消息队列由键值唯一标识,支持一个或多个进程之间的数据传输。
相关函数 msgget
1 int msgget (key_t key, int msgflg) ;
参数:
key
:消息队列的键即标识,可以通过 ftok
生成
msgflg
:访问权限。
IPC_CREAT
—— 如果 key 不存在,则创建
IPC_EXCL
—— 如果 key 存在,则返回失败
返回值:成功返回消息队列标识符(非负整数),失败返回 -1
msgsnd
1 int msgsnd (int msqid, const void *msgp, size_t msgsz, int msgflg) ;
参数:
msqid
:消息队列标识符,也就是上述创建的返回值
msgp
:指向消息的指针,是个结构体,但需要自己手动定义(放下面了)
msgsz
:消息正文的大小(不包括消息类型)
msgflg
:操作标志(如 IPC_NOWAIT
非阻塞发送,即如果包含此选项,则消息队列满时,不发送该消息,立即返回 -1。反之,如果不包含此选项,则消息队列满时,挂起本进程,直到消息队列由空间可用。)
1 2 3 4 5 struct message { long msg_type; char msg_text[100 ]; };
msgrcv
1 ssize_t msgrcv (int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg) ;
参数:
msqid
:消息队列标识符,即创建消息队列时候的函数返回值
msgp
:存储接收到的消息的指针(上面 msgsnd
已介绍)
msgsz
:期望接收的消息正文大小
msgtyp
:消息类型(0
表示接收任意类型)
0
:忽略消息类型,从消息队列中接收队列中的第一条消息(按照队列的 FIFO 顺序)
大于 0
:从消息队列中接收类型为 msg_type
的第一条消息,如果队列中没有匹配的消息,进程会阻塞,直到符合条件的消息到达(或设置了非阻塞标志)
小于 0
:从消息队列中接收类型值小于等于 |msg_type|
(绝对值)的消息,选择类型值小于等于 |msg_type|
且优先级最高的消息(类型值越小,优先级越高)
msgflg
:操作标志(如 IPC_NOWAIT
非阻塞接收,上述 msgsnd
已经介绍)
返回值:成功返回消息队列标识符(非负整数),失败返回 -1
msgctl
1 int msgctl (int msqid, int cmd, struct msqid_ds *buf) ;`
参数:
msqid
:消息队列标识符,即创建消息队列时候的函数返回值
cmd
:控制命令,指定要对消息队列执行的操作
IPC_STAT
:获取消息队列的当前状态
IPC_SET
:设置消息队列的属性
IPC_RMID
:从系统中删除消息队列
buf
:指向一个 msqid_ds
结构的指针,用于传递或接收消息队列的信息
**IPC_STAT
**:由内核填充 buf
,包含消息队列的当前状态,然后作为传出参数,用户可以进行读取数据查看消息队列状态
**IPC_SET
**:用户手动填充 buf
中的部分字段,将其作为传入参数,修改消息队列的属性
**IPC_RMID
**:此参数可以为 NULL
,因为该操作不需要 buf
返回值 :成功返回 0
,失败返回 -1
示例 发送方
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 #include <sys/ipc.h> #include <sys/msg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> struct msgbuf { long msg_type; char msg_text[256 ]; }; int main () { key_t key; int msqid; struct msgbuf msg ; key = ftok("." , 123 ); if (key == -1 ) { perror("ftok" ); exit (EXIT_FAILURE); } msqid = msgget(key, IPC_CREAT | 0666 ); if (msqid == -1 ) { perror("msgget" ); exit (EXIT_FAILURE); } printf ("Message queue created with ID: %d\n" , msqid); for (int i = 1 ; i <= 5 ; ++i) { msg.msg_type = 1 ; snprintf (msg.msg_text, sizeof (msg.msg_text), "Message %d from sender" , i); if (msgsnd(msqid, &msg, strlen (msg.msg_text) + 1 , 0 ) == -1 ) { perror("msgsnd" ); exit (EXIT_FAILURE); } printf ("Sent: %s\n" , msg.msg_text); sleep(1 ); } return 0 ; }
接收方
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 #include <sys/ipc.h> #include <sys/msg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> struct msgbuf { long msg_type; char msg_text[256 ]; }; int main () { key_t key; int msqid; struct msgbuf msg ; key = ftok("." , 123 ); if (key == -1 ) { perror("ftok" ); exit (EXIT_FAILURE); } msqid = msgget(key, 0666 ); if (msqid == -1 ) { perror("msgget" ); exit (EXIT_FAILURE); } printf ("Message queue opened with ID: %d\n" , msqid); while (1 ) { if (msgrcv(msqid, &msg, sizeof (msg.msg_text), 1 , 0 ) == -1 ) { perror("msgrcv" ); exit (EXIT_FAILURE); } printf ("Received: %s\n" , msg.msg_text); if (strcmp (msg.msg_text, "exit" ) == 0 ) { printf ("Received exit signal. Exiting...\n" ); break ; } } return 0 ; }
输出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Message queue created with ID: 12345 Sent: Message 1 from sender Sent: Message 2 from sender Sent: Message 3 from sender Sent: Message 4 from sender Sent: Message 5 from sender Message queue opened with ID: 12345 Received: Message 1 from sender Received: Message 2 from sender Received: Message 3 from sender Received: Message 4 from sender Received: Message 5 from sender
xingzhu
keep trying!keep doing!believe in yourself!
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 星竹 !