消息队列、共享内存、信号量集
【1】命令
ipcs -l 查看IPC对象的属性
ipcs -m 查看共享内存的标识符
ipcs -q 查看消息队列的标识符
ipcs -s 查看信号灯集的标识符
ipcrm -m 删除共享内存的标识符
ipcrm -q 删除消息队列的标识符
ipcrm -s 删除信号灯集的标识符
【2】key值:相当于ipc对象通信的外部名字
#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);
功能:获得key值,用于system V中的IPC通信
参数:pathname 文件名(要求文件必须存在)
proj_id 整形值(低八位不能为0,所以一般用一个字符)
返回值:成功返回key值,失败-1
【3】消息队列
一个消息的列表,用户可以在消息队列中添加信息,读取信息
编写流程:
1.创建或者打开消息队列
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int msgflg);
功能:创建或打开一个消息队列
参数:key ftok获得的key值
msgflg 打开的方式
IPC_CREAT 创建
IPC_EXCL 如果存在报错
0666
返回值:成功返回消息队列的id,失败返回-1
2.添加消息-》入队
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
功能:向消息队列中添加一条消息(入队操作)
参数:msqid id,msgget获得的
msgp 要发送的消息的地址
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[64]; /* message data */
};
msgsz 消息正文的大小
msgflg 0 如果队列满了,它会阻塞等到
IPC_NOWAIT 如果队列满了,以非阻塞的方式发送
返回值:成功返回0 失败-1
3.读取消息
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,
int msgflg);
功能:读取消息(出队操作)
参数:msqid id,msgget获得的
msgp 读到数据存放的地址(一定要和发送的地址长的一样)
msgsz 消息正文的大小
msgtyp 消息的类型
0 表示从第一个开始读取,按队列的规则
>0 按指定的消息类型进行读取
<0 表示读取小于他的绝对值相等的类型按类型从小到大读取
比如-400,它会按一下顺序读取
300 100 200 400 100
4 1 3 2
msgflg 0 如果队列空了,它会阻塞等待
IPC_NOWAIT 如果队列空了,直接结束
返回值:成功返回正文的大小,失败-1
4.控制消息队列
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
功能:控制消息队列
参数:msqid id,msgget获得的
cmd 决定了该函数的功能
IPC_STAT 表示要获取消息队列的属性,存在第三个参数中
IPC_SET 表示要设置消息队列的属性,属性存在第三个参数中
IPC_RMID 删除消息队列,此时第三个参数为NULL
buf 详见上方
返回值: 成功0 失败-1
【4】共享内存
1.共享内存是一个最为高效的进程间通信方式,进程可以直接读写内存
2.共享内存使用过程需要注意(打架),需要通过同步、互斥来解决
编写流程:
1.ftok获得key值
2.创建或者打开一个共享内存
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
功能:创建或者打开一个共享内存
参数:key ftok获得key值
size 共享内存的大小
shmflg IPC_CREAT IPC_EXCL
返回值:返回共享内存的id,失败-1
3.共享内存的映射:把指定的共享内存映射到进程的用户空间
void *shmat(int shmid, const void *shmaddr, int shmflg);
功能:共享内存的映射
参数:shmid 共享内存的id
shmaddr 表示映射到进程的地址,一般用NULL,让系统自动匹配
shmflg 0 可读可写
SHM_RDONLY 可读
返回值:成功返回映射的地址,失败(void *)-1
4.取消共享内存的映射
int shmdt(const void *shmaddr);
参数:shmaddr 共享内存映射完的地址
返回值:成功返回0 失败-1
4.共享内存的控制
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
功能:共享内存的控制
参数:shmid 共享内存的id
cmd 决定了该函数的功能
IPC_STAT 表示要获取共享内存的属性,存在第三个参数中
IPC_SET 表示要设置共享内存的属性,属性存在第三个参数中
IPC_RMID 删除共享内存,此时第三个参数为NULL
buf 详见上方
返回值:成功0 失败-1
【5】信号灯集
信号灯集也叫做信号量;一般和共享内存一起使用
编写流程:
1.ftok获得key值
2.创建或者打开一个信号灯集
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semget(key_t key, int nsems, int semflg);
功能:创建或者打开一个信号灯集
参数:key ftok获得key值
nsems 要创建的信号量的个数
semflg IPC_CREAT IPC_EXCL
返回值:成功返回semid,失败返回-1
3.初始化、P、V
初始化:
int semctl(int semid, int semnum, int cmd, ...);
功能:控制一个信号灯集
参数:semid 信号灯的id
semnum 要对第几个信号灯进行操作,编号从0开始
cmd IPC_STAT
IPC_SET
IPC_RMID
SETVAL 初始化,此时需要第四个参数
union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux-specific) */
};
GETVAL 获得信号量的值
返回值:失败-1
P、V操作
int semop(int semid, struct sembuf *sops, unsigned nsops);
功能:进行P、V操作
参数:semid 信号灯集id
sops 结构体指针
struct sembuf{
unsigned short sem_num; /* semaphore number */
short sem_op; /* semaphore operation */
0 等待,直到信号量的值变为0
>0 释放资源,V操作
<0 申请资源,P操作
short sem_flg; /* operation flags */
0 以阻塞的方式进行操作
IPC_NOWAIT 以非阻塞的方式
};
nsops 执行一次,要操作的信号灯的个数
返回值:成功返回0 失败返回-1
4.删除
详见semctl
【总结】
1.标准IO、文件IO
2.进程
3.线程
4.线程的同步与互斥
5.无名管道、有名管道、信号--传统间的通信方式
6.消息队列、共享内存、信号量集--system V IPC