System VIPC机制主要由消息队列、信号量和共享内存3种机制。
使用ipcs命令可以查看当前系统正在使用的IPC;
创建IPC结构,需指定一个关键字(key),关键字的数据类型由系统规定key_t,通常在头文件<sys/types.h>中被规定为长整型。
一、消息队列
消息队列是消息的链接表,存放在内核中,并由消息队列标识符标识。
消息队列需要两种类型的数据结构:
1)msqid_ds:标识整个消息队列的基本情况,包括队列的权限、拥有者和操作权限等,还有两个指针,分别指向队列的第一个消息和最后一个消息。
2)msg:整个队列的主体,一个队列有若干消息,每个msg结构基本属性包括消息类型、消息大小、消息内容指针和下一个msg的位置。
msg的结构体如下:
struct msg_msg{
struct list_head m_list;
long m_type;
int m_ts;
struct msg_msgseg *next;
void *security;
}
用msgget创建或打开消息队列:
头文件:<sys/msg.h>
int msgget(key_t key ,int flag)
key为IPC的可能取值
flag的低位用来确定消息队列的访问权限,如0666=rw-rw-rw
用msgctl对消息队列属性进行控制
头文件:<sys/msg.h>
int msgctl(int msqid,int cmd,struct msqid_ds *buf);
若成功则为0,出错则为-1
下面为两段代码
receive为接收端,接收send发来的消息
send为发送端,向receive发送消息
编译时需要启动两个终端同时编译
/*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(int type){
struct msgstru msgs;
int msgid,ret_value;
char str[512];
while(1){
msgid = msgget(MSGKEY,IPC_EXCL );/*检查消息队列是否存在 */
if(msgid < 0){
printf(".\n");//msq not existed! errno=%d [%s]\n",errno,(char *)strerror(errno));
sleep(2);
continue; //continue break 两者区别
}
/*接收消息队列*/
ret_value = msgrcv(msgid,&msgs,sizeof(struct msgstru),type,0);
printf("text=[%s] pid=[%d]\n",msgs.msgtext,getpid());
}
return;
}
void main()
{
int i,cpid;
/* create 2 child process */
for (i=1;i<=2;i++)
{
cpid = fork();
if (cpid < 0)
printf("fork failed\n");
else if (cpid ==0) /*child process*/
{
printf("pid=%d,type=%d",getpid(),i);
childproc(i);
}
}
}
/*send.c*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <errno.h>
#include <stdlib.h>
//IPC可能取值
#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,(char *)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拷贝函数
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,(char *)strerror(errno));
exit(-1);
}
}
msgctl(msqid,IPC_RMID,0); //删除消息队列
}