Linux进程间通信机制
1.无名管道:只能用于亲缘进程之间的通信
单向通信
双向通信
亲缘进程:
只要存在继承关系的进程就是亲缘进程,继承关系分为两种。
(1)直接继承 :父进程 -->子进程
(2) 间接继承:父进程 -->子进程 -->子进程
读管道时,如果没有数据的话,读操作会休眠(阻塞)
2.有名管道:
单向通信
双向通信
无名管道因为没有文件名,被称为了无名管道,同样的道理,有名管道之所以叫有名管道,是因为它有文件名
也就是说当我们调用相应的API创建号“有名管道”后,会在相应的路径下面看到一个叫某某名字的“有名管道文件”
不管有名管道还是无名管道,它们的本质其实都是一样的,它们都是内核所开辟的一段缓存空间。进程间通过管道通信时,本质上就是通过共享操作
这段缓存来实现,只不过操作这段缓存的方式,是以读写文件的形式来操作的。
有名管道特点:
(1)能够用于非亲缘进程之间的通信
因为有文件名,所以进程可以直接调用open函数打开文件,从而得到文件描述符,不需要像无名管道一样,必须在通过继承的方式才能获取到文件描述符。
所以任何两个进程之间,如果想要通过“有名管道”来通信的话,不管它们是亲缘的还是非亲缘的,只要调用open函数打开同一个“有名管道”文件,然后对同一个“有名管道文件”进程读写操作,既可以实现通信。
A进程 --> 有名管道 --> B进程
读管道时,如果没有数据的话,读操作同样会休眠(阻塞)
当进程写一个所有读端都被关闭了的管道时,进程会被内核返回SIGPIPE信号,如果不行被该信号终止的话,我们需要忽略、捕获、屏蔽该信号。
不过一般情况下,不需要对这个信号进行处理,除非你有必须要处理的理由
对于通信的两个进程来说,创建管道时,只需要一个人创建,另外一个直接使用即可
有名管道使用步骤:
(1)进程调用mkfifo创建有名管道
(2)open打开有名管道
(3)read/write读写管道进行通信
为了保证管道一定被创建,最好是两个进程都包含创建管道的代码,谁先运行就谁先创建,后运行的发现管道已经创建好了,那就直接open打开使用。
下面三种是属于Unix 的 System V IPC通信机制
3.消息队列 :OS创建的链表,链表的所有结点都是保存在物理内存上的,所以消息队列这个链表其实也是OS在内存上所开辟的缓存
使用步骤:
(1)使用msgget函数创建新的消息队列,或者获取已存在的某个消息队列,并返回唯一标识消息队列的标识符(msqID),后序收发消息就是使用这个标识符来表示的
(2)使用msgsnd函数,利用消息队列标识符发送某编号的消息。
(3)使用msgrcv函数,利用消息队列标识符接收某编号的消息
(4)使用msgctl函数,利用消息队列标识符删除消息队列
4.共享内存
共享内存的API与消息队列的API非常相似,应该System V IPC的API都差不多
5.信号量(semaphore)
(1)互斥
对于互斥操作来说,多进程共享操作时,多个进程间不关心谁先操作,谁后 操作的先后顺序问题,它们只关心一件事,那就是我在操作时别人不能操作。
互斥时,如果当前正在操作的进程它的时间片到了,切换到了其它进程上,但是当该进程检测到上一个进程还没操作完时,该进程在当前的时间片内会休眠,直到再次切换回上一个进程,将操作完成后再切换回来,此时才能进行操作。
(2)同步
同步其实本身就包含了互斥,不过同步不仅仅只有互斥,同步对于谁先操作,谁后操作的先后顺序有要求,比如规定A进程先写,然后B进程写,然后是C进程写,那就绝对不能出现这种操作顺序以外的顺序。