IPC对象也是在内核空间开辟区域,每一种IPC对象创建好之后都会将其设置为全局,并且
会给其分配一个编号,只要找到唯一的这个编号就可以进行通信,所以不相关的进程可以通
过IPC对象通信。
IPC对象创建好之后,会在当前系统中可见,只要不删除或者不关闭系统,就会一直存在。
查看已经创建的IPC对象:
ipcs
查看当前系统中所有创建的
IPC
对象
ipcs ‐q
查看创建的消息队列
ipcs ‐m
查看创建的共享内存
ipcs ‐s
查看信号量
ipcrm
删除
IPC
对象
例如:
ipcrm ‐q msqid
删除标号为
msqid
的消息队列
2、消息队列的概述
2.1 消息队列的概念
消息队列是消息的链表,存放在内存中,由内核维护
消息队列的特点
1、消息队列中的消息是有类型的。
2、消息队列中的消息是有格式的。
3、消息队列可以实现消息的随机查询。消息不一定要以先进先出的次序读取,编程时可以
按消息的类型读取
4、消息队列允许一个或多个进程向它写入或者读取消息。
5、与无名管道、命名管道一样,从消息队列中读出消息,消息队列中对应的数据都会被删
除。
6、每个消息队列都有消息队列标识符,消息队列的标识符在整个系统中是唯一的。
7、只有内核重启或人工删除消息队列时,该消息队列才会被删除。若不人工删除消息队
列,消息队列会一直存在于系统中。
在ubuntu 12.04中消息队列限制值如下:
每个消息内容最多为8K字节
每个消息队列容量最多为16K字节
系统中消息队列个数最多为1609个
系统中消息个数最多为16384个
System V提供的IPC通信机制
需要一个key值,
通过key值就可在系统内获得一个唯一的消
息队列标识符
。
key值可以是人为指定的,也可以通过ftok函数获得。
如果多个进程想通过IPC对象通信,则必须找到唯一的标识,而唯一的标识是由key决定
的,所以只要key知道,则就可以实现多个进程通信
(另外,Posix IPC的操作稍有不同,后面补充)
2.2 ftok函数
ftok - convert a pathname and a project identifier to a System V IPC key
#include
#include
key_t ftok
(
const char *pathname, int proj_id
);
功能:通过文件名和目标值共同创造一个键值并返回值
参数:
pathname
:任意一个文件名(文件名或者目录名)
proj_id:目标值,范围一般是
0~127
返回值:
成功:键值
失败:
‐1
如果使用
ftok
函数获取键值,得到的键值是由
ftok
的第一个
参数对应文件的信息和第二个参数一起决定的
int main(int argc, char const *argv[])
mykey = ftok("test",666);
printf("mykey = %#x\n", mykey);
3、消息队列操作
3.1创建消息队列 -- msgget()
#include
#include
#include
int msgget
(
key_t key, int msgflg
);
功能:创建一个消息队列,得到消息队列的
id
参数:
key
:键值,唯一的键值确定唯一的消息队列
方法
1
:任意指定一个数
方法
2
:使用
ftok
函数获取键值
msgflg
:消息队列的访问权限,
一般设置为
IPC_CREAT
|
IPC_EXCL
|
0777
或者
IPC_CREAT
|
0777
返回值:
成功:消息队列的
id
失败:‐1
查看消息队列
ipcs ‐q
删除消息队列
ipcrm ‐q msqid
测试msgget
int main(int argc, char const *argv[])
mykey = ftok("test", 666);
printf("mykey = %#x\n", mykey);
msgid = msgget(mykey, IPC_CREAT | 0666);
perror("fail to msgget");
printf("msgid = %d\n", msgid);
3.2 发送消息-- msgsnd()
#
include
#
include
#
include
int
msgsnd
(
int
msqid
,
const void
*
msgp
,
size_t msgsz
,
int
msgflg
);
功能:向指定的消息队列发送数据(写操作)
参数:
msqid
:
消息队列的id
msgp
:
要写入的数据,需要自己定义结构体
struct
struct_name
{
long
mtype
;
//
消息的编号,必须大于
0
char
mtext
[
128
];
//
消息正文,可以定义多个成员
...
}
msgsz
:消息正文的大小,不包括消息的编号长度
msgflg
:标志位
0
阻塞
IPC_NOWAIT
非阻塞
返回值:
成功:
0
失败:
‐
1
#define MSG_SIZE (sizeof(MSG)-sizeof(long))
int main(int argc, char const *argv[])
mykey = ftok("test", 666);
printf("mykey = %#x\n", mykey);
msgid = msgget(mykey, IPC_CREAT | 0666);
perror("fail to msgget");
MSG msg1 ={1,"hello world"};
if(msgsnd(msgid,&msg1,MSG_SIZE,0)==-1){
if(msgsnd(msgid,&msg2,MSG_SIZE,0)==-1){
if(msgsnd(msgid,&msg3,MSG_SIZE,0)==-1){
if(msgsnd(msgid,&msg4,MSG_SIZE,0)==-1){
3.3 消息接收--msgrcv()
#
include
#
include
ssize_t
msgrcv
(
int
msqid
,
void
*
msgp
,
size_t msgsz
,
long
msgtyp
,
int
msgflg
);
功能:从消息队列中接收数据(读操作),接收的数据会从消息队列中删除
参数:
msqid
:
消息队列id
msgp
:
保存接收到的数据的结构体
struct
struct_name
{
long
mtype
;
//
消息的编号,必须大于
0
char
mtext
[
128
];
//
消息正文,可以定义多个成员
}
msgsz
:
消息正文的大小
msgtyp
:设置要接收哪个消息
0
按照写入消息队列的顺序依次读取
>
0
只读取消息队列中消息编号为当前参数的第一个消息
<
0
只读取消息队列中小于等于当前参数的绝对中内最小的第一个消息
msgflg
:标志位
0
阻塞
IPC_NOWAIT
非阻塞
返回值:
成功:接收到的消息正文的长度
失败:
‐
1
#define MSG_SIZE (sizeof(MSG)-sizeof(long))
int main(int argc, char const *argv[])
mykey = ftok("test", 666);
printf("mykey = %#x\n", mykey);
msgid = msgget(mykey, IPC_CREAT | 0666);
perror("fail to msgget");
if(msgrcv(msgid, &msg, MSG_SIZE, -3, 0) == -1)
perror("fail to msgrcv");
printf("recv_msg = %s\n", msg.msg_text);