1 基于消息队列的进程间通信
2 基于共享内存的进程间通信
3 基于信号量的进程间通信
1 基于消息队列的进程间通信
1.1 问题
消息队列是一个由系统内核负责存储和管理,并通过消息队列标识符引用的消息链表。相较于其它几种IPC机制,消息队列具有明显的优势。
1.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:进程A
代码如下所示:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/stat.h>
#include <sys/msg.h>
#define MSG_FILE “/home/tarena/server.c”
#define BUFFER 255
#define PERM S_IRUSR|S_IWUSR
struct msgtype
{
long mtype;
char buffer[BUFFER+1];
};
int main()
{
struct msgtype msg;
key_t key;
int msgid;
if((key=ftok(MSG_FILE,‘a’))-1)
{
perror(“Creat Key Error”);
exit(1);
}
if((msgid=msgget(key,PERM | IPC_CREAT | IPC_EXCL))-1)
{
perror("Creat Message Error ");
exit(1);
}
while(1)
{
msgrcv(msgid, &msg, sizeof(struct msgtype), 1,0);
printf(“Server Receive:%s\n”,msg.buffer);
msg.mtype=2;
msgsnd(msgid,&msg,sizeof(struct msgtype),0);
}
return 0;
}
上述代码中,以下代码:
if((key=ftok(MSG_FILE,‘a’))==-1)
{
perror(“Creat Key Error”);
exit(1);
}
使用函数ftok获取key值,该函数有两个参数,说明如下:
第一个参数为指定的文件名,该文件必须是存在而且可以访问的。
第二个参数为子序号,虽然为int,但是只有8个比特被使用(0-255)。
上述代码中,以下代码:
if((msgid=msgget(key,PERM | IPC_CREAT | IPC_EXCL))==-1)
{
perror("Creat Message Error ");
exit(1);
}
使用函数msgget创建新的或获取已有的消息队列。该函数有两个参数,说明如下:
第一个参数为消息队列键。
第二个参数为创建标志,可取以下值:
0 - 获取,不存在即失败
IPC_CREAT - 创建,不存在即创建,已存在即获取
IPC_EXCL - 排斥,已存在即失败
上述代码中,以下代码:
msgrcv(msgid, &msg, sizeof(struct msgtype), 1,0);
使用函数msgrcv接收消息,该函数有五个参数,说明如下:
第一个参数为消息队列标识符。
第二个参数为指向一块包含消息类型(4字节)和消息数据的内存。
第三个参数为期望接收消息数据(不含消息类型)的字节数。
第四个参数为消息类型,可取以下值:
0 - 提取消息队列的第一条消息。
0 - 若msgflg参数不包含MSG_EXCEPT位,则提取消息队列的第一条类型为msgtyp的消息;若msgflg参数包含MSG_EXCEPT位,则提取消息队列的第一条类型不为msgtyp的消息。
<0 - 提取消息队列中类型小于等于msgtyp的绝对值的消息,类型越小的消息越被优先提取。
第五个参数为接收标志,一般取0即可。
上述代码中,以下代码:
msgsnd(msgid,&msg,sizeof(struct msgtype),0);
使用函数msgsnd发送消息,该函数有四个参数,说明如下:
第一个参数为消息队列标识符。
第二个参数为指向一个包含消息类型和消息数据的内存块。该内存块的前4个字节必须是一个大于0的整数,代表消息类型,其后紧跟消息数据。消息数据长度用msgsz参数表示。
第三个参数为期望发送消息数据(不含消息类型)的字节数。
第四个参数为发送标志,一般取0即可。
步骤二:进程B
代码如下所示:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/stat.h>
#define MSG_FILE “/home/tarena/server.c”
#define BUFFER 255
#define PERM S_IRUSR|S_IWUSR
struct msgtype
{
long mtype;
char buffer[BUFFER+1];
};
int main(int argc,char **argv)
{
struct msgtype msg;
key_t key;
int msgid;
if((key=ftok(MSG_FILE,‘a’))-1)
{
perror(“Creat Key Error”);
exit(1);
}
if((msgid=msgget(key,PERM))-1)
{
perror(“Creat Message Error”);
exit(1);
}
msg.mtype=1;
strcpy(msg.buffer, “这是客户端发出的消息内容”);
msgsnd(msgid, &msg, sizeof(struct msgtype), 0);
memset(&msg, ‘\0’, sizeof(struct msgtype));
msgrcv(msgid, &msg, sizeof(struct msgtype),2,0);
printf(“Client receive:%s\n”,msg.buffer);
return 0;
}
上述代码中,以下代码:
if((key=ftok(MSG_FILE,‘a’))==-1)
{
perror(“Creat Key Error”);
exit(1);
}
使用函数ftok获取key值,该函数有两个参数,说明如下:
第一个参数为指定的文件名,该文件必须是存在而且可以访问的。
第二个参数为子序号,虽然为int,但是只有8个比特被使用(0-255)。
上述代码中,以下代码:
if((msgid=msgget(key,PERM))==-1)
{
perror(“Creat Message Error”);
exit(1);
}
使用函数msgget获取已有的消息队列。
上述代码中,以下代码&