1. IPC对象
IPC对象主要指三种进程间通信机制:消息队列、共享内存、信号灯集
优点:创建IPC对象后,在当前系统中所有进程都是可见的。
2. 查看IPC对象命令
使用ipcs
查看当前ipc对象
ipcs 查看所有的ipc对象
-q 查看消息队列
-m 查看共享内存
-s 查看信号量
ipcrm 删除ipc对象
ipcrm –q msqid 删除指定的消息队列
3. 消息队列
3.1 概念
- 消息队列是IPC对象的一种
- 消息队列由消息队列ID来唯一标识
- 消息队列就是一个消息的列表。用户可以在消息队列中添加消息、读取消息等。
- 消息队列可以按照类型来发送/接收消息
3.2 相关函数
3.2.1 msgget() 创建或者打开消息队列
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int msgflg);
功能:
创建或者打开一个消息队列,得到消息队列id
参数:
key:键值,唯一的键值确定唯一的消息队列
如何设置键值:
自己直接定义一个键值
使用ftok函数获取键值
msgflg:标志位
一般设置为 IPC_CREAT | 0777
返回值:
成功:消息队列id
失败:-1
3.2.2 ftok() 获取键值
#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);
功能:
获取键值
参数:
pathname:路径名
proj_id:自定义的值,只取前八位
返回值:
成功:键值
失败:-1
3.2.3 msgctl() 控制消息队列
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
功能:
控制一个消息队列
参数:
msqid:消息队列id
cmd:具体控制
IPC_STAT 获取消息队列属性信息
IPC_SET 设置消息队列属性信息
IPC_RMID 删除一个消息队列
msqid_ds:消息队列属性结构体
返回值:
成功:0
失败:-1
3.2.4 msgsnd() 向消息队列写信息
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
功能:向一个消息队列中写入数据
参数:
msqid:消息队列id
msgp:要写入的数据,需要自己定义一个结构体
struct msg_buf{
//消息类型,必须有且类型也不能变
// 用于读取数据时,可以指定消息的类型来读取
long type;
//消息正文具体要写入的数据,大小自己定义,类型也可以自定义
char mtext[32];
};
msgsz:消息正文的大小,就是mtext的大小,一定不是第二个参数的大小
msgflg:标志位
0 阻塞
IPC_NOWAIT 非阻塞
返回值:
成功:0
失败:-1
3.2.5 msgrcv() 从消息队列读
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz,
long msgtyp, int msgflg);
功能:从消息队列中读取数据
参数:
msqid:消息队列id
msgp:保存读取的数据
msgsz:消息正文大小
msgtyp:消息类型
0 按照顺序读取一个消息
>0 按照顺序读取第一个消息类型为当前参数的消息
<0 按照顺序读取第一个消息类型小于等于这个参数的绝对值的类型的消息
msgflg:标志位
0 阻塞
IPC_NOWAIT 非阻塞
返回值:
成功:接收到的数据的大小
失败:-1
3.3 消息队列 示例
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
typedef struct{
long type;
int id;
char name[32];
int score;
}MSG;
#define DATASIZE (sizeof(MSG) - sizeof(long))
int main(int argc, char const *argv[])
{
//使用ftok函数获取键值
key_t key;
if((key = ftok(".", 1000)) == -1)
{
perror("ftok error");
exit(1);
}
//ftok函数获取的健值就是
//这个函数的第二个参数的后8位 ↓
//和 第一个参数对应文件的设备号的后8位 ↓
//以及这个文件inode号的后16位 ↓
//共同组成键值
// printf("key = %#x\n", key);
// struct stat mystat;
// stat(".", &mystat);
// printf("dev_num = %x\n", mystat.st_dev);
// printf("inode = %x\n", mystat.st_ino);
// printf("1000 = %#x\n", 1000);
//创建一个消息队列
int msgid;
if((msgid = msgget(key, IPC_CREAT | 0777)) == -1)
{
perror("msgget error");
exit(1);
}
puts("--------------------------------------------")