进程通信之 消息队列

消息队列例程

Msgget建立消息队列,msgget(key,IPC_CREAT|0660);key键值以及属性和权限

msgsnd(msgid,(void*)&msg_parent,sizeof(msg_parent)-sizeof(long),IPC_NOWAIT)

消息ID,消息地址,消息长度,以及阻塞设置等

函数原型:int  msgsnd ( int msgid ,  struct msgbuf*msgp , int msgsz, int msgflg );

参数说明:

传给msgsnd()函数的第一个参数msqid 是消息队列对象的标识符(由msgget()函数得

到),第二个参数msgp 指向要发送的消息所在的内存,第三个参数msgsz 是要发送信息     的长度(字节数),可以用以下的公式计算:
msgsz = sizeof(struct mymsgbuf) - sizeof(long);
第四个参数是控制函数行为的标志,可以取以下的值:
0,忽略标志位;
IPC_NOWAIT,如果消息队列已满,消息将不被写入队列,控制权返回调用函数的线
程。如果不指定这个参数,线程将被阻塞直到消息被可以被写入。


msgrcv(msgid,(void*)&msg_child,sizeof(msg_child)-sizeof(long),msg_type_child,IPC_NOWAIT)

消息ID , 消息地址,消息长度,消息种类,阻塞设置等

函数定义:int  msgrcv( int  msgid , struct   msgbuf*  msgp ,  int msgsz ,  long msgtyp, int msgflg);

参数:

函数的前三个参数和msgsnd()函数中对应的参数的含义是相同的。第四个参数mtype

指定了函数从队列中所取的消息的类型。函数将从队列中搜索类型与之匹配的消息并将 返回。不过这里有一个例外。如果mtype 的值是零的话,函数将不做类型检查而自动返     回队列中的最旧的消息。第五个参数依然是是控制函数行为的标志,取值可以是:
0,表示忽略;
IPC_NOWAIT,如果消息队列为空,则返回一个ENOMSG,并将控制权交回调用函数
的进程。如果不指定这个参数,那么进程将被阻塞直到函数可以从队列中得到符合条件 消息为止。如果一个client 正在等待消息的时候队列被删除,EIDRM 就会被返回。如果     进程在阻塞等待过程中收到了系统的中断信号,EINTR 就会被返回。
MSG_NOERROR,如果函数取得的消息长度大于msgsz,将只返回msgsz 长度的信息,
剩下的部分被丢弃了。如果不指定这个参数,E2BIG 将被返回,而消息则留在队列中不     被取出。


#include<stdio.h>
#include<errno.h>
#include<unistd.h>
#include<string.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<stdlib.h>
typedefstruct
{
long int msg_type;
unsigned char text[255];
}st_msg;
 
#defineIPCKEY 0x111
intmain(void)
{
int msgid = 0;
unsigned char r_buf[20];
unsigned char w_buf[20];
key_t key = 0;
pid_t pid = 0;
st_msg msgdata={0,{0}};
//memset(msgdata,0,sizeof(msgdata));
 
key = ftok("/dev/null",IPCKEY);
msgid = msgget(key,IPC_CREAT|0660);
if(msgid == -1)
{
if(errno != EEXIST)
perror("msgget invalid\n");
}
pid = fork();
if(pid == 0)
{
 
long int msg_type_child = 2;
st_msg msg_child={0,{0}};
//memset(msg_child,0,sizeof(msg_child));
sleep(2);
printf("This is a Child prosess\n");
if(msgrcv(msgid,(void*)&msg_child,sizeof(msg_child)-sizeof(long),msg_type_child,IPC_NOWAIT)<0)
{
perror("msgrcv invalid\n");
exit(2);
}
printf("the second num is %d\n",msg_child.text[0]);
 
msg_type_child=1;
if(msgrcv(msgid,(void*)&msg_child,sizeof(msg_child)-sizeof(long),msg_type_child,IPC_NOWAIT)<0)
{
perror("msgrcv invalid\n");
exit(2);
}
printf("the first num is %d\n",msg_child.text[0]);
exit(1);
 
}
else if(pid >0)
{
long int msg_type_parent = 0;
st_msg msg_parent={0,{0}};
//memset(msg_parent,0,sizeof(msg_parent));
 
msg_parent.msg_type = 1;
msg_parent.text[0]=2;
msg_parent.text[1]=3;
 
printf("This is a Parent process to send the first num,the numis %d\n",msg_parent.text[0]);
if(msgsnd(msgid,(void*)&msg_parent,sizeof(msg_parent)-sizeof(long),IPC_NOWAIT)<0)
{
perror("msgsnd invalid\n");
exit(1);
}
msg_parent.msg_type = 2;
msg_parent.text[0]=3;
msg_parent.text[1]=4;
 
printf("This is a Parent process to send second num,the num is%d\n",msg_parent.text[0]);
if(msgsnd(msgid,(void*)&msg_parent,sizeof(msg_parent)-sizeof(long),IPC_NOWAIT)<0)
{
perror("msgsnd invalid\n");
exit(1);
}
//sleep(2);
 
wait();
 
}
else
printf("Fork invalid\n");
 
if(msgctl(msgid,IPC_RMID,0)==-1)
{
perror("msgctl IPC_RMIDinvalid\n");        
}
return 0;
}

运行结果

Machine generated alternative text: This is a Parent process to send the first nun,the nun is 2This is a Parent process to send second nun,the nun is 3This is a Child prosessthe second nun is 3the first nun is 2

分析:

父进程发送两个消息,消息type有两种,一个是type=1,一个是type=2,子进程接受消息,根据设置的

信号msg_type_child接受,在msg_type_child=1时,挑选出消息队列中type=1的信息。由于父进程首先结束,为避免僵尸进程的形成,在父进程中wait等待子进程结束



参考:http://lobert.iteye.com/blog/1743256


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值