共享内存:
基础特点:
两个或多个进程之间共享一块由内核统一管理的内存,该内存可以与多个进程的虚拟内存进行映射
优点:不需要复制任何信息,直接读写内存,是最快的一种IPC机制
缺点:需要考虑同步访问的问题,一般使用信号
int shmget(key_t key, size_t size, int shmflg);
功能:创建\获取一块共享内存
key: IPC键值(独一无二)
size: 共享内存的大小,获取共享内存时此参数无意义,一般给0
shmflg:
IPC_CREAT 创建共享内存,如已存在直接获取
IPC_EXCL 共享内存已存在,返回失败
获取时直接给0
注意:如果是创建共享内存还需要额外提供共享内存的权限
例如: IPC_CREAT|0664
返回值: IPC标识符,失败-1
void *shmat(int shmid, const void *shmaddr, int shmflg);
功能:虚拟内存与共享内存进行映射
shmid:IPC标识符 shmget的返回值
shmaddr: 想要映射的虚拟内存首地址,为NULL时系统会自动分配地址
shmflag:
SHM_RDONLY 以只读方式映射共享内存
SHM_RND: 只有shmaddr参数不为NULL时才能有效,表示从shmaddr开始向下以整数页方式映射
返回值:与共享内存映射成功后的虚拟内存首地址,失败返回(void *) -1
int shmdt(const void *shmaddr);
功能:取消映射
shmaddr: 映射成功后的虚拟内存首地址
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
功能:删除/控制共享内存
shmid: IPC标识符
cmd:
IPC_STAT 获取共享内存属性 buf输出型参数
IPC_SET 设置共享内存属性 buf输入型参数
IPC_RMID 删除共享内存 NULL
buf
编程模型:
进程A 进程B
创建共享内存 获取共享内存
映射共享内存 映射共享内存
写数据通知其他进程 收到通知并读数据
取消映射 取消映射
删除共享内存
消息队列:
基本特点:是由内核负责维护的链式数据队列,不是根据先后顺序出队,而是根据消息类型收发数据
int msgget(key_t key, int msgflg)
功能:创建\获取消息队列
key: IPC键值
msgflg:
IPC_CREAT 消息队列已经存在则获取,否则创建
IPC_EXCL 消息队列已存在则返回错误
注意:如果创建需要提供权限
返回值: IPC标识符,失败-1
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
功能:向消息队列发送消息包
msqid: IPC标识符
msgp: 要发送的消息包的首地址
struct msgbuf {
long mtype; // 消息类型
char mtext[n]; // 数据
};
msgsz: 数据的字节数,不包含消息类型
msgflg:
阻塞发送一般给0
IPC_NOWAIT 当消息队列满,不等待立即返回
返回值: 成功返回0,失败-1
size_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
功能:从消息队列中接受对应消息包的数据
msqid: IPC标识符
msgp: 存储消息包的内存首地址
msgsz: 存储数据的内存字节数(尽量大些)
msgtyp: 消息类型(按照类型获取,不按照顺序)
>0 读取消息类型等于msgtype的消息
=0 读取消息队列中的第一条消息
<0 读取消息类型小于abs(msgtyp)的消息,如果有多个则读值最小的
msgflg
IPC_NOWAIT 消息队列都不符合时不阻塞,立即返回
MSG_EXCEPT 如果msgtyp>0,则读取第一条不等于msgtyp的消息
MSG_NOERROR 如果不包含此标志,如果实际发送过来的数据字节>接受的字节数,则返回失败
如果包含此标志,那么就只读取接收的字节数,一定会成功
返回值:成功读取到数据的字节数
int msgctl(int msqid,int cmd, struct msqid_ds *buf);
msg_qid: IPC标识符
IPC_STAT 获取消息队列属性 buf输出型参数
IPC_SET 设置消息队列属性 buf输入型参数
IPC_RMID 删除消息队列 NULL
buf
编程模型:
进程A 进程B
创建消息队列 获取消息队列
发送消息 获取消息
获取消息 发送消息
删除消息队列
信号量:
基本特点:由内核管理的一个"全局变量",用于记录共享资源的数量,限制进程对共享资源的访问使用
信号量是一种数据操作锁,本身是不具备数据交互功能,而是通过控制其他的通信资源从而匹配实现进程间通信
1、如果信号量的值大于0,说明可以使用资源,使用时需要信号量-1,然后再使用
2、如果信号量的值等于0,说明没有资源可使用,此时进程进入休眠,直到信号量大于>0,进程会被唤醒,执行步骤1
3、当资源使用完毕,把信号量+1,正在休眠的进程就会被唤醒
int semget(key_t key, int nsems, int semflg);
功能: 创建\获取信号量
key: IPC键值
nsems: 信号量的数量 一般写1
semflg:
IPC_CREAT 信号量已存在则获取,否则创建
IPC_EXCL 信号量已存在则返回错误
注意:如果创建需要提供权限
返回值: IPC标识符 失败-1
int semctl(int semid, int semnum, int cmd, ...);
功能:删除、控制信号量
semid: IPC标识符
semnum: 要操作的第几个信号量,从0开始,下标
cmd:
IPC_STAT 获取信号量属性 buf输出型参数
IPC_SET 设置信号量属性 buf输入型参数
IPC_RMID 删除信号量 NULL
SETVAL 设置某个信号量的值
SETALL 设置所有信号量的值
GETVAL 获取某个信号量的值
GETALL 获取所有信号量的值
GETNCNT 获取等待拿资源的进程的数量
int semop(int semid, struct sembuf *sops, size_t nsops);
功能:对信号量进行加减操作
semid: IPC标识符
sembuf {
unsigned short sem_num; /* 信号量的下标 */
short sem_op;
1 信号量+1
-1 信号量-1 如果不能减,则默认阻塞
short sem_flg;
IPC_NOWAIT 不阻塞
SEM_UNDO 如果进程终止没有手动还资源,系统会自动帮你还
}
nsops: 表示sops指向多少个结构体数量 一般写1