进程间通信之IPC 对象:
IPC: 进程间通信
IPC对象: 内核维护的一组共享数据对象;
消息队列对象 共享内存对象 信号量集对象
IPC 通用操作框架:
创建key值 》申请IPC对象 》打开对象》读写对象》
关闭对象 ==》卸载对象
1、唯一key值的创建:
1.1 私有键值 ==》IPC_PRIVATE 只给亲缘关系进程使用;
1.2 临时键值 ==》ftok() 临时创建键值
1.3 自定义键值 ==》 0x12345678 0x888 0x666
#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);
功能:该函数可以根据指定的路径和id唯一生成一个key值;
参数: pathname 指定一个不能被删除重建的路径
id 指定一个128 以内的任意数字;
返回值:成功 唯一key值
失败 -1;
2、消息队列操作框架:
申请/打开消息队列对象 ===》读写对象 ===》卸载对象
msgget() msgsnd() msgctl()
msgrcv()
#include <sys/msg.h>
int msgget(key_t key, int msgflg);
功能:该函数可以根据key值向操作系统内核提出消息队列使用申请;
参数:key 唯一键值
msgflg 申请消息队列的方式以及权限
如果是第一次申请用IPC_CREAT 来创建对象
如果不是第一次申请用IPC_EXCL 来检测判断
权限使用八进制的默认权限
返回值:成功 msgid 的消息队列对象id
失败 -1
注意要验证申请的对象是否创建成功可以通过一下shell命令查看;
ipcs -a ===> 可以查看所有IPC对象信息
ipcs -q ====》只查看消息队列对象信息
删除:
ipcrm -q msgid
eg: ipcrm -q 0
读写消息队列:===》进程间通信
写操作:msgsnd()
int msgsnd(int msqid, const void msgp, size_t msgsz, int msgflg);
功能:该函数可以将指定的格式的数据写入目标消息队列对象中。
参数:msqid 要存储消息的消息队列id
msgp 要存储消息的消息格式,一般如下格式:
struct msgbuf {
long mtype; / message type, must be > 0 /
char mtext[128]; / message data */
};
msgsz 要存储消息的大小,一般是参数2的大小
msgflg 存储消息的方式,0 表示阻塞存储,IPC_NOWAIT 表示非阻塞;
返回值:成功 0
失败 -1;
读操作: msgrcv()
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,
int msgflg);
功能:该函数可以从指定的消息队列对象中获取数据到本地内存。
参数: msqid 消息队列id
msgp 获取消息后存储到本地的本地内存,一般和发送数据结构一样;
msgsz 预计获取数据的长度
msgtyp 要获取数据的类型
msgflg 获取数据的方式,0 表示阻塞获取;
返回值:成功 返回实际获取的数据长度
失败 -1;
删除消息队列对象: msgctl
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
功能:该函数可以修改指定消息队列的属性,也可以删除消息队列;
属性一般不做调整,多用于删除操作。
参数:msqid 要删除的目标消息队列id
cmd IPC_RMID 表示删除消息队列
buf NULL 表示属性不做调整;
返回值:成功 0
失败 -1;
//消息队列接受消息
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <errno.h>
#define SIZE sizeof(struct msgbuf)-sizeof(long)
struct msgbuf
{
long mtype;
//消息正文
int a;
char b;
};
int main()
{
//获得key值
key_t key;
if(key=ftok(".",'q')<0)
{
perror("key error\n");
return -1;
}
//创建获打开消息队列
int msqid;
struct msgbuf msgbuf;
if(msqid=msgget(key,IPC_CREAT|IPC_EXCL|0664)<0)
{
if(errno!=EEXIST)
{
perror("msgget error\n");
return -1;
}
else
{
//如果存在,则打开消息队列
msqid=msgget(key,0664);
}
}
//接受消息
msgrcv(msqid,&msgbuf,SIZE,100,0);
printf("a=%d b=%c\n",msgbuf.a,msgbuf.b);
//删除消息队列
msgctl(msqid,IPC_RMID,NULL);
system("ipcs -q");
return 0;
}
//消息队列发送消息
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#define SIZE sizeof(struct msgbuf)-sizeof(long)
struct msgbuf
{
long mtype;
//消息正文
int a;
char b;
};
int main()
{
//获得key值
key_t key;
if(key=ftok(".",'q')<0)
{
perror("key error\n");
return -1;
}
//创建获打开消息队列
int msqid;
struct msgbuf msgbuf;
if(msqid=msgget(key,IPC_CREAT|IPC_EXCL|0664)<0)
{
if(errno!=EEXIST)
{
perror("msgget error\n");
return -1;
}
else
{
//如果存在,则打开消息队列
msqid=msgget(key,0664);
}
}
msgbuf.mtype=100;
msgbuf.a=10;
msgbuf.b='q';
msgsnd(msqid,&msgbuf,SIZE,0);
system("ipcs -q");
return 0;
}