linux IPC之消息队列
来源:互联网 发布:transmit mac 破解 编辑:程序博客网 时间:2024/04/30 12:26
消息队列相关概念
消息队列就是一个消息的链表。可以把消息看作一个记录,具有特定的格式以及特定的优先级。对消息队列有写权限的进程可以向其中按照一定的规则添加新消息;对消息队列有读权限的进程则可以从消息队列中读走消息。在linux系统中消息队列与键值一一对应。消息队列是通过链表管理的,内核提供一个struct msqid_ds *msgque[MSGMNI]向量维护内核的一个消息队列列表,因此linux系统支持的最大消息队列数由msgque数组大小来决定,每一个msqid_ds表示一个消息队列,并通过msqid_ds.msg_first、msg_last维护一个先进先出的msg链表队列,当发送一个消息到该消息队列时,把发送的消息构造成一个msg结构对象,并添加到msqid_ds.msg_first、msg_last维护的链表队列,同样,接收消息的时候也是从msg链表队列尾部查找到一个msg_type匹配的msg节点,从链表队列中删除该msg节点,并修改msqid_ds结构对象的数据。键值即是数组msgque的索引。
msqid_ds 与msg相关的关系如下图所示:
消息队列的使用步骤
- 获取键值
key_t ftok(char *pathname, char proj)
头文件为”sys/ipc.h”。返回文件名对应的键值,失败返回 -1。proj是消息队列名字,不能为空。fname是指定的文件名(已经存在的文件名)。需要有-t 的权限,或用root权限执行,通常设为/tmp。 - 创建/打开消息队列
int msgget(key_t key, int msgflg)
头文件为sys/msg.h。key由ftok获得。
msgflg有:
IPC_CREAT 创建新的消息队列,应配有文件权限0666。
IPC_EXCL 与IPC_CREAT一同使用,表示如果要创建的消息队列已经存在,则返回错误。
IPC_NOWAIT 读写消息不阻塞。
当没有与key相对应的消息队列并且msgflg中包含了IPC_CREAT标志 或 key的参数为IPC_PRIVATE 时,创建一个新的消息队列。 - 发送消息
int msgsnd(int msqid, struct msgbuf *msgp, int msgsz, int msgflg)
向消息队列发送一条消息。参数msqid为消息队列的id,msgp为存放消息的结构体。msgsz是消息的长度,和数组的大小不一样哦。msgflg为消息标志,通常为0,也可以为IPC_NOWAIT。出错返回 -1。
消息格式
struct msgbuf {
long mtype;
char mtext[100];
}; - 接收消息
int msgrcv(int msqid, struct msgbuf *msgp, int msgsz, long msgtyp, int msgflg)
参数msqid代表的消息队列中读取一个msgtyp类型的消息,并把消息存储在msgp指定的msgbuf结构中。读取后队列中的消息将会删除。size为结构体中数据的大小,不要计算msgtyp。出错返回 -1。 - 设置消息队列属性
int msgctl ( int msgqid, int cmd, struct msqid_ds *buf );
参数:msgctl 系统调用对 msgqid 标识的消息队列执行 cmd 操作,系统定义了 3 种 cmd 操作: IPC_STAT , IPC_SET , IPC_RMID
IPC_STAT : 该命令用来获取消息队列对应的 msqid_ds 数据结构,并将其保存到 buf 指定的地址空间。
IPC_SET : 该命令用来设置消息队列的属性,要设置的属性存储在buf中。
IPC_RMID : 从内核中删除 msqid 标识的消息队列。
示列
消息发送端:send.c
/*send.c*/ #include <stdio.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include <errno.h> #define MSGKEY 1024 struct msgstru { long msgtype; char msgtext[2048]; }; main() { struct msgstru msgs; int msg_type; char str[256]; int ret_value; int msqid; msqid=msgget(MSGKEY,IPC_EXCL); /*检查消息队列是否存在*/ if(msqid < 0){ msqid = msgget(MSGKEY,IPC_CREAT|0666);/*创建消息队列*/ if(msqid <0){ printf("failed to create msq | errno=%d [%s]\n",errno,strerror(errno)); exit(-1); } } while (1){ printf("input message type(end:0):"); scanf("%d",&msg_type); if (msg_type == 0) break; printf("input message to be sent:"); scanf ("%s",str); msgs.msgtype = msg_type; strcpy(msgs.msgtext, str); /* 发送消息队列 */ ret_value = msgsnd(msqid,&msgs,sizeof(struct msgstru),IPC_NOWAIT); if ( ret_value < 0 ) { printf("msgsnd() write msg failed,errno=%d[%s]\n",errno,strerror(errno)); exit(-1); } } msgctl(msqid,IPC_RMID,0); //删除消息队列 }
消息接收端 receive.c
/*receive.c */ #include <stdio.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include <errno.h> #define MSGKEY 1024 struct msgstru { long msgtype; char msgtext[2048]; }; /*子进程,监听消息队列*/ void childproc(){ struct msgstru msgs; int msgid,ret_value; char str[512]; while(1){ msgid = msgget(MSGKEY,IPC_EXCL );/*检查消息队列是否存在 */ if(msgid < 0){ printf("msq not existed! errno=%d [%s]\n",errno,strerror(errno)); sleep(2); continue; } /*接收消息队列*/ ret_value = msgrcv(msgid,&msgs,sizeof(struct msgstru),0,0); printf("text=[%s] pid=[%d]\n",msgs.msgtext,getpid()); } return; } void main() { int i,cpid; /* create 5 child process */ for (i=0;i<5;i++){ cpid = fork(); if (cpid < 0) printf("fork failed\n"); else if (cpid ==0) /*child process*/ childproc(); } }
0 0
- Linux IPC 之消息队列
- linux IPC之消息队列
- linux IPC之消息队列
- Linux IPC 之消息队列
- Linux XSI IPC 之消息队列
- linux IPC之POSIX消息队列
- linux下IPC之消息队列
- 【Linux】IPC通信之消息队列
- linux IPC-消息队列
- linux IPC-消息队列
- Linux IPC- 消息队列
- linux IPC--消息队列
- linux IPC---消息队列
- IPC之消息队列
- IPC之消息队列
- IPC之消息队列
- IPC之消息队列
- linux ipc—消息队列
- 怎么把PDF文件分割成单独的几页
- 看数据结构写代码(13)栈的应用(四) 迷宫求解
- nyoj 44 子串和 & nyoj 104 最大和
- gcc编译器 CFLAGS 标志参数说明
- 利用BeanUtils在对象间复制属性
- linux IPC之消息队列
- vs2010 空格出现点的解决办法
- windows自定义命令的创建
- 关于jquery jqgrid 列编辑状态时获得值
- Android应用之《宋词三百首》(一)
- jQuery 方法append与after
- 北大ACM试题1001
- Header V3 DSA signature: NOKEY, key ID
- ORACLE--查询当前连接的用户信息及操作的SQL语句