Linux进程间通信——消息队列

2019-07-12 14:27发布

一、消息队列概述         消息队列是一些消息的列表。用户可以从消息队列中添加消息和读取消息等。消息队列具有一定的FIFO特性,但是它可以实现消息的随机查询,比FIFO具有更大的优势。这些消息存在于内核中,由“队列ID”标识。 二、消息队列的应用 (1)函数说明          消息队列的实现包括创建或打开消息队列、添加消息、读取消息和控制消息队列: (1) msgget()创建或打开消息队列:创建的消息队列的数量会受到系统消息队列数量的限制 (2) msgsnd()添加消息:它把消息添加到已打开的信息队列末尾 (3) msgrcv()读取消息:它把消息从消息队列中取走,与FIFO不同的是,这里可以指定取走某一条消息 (4) msgclt()控制消息队列:它可以完成多项功能 (2)函数格式 msgget()函数语法要点 所需头文件 #include #include #include 函数原型 int msgget(key_t key,int msgflg) 函数传入值 key:消息队列的键值,多个进程可以通过它访问同一个消息队列,其中有个特殊值IPC_PRIVATE。它用于创建当前进程的私有消息队列。 msgflg:权限标志位 函数返回值 成功:消息队列ID 出错:-1 msgsnd()函数语法要点 所需头文件 #include #include #include 函数原型 int msgsnd(int msgid,const void *msgp,size_t msgsz,int msgflg) 函数传入值 msgid:消息队列的队列ID msgp:指向消息结构的指针。该消息结构msgbuf通常为: struct msgbuf {      long mtype;          /* 消息类型,该结构必须从这个域开始 */      char mtext[1];      /* 消息正文 */ } msgsz:消息正文的字节数(不包括消息类型指针变量) msgflg: IPC_NOWAIT若消息无法立即发送(比如:当消息队列已满),函数会立即返回 0:msgsnd调阻塞直到发送成功为止 函数返回值 成功:0 出错:-1 msgrcv()函数语法要点 所需头文件 #include #include #include 函数原型 int msgrcv(int msgid,void *msgp,size_t msgsz,long int msgtyp,int msgflg) 函数传入值 msqid:消息队列的队列ID msgp:消息缓冲区,同于msgsnd()函数的msgp msgsz:消息正文的字节数(不包括消息类型指针变量) msgtyp: 0:接收消息队列中第一个消息 大于0:接收消息队列中第一个类型为msgtyp的消息 小于0:接收消息队列中第一个类型值不小于msgtyp绝对值且类型值又最小的消息 msgflg: MSG_NOERROR:若返回的消息比msgsz字节多,则消息就会截短到msgsz字节,且不通知消息发送进程 IPC_NOWAIT:若在消息队列中并没有相应类型的消息可接收,则函数立即返回 0:msgrcv()调用阻塞直到接收到一条相应类型的消息为止 函数返回值 成功:0 失败:-1 msgctl()函数语法要点 所需头文件 #include #include #include 函数原型 int msgctl(int msgid,int cmd,struct msgid_ds *buf) 函数传入值 msgid:消息队列的队列ID cmd: 参数命令 IPC_STAT:读取消息队列的数据结构msgid_ds,并将其存储在buf指定的地址中 IPC_SET:设置消息队列的数据结构msgid_ds中的ipc_perm域(IPC操作权限描述结构)值。这个值取自buf参数。 IPC_RMID:从系统中删除消息队列 buf:描述消息队列的msgid_ds结构类型变量 函数返回值 成功:0 出错:-1 (3)使用实例 msgsnd.c /* msgsnd.c */ #include #include #include #include #include #include #include #include #define BUFSIZE 512 struct msgbuf { long mtype; char mtext[BUFSIZE]; }; int main() { int msgid; struct msgbuf msg; if((msgid = msgget((key_t)1234,IPC_CREAT|0666)) == -1) { printf("SEND:msgget error. "); exit(1); } while(1) { if(fgets(msg.mtext,BUFSIZE,stdin) == NULL) { printf("SEND:fgets error. "); exit(1); } msg.mtype = getpid(); if(msgsnd(msgid,&msg,BUFSIZE,0) == -1) { printf("SEND:msgsnd error. "); exit(1); } if(strncmp(msg.mtext,"quit",4) == 0) { break; } } exit(0); } msgrcv.c /* msgrcv.c */ #include #include #include #include #include #include #include #define BUFSIZE 512 struct msgbuf { long mtype; char mtext[BUFSIZE]; }; int main() { int msgid; struct msgbuf msg; if(msgid = msgget((key_t)1234,IPC_CREAT|0666) == -1) { printf("RECV:msgget error. "); exit(1); } do { memset(msg.mtext,0,BUFSIZE); if(msgrcv(msgid,(void *)&msg,BUFSIZE,0,0) == -1) { printf("RECV:msgrcv error. "); exit(1); } printf("RECV:%s ",msg.mtext); }while(strncmp(msg.mtext,"quit",4)); if(msgctl(msgid,IPC_RMID,NULL) == -1) { printf("RECV:msgctl(IPC_RMID) error. "); exit(1); } exit(0); }