linux进程间通信之消息队列
2014-03-11 10:18
344 查看
消息队列是消息的链表,存放在内核中并由消息队列标识符标识。
对于系统中的每个消息队列,内核维护一个定义在<sys/msg.h>头文件中的信息结构
msgget用于创建一个新队列或打开一个现存的队列。
msgsnd将新消息添加到队列尾端,每个消息包含一个正长整型字段,一个非负长度以及实际数据字节。
msgrcv用于从队列中取消息,可以先进先出的次序取消息,也可以按消息的类型字段取消息
key:消息队列关联的键。可通过ftok函数获得
msgflg:消息队列的建立标志和存取权限。
IPC_CREAT如果内核中没有此队列,则创建它。
IPC_EXCL当和IPC_CREAT一起使用时,如果队列已经存在,则失败。
如果单独使用IPC_CREAT,则msgget()要么返回一个新创建的消息队列的标识符,要么返回具有相同关键字值的队列的标识符。如果IPC_EXCL和IPC_CREAT一起使用,则msgget()要么创建一个新的消息队列,要么如果队列已经存在则返回一个失败值-1。IPC_EXCL单独使用是没有用处的。
msqid:消息队列的识别码。
msgp:指向消息缓冲区的指针,此位置用来暂时存储发送和接收的消息,是一个用户可定义的通用结构,形态如下
struct msgbuf {
long mtype; /* 消息类型,必须 > 0 */
char mtext[1]; /* 消息文本 */
};
msgsz:消息的大小。
msgtyp:消息类型
msgtyp等于0 则返回队列的最早的一个消息。
msgtyp大于0,则返回其类型为mtype的第一个消息。
msgtyp小于0,则返回其类型小于或等于mtype参数的绝对值的最小的一个消息。
msgflg:这个参数依然是是控制函数行为的标志,取值可以是:0,表示忽略;IPC_NOWAIT,如果消息队列为空,则返回一个ENOMSG,并将控制权交回调用函数的进程。如果不指定这个参数,那么进程将被阻塞直到函数可以从队列中得到符合条件的消息为止。如果一个client 正在等待消息的时候队列被删除,EIDRM 就会被返回。如果进程在阻塞等待过程中收到了系统的中断信号,EINTR 就会被返回。MSG_NOERROR,如果函数取得的消息长度大于msgsz,将只返回msgsz 长度的信息,剩下的部分被丢弃了。如果不指定这个参数,E2BIG
将被返回,而消息则留在队列中不被取出。当消息从队列内取出后,相应的消息就从队列中删除了。
msgctl函数对队列执行多种操作
IPC_STAT
读取消息队列的数据结构msqid_ds,并将其存储在b u f指定的地址中。
IPC_SET
设置消息队列的数据结构msqid_ds中的ipc_perm元素的值。这个值取自buf参数。
IPC_RMID
从系统内核中移走消息队列。
下面展示了两个进程通过消息队列通信的实例
进程A
进程B
对于系统中的每个消息队列,内核维护一个定义在<sys/msg.h>头文件中的信息结构
struct msqid_ds { struct ipc_perm msg_perm; /* 相关权限 */ time_t msg_stime; /* 上一次发送时间 */ time_t msg_rtime; /* 上一次接收时间 */ time_t msg_ctime; /* 上一次改变时间 */ unsigned long __msg_cbytes; /* 当前队列的字节数 */ msgqnum_t msg_qnum; /* 当前队列中的消息数 */ msglen_t msg_qbytes; /* 消息队列所能存储的最大值 */ pid_t msg_lspid; /* 上一个发送消息的进程ID */ pid_t msg_lrpid; /* 上一个接收消息的进程ID */ };
msgget用于创建一个新队列或打开一个现存的队列。
msgsnd将新消息添加到队列尾端,每个消息包含一个正长整型字段,一个非负长度以及实际数据字节。
msgrcv用于从队列中取消息,可以先进先出的次序取消息,也可以按消息的类型字段取消息
#include <sys/ipc.h> #include <sys/msg.h> int msgget(key_t key, int msgflg); 返回值:成功则返回消息队列ID,失败返回-1参数:
key:消息队列关联的键。可通过ftok函数获得
msgflg:消息队列的建立标志和存取权限。
IPC_CREAT如果内核中没有此队列,则创建它。
IPC_EXCL当和IPC_CREAT一起使用时,如果队列已经存在,则失败。
如果单独使用IPC_CREAT,则msgget()要么返回一个新创建的消息队列的标识符,要么返回具有相同关键字值的队列的标识符。如果IPC_EXCL和IPC_CREAT一起使用,则msgget()要么创建一个新的消息队列,要么如果队列已经存在则返回一个失败值-1。IPC_EXCL单独使用是没有用处的。
#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); 返回值:成功则返回0,出错返回-1 ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); 返回值:成功则返回消息数据部分的长度,出错返回-1参数
msqid:消息队列的识别码。
msgp:指向消息缓冲区的指针,此位置用来暂时存储发送和接收的消息,是一个用户可定义的通用结构,形态如下
struct msgbuf {
long mtype; /* 消息类型,必须 > 0 */
char mtext[1]; /* 消息文本 */
};
msgsz:消息的大小。
msgtyp:消息类型
msgtyp等于0 则返回队列的最早的一个消息。
msgtyp大于0,则返回其类型为mtype的第一个消息。
msgtyp小于0,则返回其类型小于或等于mtype参数的绝对值的最小的一个消息。
msgflg:这个参数依然是是控制函数行为的标志,取值可以是:0,表示忽略;IPC_NOWAIT,如果消息队列为空,则返回一个ENOMSG,并将控制权交回调用函数的进程。如果不指定这个参数,那么进程将被阻塞直到函数可以从队列中得到符合条件的消息为止。如果一个client 正在等待消息的时候队列被删除,EIDRM 就会被返回。如果进程在阻塞等待过程中收到了系统的中断信号,EINTR 就会被返回。MSG_NOERROR,如果函数取得的消息长度大于msgsz,将只返回msgsz 长度的信息,剩下的部分被丢弃了。如果不指定这个参数,E2BIG
将被返回,而消息则留在队列中不被取出。当消息从队列内取出后,相应的消息就从队列中删除了。
msgctl函数对队列执行多种操作
#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> int msgctl(int msqid, int cmd, struct msqid_ds *buf); 返回值:成功返回0,失败返回-1参数:
IPC_STAT
读取消息队列的数据结构msqid_ds,并将其存储在b u f指定的地址中。
IPC_SET
设置消息队列的数据结构msqid_ds中的ipc_perm元素的值。这个值取自buf参数。
IPC_RMID
从系统内核中移走消息队列。
下面展示了两个进程通过消息队列通信的实例
进程A
#include <stdio.h> #include <stdlib.h> #include <sys/msg.h> #include <fcntl.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include <unistd.h> struct msgbuf { long mtype; char mtext[200]; }; main() { int msgid; key_t key; int r; int num; struct msgbuf buf; key = ftok(".", 255); if (key == -1) perror("ftok error"), exit(-1); msgid = msgget(key, IPC_CREAT|0666); if (msgid == -1) perror("msgid error"), exit(-1); num = 0; while (1) { sprintf(buf.mtext, "%d", num); r = msgsnd(msgid, &buf, sizeof(buf.mtext), 0); num++; sleep(1); } }
进程B
#include <stdio.h> #include <stdlib.h> #include <sys/msg.h> #include <fcntl.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include <unistd.h> struct msgbuf { long mtype; char mtext[200]; }; main() { int msgid; key_t key; ssize_t r; struct msgbuf buf; key = ftok(".", 255); if (key == -1) perror("ftok error"), exit(-1); msgid = msgget(key, 0); if(msgid == -1) perror("msgid error"), exit(-1); while(1) { r = msgrcv(msgid, &buf, 200, 0, 0); if (r < 0) perror("msgrcv error"), exit(-1); printf("%s\n", buf.mtext); sleep(1); } }
相关文章推荐
- Linux 进程间通信之 消息队列
- Linux进程间通信之消息队列
- Linux进程间通信(二) - 消息队列
- linux 系统编程-学习笔记10--进程间通信--管道/FIFO/消息队列/
- Linux进程间通信--进程,信号,管道,消息队列,信号量,共享内存
- Unix/Linux进程间通信——(System V)消息队列
- Linux进程间通信——使用消息队列
- Linux进程间通信:消息队列
- Linux进程间通信——消息队列(一)
- linux进程间通信之消息队列
- Linux下进程间通信--消息队列
- Linux进程间通信——使用消息队列
- Linux进程间通信——消息队列(二)
- Linux环境进程间通信(三) 消息队列
- Linux进程间通信——消息队列应用实例
- linux 进程间通信---消息队列
- linux 进程间通信--systemV 消息队列 实例
- linux进程间通信——消息队列
- Linux进程间通信——使用消息队列
- Linux进程间通信--信号,管道,消息队列,信号量,共享内存,socket