进程间通信
基本的通信方式:管道 共享内存 消息队列 信号量
进程通信的目的:数据传输,数据共享,进程间的访问控制
管道—传输数据
共享内存共享数据
消息队列数据传输
信号量进程访问控制
管道:进程间的数据传输
半双工
原理:内核的缓冲区
匿名管道:这能用于有亲缘关系的进程间通信
int pipe(int pipefd[2]);
pipefd[0]-----读数据
pipefd[1]----write
返回值 0,失败-1
管道读写特性:
若管道中没有数据,read会阻塞,直到数据返回
若管道数据满了,write会阻塞直到数据读取有空闲位置,写入返回
若管道所有的读端都被关闭,则write会触发异常–SIGPIPE–导致进程退出
若管道所有的写端都关闭,则read读完数据,返回0
管道自带同步互斥特性:当读写大大小小于PIPE_BUF时保证操作原子性
互斥:保证对临界资源同一时间的唯一使用
同步:保证对临界资源的时序可控性
管道的生命周期伴随进程
命名管道
可见于文件系统,因为创建命名管道会随之在文件系统创建一个命名管道文件
mkfifo
因为所有的进程都可以通过打开文件操作管道
int mkfifo(const char* pathname,mode_t mode)
pathname:管道文件名字
mode:权限
返回值
命名管道文件的打开特性:
以只读方式打开若管道文件没有其他进程以写的方式打开则阻塞直到文件被以写的方式打开
若文件以只写的方式打开,其他进程没有以读的方式打开则阻塞直到有其他文件以读的方式打开
共享内存
最快的进程间通信方式,因为相较于其他通信方式将数据从用户态拷贝到内核态使用时从内核态拷贝到用户态,共享内存直接将一块内存映射到用户空间,用户可以通过地址对内存进行操作,并反馈到其他进程
共享内存使用流程
1.创建共享内存
头文件 和接口
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
key: 共享内存标识符
#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);
pathname:文件名
proj_id:数字
通过文件的iNode结点号和proj_id共同得出key值
size: 共享内存大小
shmflg: 打开方式创建权限
IPC_CREAT 共享内存不存在创建,存在打开
IPC_EXCL:存在报错不存在创建
mode_flags 权限
返回值:操作句柄shmid 失败返回-1
IPS查看共享内存
ipcs -m
ipcrm -m
2.将共享内存映射到虚拟地址空间
void *shmat(int shmid, const void *shmaddr, int shmflg);
shmid : 创建共享内存的返回的操作句柄
shmaddr: 用于指定映射在虚拟地址空间首地址: 通常置NULL
shmflg: 0–可读写
返回值:映射首地址(通过这个地址对共享内存进行操作)失败返回-1
int shmdt(const void *shmaddr);
2.对共享内存进行操作
4.接触映射关系
void *shmat(int shmid, const void *shmaddr, int shmflg);
5.删除共享内存
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
cmd:
IPC_RMID 删除共享内存
buf:设置获取共享内存信息,用不着置NULL
共享内存删除并不是立即删除只是聚聚后续映射链接,当共享内存映射链接数为0时删除共享内存