进程间通讯
文章目录
##including
管道中的无名管道是存放在文件描述符, 那么也像sockfd一样也是在内核有缓存区域的. 有名管道是无缓存的, 那么就像 消息队列是存放在内核的 信号量是生成在内核的
共享内存就是destination:是process虚拟空间的mmap区域(between heap and stack) source: mmap()是硬盘的文件, shm 是内核的某个区域
##IPC的方式通常有
###管道(包括无名管道和命名管道):PIPE
first: int pipe(int pipefd[2]) second: mkfifo() —> 无缓存pipe
|
|
###信号量:
###消息队列:
消息队列,是消息的链接表,存放在内核中。一个消息队列由一个**标识符(即队列ID)**来标识。
- 特点
- 消息队列是面向记录的,其中的消息具有特定的格式以及特定的优先级。
- 消息队列独立于发送与接收进程。进程终止时,消息队列及其内容并不会被删除。
- 消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取。
- 原型 –> msg开头
|
|
在以下两种情况下,msgget将创建一个新的消息队列:
- 如果没有与键值key相对应的消息队列,并且flag中包含了IPC_CREAT标志位。
- key参数为IPC_PRIVATE。
函数msgrcv在读取消息队列时,type参数有下面几种情况:
- type == 0,返回队列中的第一个消息;
- type > 0,返回队列中消息类型为 type 的第一个消息;
- type < 0,返回队列中消息类型值小于或等于 type 绝对值的消息,如果有多个,则取类型值最小的消息。 可以看出,type值非 0 时用于以非先进先出次序读消息。[所以zero就是以队列的形式输出]也可以把 type 看做优先级的权值。(其他的参数解释,请自行Google之)
###信号量
信号量(semaphore)与已经介绍过的 IPC 结构不同,它是一个计数器。信号量用于实现进程间的互斥与同步,而不是用于存储进程间通信数据。
- 特点
- 信号量用于进程间同步,若要在进程间传递数据需要结合共享内存。
- 信号量基于操作系统的PV操作,程序对信号量的操作都是原子操作。
- 每次对信号量的PV操作不仅限于对信号量值加 1 或减 1,而且可以加减任意正整数。
- 支持信号量组。
2.原型
- binary semaphore: 最简单的信号量是只能取 0 和 1 的变量,这也是信号量最常见的一种形式,叫做二值信号量(Binary Semaphore)。
- common semphore: 而可以取多个正整数的信号量被称为通用信号量。
Linux 下的信号量函数都是在通用的信号量数组(common semphore)上进行操作,而不是在一个单一的二值信号量上进行操作。
|
|
- 当semget创建新的信号量集合时,必须指定集合中信号量的个数(即num_sems),通常为1;
- 如果是引用一个现有的集合,则将num_sems指定为 0.
在semop函数中,sembuf结构的定义如下:
|
|
其中 sem_op 是一次操作中的信号量的改变量:
若sem_op > 0,表示进程释放相应的资源数,将 sem_op 的值加到信号量的值上。如果有进程正在休眠等待此信号量,则换行它们。
若sem_op < 0,请求 sem_op 的绝对值的资源。
- 如果相应的资源数可以满足请求,则将该信号量的值减去sem_op的绝对值,函数成功返回。
- 当相应的资源数不能满足请求时,这个操作与sem_flg有关。
- sem_flg 指定IPC_NOWAIT,则semop函数出错返回EAGAIN。
- sem_flg 没有指定IPC_NOWAIT,则将该信号量的semncnt值加1,然后进程挂起直到下述情况发生:
- 当相应的资源数可以满足请求,此信号量的semncnt值减1,该信号量的值减去sem_op的绝对值。成功返回;
- 此信号量被删除,函数smeop出错返回EIDRM;
- 进程捕捉到信号,并从信号处理函数返回,此情况下将此信号量的semncnt值减1,函数semop出错返回EINTR
若sem_op == 0,进程阻塞直到信号量的相应值为0:
- 当信号量已经为0,函数立即返回。
- 如果信号量的值不为0,则依据sem_flg决定函数动作:
- sem_flg指定IPC_NOWAIT,则出错返回EAGAIN。
- sem_flg没有指定IPC_NOWAIT,则将该信号量的semncnt值加1,然后进程挂起直到下述情况发生:
- 信号量值为0,将信号量的semzcnt的值减1,函数semop成功返回;
- 此信号量被删除,函数smeop出错返回EIDRM;
- 进程捕捉到信号,并从信号处理函数返回,在此情况将此信号量的semncnt值减1,函数semop出错返回EINTR
在semctl函数中的命令有多种,这里就说两个常用的:
- SETVAL:用于初始化信号量为一个已知的值。所需要的值作为联合semun的val成员来传递。在信号量第一次使用之前需要设置信号量。
- IPC_RMID:删除一个信号量集合。如果不删除信号量,它将继续在系统中存在,即使程序已经退出,它可能在你下次运行此程序时引发问题,而且信号量是一种有限的资源。
|
|
###共享存储:
####mmap()
其中Stack的大小是固定的, 而heap mmap的区域是两边向中间缩小.
####shm
- 二者本质上是类似的,mmap可以看到文件的实体,而shmget对应的文件在交换分区上的shm文件系统内,无法直接 cat 查看
- 安全性:
mmap 方式对应的真实文件,如果用户有权限即可查看,甚至删除 shmget 方式其实也一样,好了一层皮罢了(ipcrm -m …)
###Socket — Streams:
其中 Socket和Streams支持不同主机上的两个进程IPC
文章作者 zput
上次更新 2019-07-04