当前位置: 技术问答>linux和unix
利用消息队列在进程间通信
来源: 互联网 发布时间:2016-10-31
本文导语: 以下代码利用消息队列在进程间通信,可 client 无法接收消息。麻烦各位给一下意见 #include #include #include #include #include #include #include #include #define MSGKEY 75 struct msgform { long mtype; char mtext[250]...
以下代码利用消息队列在进程间通信,可 client 无法接收消息。麻烦各位给一下意见
#include
#include
#include
#include
#include
#include
#include
#include
#define MSGKEY 75
struct msgform
{
long mtype;
char mtext[250];
} msg;
int msgqid,pid,*pint,i;
void client()
{
msgqid=msgget(MSGKEY,0777); /*打开75#消息队列*/
pid=getpid();
pint=(int *)msg.mtext;
*pint=pid;
msg.mtype=1; /*消息类型为1*/
printf("%sn", msgsnd(msgqid,&msg,sizeof(int),0) );//到这里不知道为什么无法继续,下一行语句没有执行
printf("errorn");
while ( 1){ /*接收消息*/
if( msgrcv(msgqid,&msg,250,pid,0) == -1)
printf("errorn");
else {
printf("(client):receive reply from pid=%dn",*pint); /*显示server进程标识数*/
exit(0);
}
}
}
void server( )
{
while(1){
msgqid=msgget(MSGKEY,0777|IPC_CREAT); /*创建75#消息队列*/
if( msgrcv(msgqid,&msg,250,1,0) != -1){ /*接收消息*/
pint=(int *)msg.mtext; /*把正文的内容传给pint,并强制转换类型*/
pid=*pint; /*获得cilent进程标识数*/
printf("(server):serving for client pid=%dn",pid);
msg.mtype=pid; /*消息类型为client进程标识数*/
*pint=getpid(); /*获取server进程标识数*/
while( msgsnd(msgqid,&msg,sizeof(int),0) != -1) /*发送消息*/
printf("server errorn");
exit(0);
}
}
}
int main()
{
int status, i =0;
while((i=fork())==-1); //创建进程1
if( i==0 )server();
while((i=fork())==-1); //创建进程2
if( i==0 ) client();
wait(0);
wait(0);
exit(0);
}
|
在server( )函数中:
while( msgsnd(msgqid,&msg,sizeof(int),0) != -1) /*发送消息*/
printf("server errorn");
exit(0);
这个地方错误,应该是:
while( msgsnd(msgqid,&msg,sizeof(int),0) == -1) /*发送消息*/
{ printf("server errorn"); }
exit(0);
只有当msgsnd()不成功时才继续重新发送数据,如果按照原来的程序,那就是msgsnd()成功时又立即重新发送数据。在程序第一次运行时,因为新建的消息队列是空的,那么msgsnd()是会成功的,不过msgsnd()不断重新发数据,这个消息队列很快被填满,导致没有空间再让往里面发数据了,并且消息队列里面消息的类型为type = server的PID。此时msgsnd()阻塞(注意不是出错)。
再来看client()程序部分,由于:
else {
printf("(client):receive reply from pid=%dn",*pint); /*显示server进程标识数*/
exit(0);
}
即一旦client第一次收到server的PID就退出,此时server会再发一条消息到消息队列,而且类型为type = server的PID。此后server再次阻塞。
到此为止,你的程序也输出了一大堆server error,并且不再有什么反应了,为了结束程序,你很可能是Ctrl+C强制退出。注意,当你退出的时候,由于整个程序没有调用删除原来消息队列的语句,所以,即使你程序退出了,原来的消息队列还是存在的。
为了验证程序,你有可能又重新运行了程序,此时原来的消息队列还是存在的,并且由于第一次运行,导致了这个消息队列处于被填满状态,没有空间再让往里面发数据了,另外这些消息的类型都为type = server的PID。
接下来,程序运行到server里面的
if( msgrcv(msgqid,&msg,250,1,0) != -1){ /*接收消息*/
语句,这里想要接收的消息类型为type = 1,但是消息队列里面没有type = 1的消息,所以,server在这条语句阻塞。
再看client进程,运行到
msgsnd(msgqid,&msg,sizeof(int),0);
语句,由于消息队列处于被填满状态,没有空间再让往里面发数据了,那么这条语句也处于阻塞状态,从而整个程序都处于阻塞状态了,也就是你看到的程序无法执行了。
为了验证消息队列处于被填满状态,我们在终端执行ipcs –q命令,得到:
------ Message Queues --------
key msqid perms used-bytes messages
0x0000004b 458752 777 16384 4096
果然,消息队列里已经有了4096条消息,占16384字节。
下面对整个程序进行了修改,修改程序如下:
while( msgsnd(msgqid,&msg,sizeof(int),0) != -1) /*发送消息*/
printf("server errorn");
exit(0);
这个地方错误,应该是:
while( msgsnd(msgqid,&msg,sizeof(int),0) == -1) /*发送消息*/
{ printf("server errorn"); }
exit(0);
只有当msgsnd()不成功时才继续重新发送数据,如果按照原来的程序,那就是msgsnd()成功时又立即重新发送数据。在程序第一次运行时,因为新建的消息队列是空的,那么msgsnd()是会成功的,不过msgsnd()不断重新发数据,这个消息队列很快被填满,导致没有空间再让往里面发数据了,并且消息队列里面消息的类型为type = server的PID。此时msgsnd()阻塞(注意不是出错)。
再来看client()程序部分,由于:
else {
printf("(client):receive reply from pid=%dn",*pint); /*显示server进程标识数*/
exit(0);
}
即一旦client第一次收到server的PID就退出,此时server会再发一条消息到消息队列,而且类型为type = server的PID。此后server再次阻塞。
到此为止,你的程序也输出了一大堆server error,并且不再有什么反应了,为了结束程序,你很可能是Ctrl+C强制退出。注意,当你退出的时候,由于整个程序没有调用删除原来消息队列的语句,所以,即使你程序退出了,原来的消息队列还是存在的。
为了验证程序,你有可能又重新运行了程序,此时原来的消息队列还是存在的,并且由于第一次运行,导致了这个消息队列处于被填满状态,没有空间再让往里面发数据了,另外这些消息的类型都为type = server的PID。
接下来,程序运行到server里面的
if( msgrcv(msgqid,&msg,250,1,0) != -1){ /*接收消息*/
语句,这里想要接收的消息类型为type = 1,但是消息队列里面没有type = 1的消息,所以,server在这条语句阻塞。
再看client进程,运行到
msgsnd(msgqid,&msg,sizeof(int),0);
语句,由于消息队列处于被填满状态,没有空间再让往里面发数据了,那么这条语句也处于阻塞状态,从而整个程序都处于阻塞状态了,也就是你看到的程序无法执行了。
为了验证消息队列处于被填满状态,我们在终端执行ipcs –q命令,得到:
------ Message Queues --------
key msqid perms used-bytes messages
0x0000004b 458752 777 16384 4096
果然,消息队列里已经有了4096条消息,占16384字节。
下面对整个程序进行了修改,修改程序如下:
#include
#include
using namespace std;
#include
#include
#include
#include
#include
#include
#include
#include
#define MSGKEY 75
//#define MSGKEY (ftok("/tmp",0x57)) //用这样的方式也可以
struct msgform
{
long mtype;
char mtext[250];
} msg;
int msgqid,pid,*pint,i;
void client()
{
msgqid=msgget(MSGKEY,0777); /*打开75#消息队列*/
cout