------信号屏蔽:
信号递送:当信号产生时,系统内核会在其维护的进程表项中,为接收信号的进程设置一个与该信号相对应的标志位,这个过程就叫递送,保存被递送信号的标志位集就叫做递送集。
信号未决:信号从产生到完成递送存在一定的时间间隔,
信号掩码:每个进程在系统内核中都有一个保存在经常表项中信号掩码,信号掩码本身也是一个信号集,凡是属于该信号集的信号,都会被阻塞与未决状态。
进程表项中存在信号未决集、信号掩码集、信号递送集。
----设置掩码和检测未决:
设置方式:使用sigprocmask函数设置掩码。使用sigpending输出未决信号集。
------现代风格的信号处理与发送:
经典风格:信号处理(signal)、信号发送(kill)
现代风格:信号处理(sigaction)、信号发送(sigqueue)
------进程间通信:
(1)为什么需要进程间通信:因为内存壁垒。
经典进程间通信包括:有名管道、无名管道。
(特点:兼容性最好,功能十分强大)
XSI进程间通信包括:共享内存、消息队列、信号量。
(特点:违背一切皆文件的设计理念)
BSD模仿网络通信的接口实现有名管道的功能:本地套接字。
------有名管道:
1)特点:有名管道有两端,一个是读端,一个是写端。可以将其看做是一个文件。
管道是存不住东西的,就是个通路,一端进行写,另一端必须进行读。
2)创建有名管道函数:mkfifo(文件路径,权限模式)
3)打开管道函数:open,使用read函数进行读取,使用close关闭管道。
------无名管道:
1)创建无名管道函数:pipe(int pipefd[2]);
参数:pipefd:输出两个文件描述符,其中pipefd[0]用于从无名管道读取数据,而pipefd[1]用于向无名管道写入数据。
2)特点:无名管道只能有一个方向,从一端读,另一端写。某个进程不能既拿写端,又拿读端。
------共享内存:
1)生成IPC对象的键
IPC对象:共享内存、消息队列、信号量集这三个合称为IPC对象。
键可以当做共享内存对象的名称。
用户用的是标识,内核中用的是地址。通过键可以获得标识,通过标识可以找到地址。
不同进程通过键访问同一个共享内存对象。
共享内存使用步骤:
函数:ftok:生成IPC对象的键(返回IPC对象的键)。
函数:shmget:创建(新的)或获取(已有的)共享内存对象(返回共享内存对象的标识)。
函数:shmat:加载共享内存(返回用户空间共享内存的起始地址)。
函数:shmdt:卸载共享内存。
注意:往用户空间放的数据,实际上是放到物理内存里了,物理内存又投射到内核空间,另一个进程也是如此。
------编程模型:(固定流程)
固定的流程。
进程1: 进程2:
获得共享内存的键 ftok 获得共享内存的键
创建共享内存 shmget 获取共享内存
价值共享内存 shmat 加载共享内存
使用共享内存 strcpy/memcpy/sprintf 使用共享内存
*pointer
卸载共享内存 shmdt 卸载共享内存
销毁共享内存
注意:
无名对象是放到内存中的;
IPC对象是被内存管理的;
用vfork创建的子进程,用_exit退出。
------消息队列:
1)逻辑模型:
一个消息中的消息指针指向下一条消息,形成类似单链表的逻辑结构。
从尾端加入(发送)新消息,从首端拿(接收)消息。
内核负责维护消息队列,整个消息队列都存在系统内核中。
2)系统限制:
限制不让链表过于大。
每个队列最大的总消息是16K。
系统限制的所有队列的总消息是:256K。
消息队列使用步骤:
1)获取消息队列的键:函数ftok
2)创建(新的)或获取(已有的)消息队列:函数msgget
3)发送消息:函数msgsend
4)接收消息:函数msgrcv
5)销毁消息队列内存:函数msgctl
编程模型:
进程1: 进程2:
获取消息队列的键 ftok 获取消息队列的键
创建消息队列 msgget 获取消息队列
发送消息队列msgsnd/msgrcv 接收发送消息
销毁消息队列 msgctl
特点分析:
消息队列更加省事了。
消息队列的效率比共享内存慢点,比管道快点。
消息队列比管道容纳的东西多。
消息队列采用链式存储,空间性能由于管道,但是时间性能略逊于共享内存。总体性能性对中庸,应用最为广泛。消息队列具有天然的同步机制,即流量控制。