0%

《趣谈linux操作系统》小结(三十) - 进程间通信方式

进程间通信方式

对于大项目,单进程已经不能满足需求了,现在很多应用往往存在多个进程,各个进程在大功能上面都是职责单一的。那么就需要有一种途径进行进程间的交互协作,这就是进程间的通行方式。

管道模型

管道模型,适用于瀑布型的流程,前一个流程的输入作为后一个流程的输出,仅仅单向的传递数据。比如命令行的管道使用方式

1
2

ps -ef | grep 关键字 | awk '{print $2}' | xargs kill -9

管道是一种单向传输数据的机制,它其实是一段缓存,里面的数据只能从一端写入,从另一端读出。如果想互相通信,我们需要创建两个管道才行。

匿名管道

“|” 表示的管道称为匿名管道,意思就是这个类型的管道没有名字,用完了就销毁了。就像上面那个命令里面的一样,竖线代表的管道随着命令的执行自动创建、自动销毁。用户甚至都不知道自己在用管道这种技术,就已经解决了问题。

命名管道

这个类型的管道需要通过 mkfifo 命令显式地创建。

1
mkfifo hello

管道以文件的形式存在,这也符合 Linux 里面一切皆文件的原则。这个时候,我们ls 一下,可以看到,这个文件的类型是 p,就是 pipe 的意思。管道的写入和读取,就可以像下面这样操作

1
2
3
4
5
6
7

# echo "hello world" > hello // 写入


# cat < hello // 读取
hello world

管道不适合进程间频繁地交换数据。 具体代码实现上,一般是用于父子进程间的通信。通过pipe函数创建管道,然后创建子进程,父子进程分别关闭读写端,然后一个只读,另一个只写。

消息队列模型

消息队列,通过发送消息块进行交互。类似邮件一样,发送完消息就可以不管了, 对端主动读取消息,如果没有消息则返回空。你来我往的进行交互通信。

系统级的消息队列使用的比较少,一般使用用户级别的消息队列,比如通过socket网络通信发送消息,然后使用链表等数据结构保存消息。

共享内存模型

消息队列适合传递小的消息块,如果太大就可以使用共享内存模型。

每个进程都有自己独立的虚拟内存空间,不同的进程的虚拟内存空间映射到不同的物理内存中去。共享内存的原理就是让不同进程的虚拟空间映射到相同的物理地址上,这样不同进程写入的内容就可以被其他进程立马读取到。这种方式是进程间通信最快的了,因为共享内存是直接将一块内存区域映射到虚拟地址空间中,因此在数据通信传输的过程中,相比较其他的通信方式少了将数据从用户态到内核态的数据拷贝过程。
什么意思,就是说这种通信方式,已经把数据拿到了地址空间,再取数据不需要再涉及到内核,不涉及执行进入内核的系统调用 来传递数据。

信号量

共享内存模型存在多个进程对其进行读写,构成了临界资源,进程间对临界资源的保护采用的是信号量。通过信号量的获取与释放,获得临界资源的访问保护,可以保证相同时间段内只能有特定数目的进程对其进行操作。

消息队列,共享内存模型和信号量,需要保证不同的进程操作的是相同的队列、内存块和信号量,需要有一个地方获取统一的标识,这个由System V IPC通信体系来保证,通过对同一个文件进行操作获取信息,保证获取相同的标识。

信号

进程间通信还有一种方式,就是信号。不同进程间可以通过发送信号给指定id的进程,然后目标进程调用信号处理函数进行处理。一般用于处理异常来用。

Linux 提供了几十种信号,分别代表不同的意义。信号之间依靠它们的值来区分。信号可以在任何时候发送给某一进程,进程需要为这个信号配置信号处理函数。当某个信号发生的时候,就默认执行这个函数就可以了。

行动,才不会被动!

欢迎关注个人公众号 微信 -> 搜索 -> fishmwei,沟通交流。