【面试实战篇】说一说进程的通信方式有哪些?

这是一道简单而又被问烂的面试题,对于这种题,你一定要回答出自己一些理解,而不能按照网上那种烂大街的回答,比如对于这种题,简单粗暴的回答就是:

进程间常见的通信方式有如下几种

  • 管道
  • 消息队列
  • 共享内存
  • 信号量
  • Socket

以上便是 80% 用户的回答。

不过,对于这种提问非常频繁且简单的问题,我们不仅仅要能够回答出来,还要争取回答的更好,可能去回答出一个 why,尽可能让这些知识点之间产生一些逻辑上的联系

下面我给出一个自己平时的回答演示

回答演示

1、管道

平时在使用 Linux 系统的时候,我们经常会用到一条「|」的命令,比如我们要查看 Linux 系统中是否有 mysql 的相关进程,则会采用命令

ps -e | grep mysql
Bash

其中的 ”|“ 是管道的意思,它的作用就是把前一条命令的输出作为后一条命令的输入。在这里就是把 ps -e 的输出结果作为 grep mysql 这条命令的输入。

如果两个进程要进行通信的话,就可以用这种管道来进行通信了,并且我们可以知道这条竖线是没有名字的,所以我们把这种通信方式称之为匿名管道

这种通信方式是单向的,只能把第一个命令的输出作为第二个命令的输入,如果进程之间想要互相通信的话,那么需要创建两个管道。

居然有匿名管道,那也意味着有命名管道,通常我们可以用 mkifo 命令来创建一个命名管道,比如

mkfifo  test

这种管道的通信方式,优点是方便、简单,在日常的使用中也用到比较多;当然,这种通信方式效率相对比较低,比如,a 进程给 b 进程传输数据,只能等待 b 进程取了数据之后 a 进程才能返回。

所以管道不适合频繁通信的进程。

2、消息队列

如果你想要把数据放在某个内存之后就马上让进程返回,我们可以用消息队列的通信模式来解决这个问题,例如 a 进程要给 b 进程发送消息,只需要把消息放在对应的消息队列里就行了,b 进程需要的时候再去对应的消息队列里取出来。

同理,b 进程要和 a 进程发送消息也是一样,这种通信方式也有点类似于缓存

当然,这种消息队列的通信方式,也有一些缺点,比如 a 进程发送的数据占的内存比较大,并且两个进程之间的通信特别频繁的话,消息队列模型就不大适合了。

因为 a 发送的数据很大的话,意味着发送消息(拷贝)这个过程需要花很多时间来读处理,比如需要读内存,写内存。

3、共享内存

如果通信频繁,且数据内存占用大,共享内存这个通信方式就可以很好着解决拷贝所消耗的时间了。

这个可能有人会问了,每个进程不是有自己的独立内存吗?两个进程怎么就可以共享一块内存了?

我们都知道,系统加载一个进程的时候,分配给进程的内存并不是实际物理内存,而是虚拟内存空间

那么我们可以让两个进程各自拿出一块虚拟地址空间来,然后映射到相同的物理内存中,这样,两个进程虽然有着独立的虚拟内存空间,但有一部分却是映射到相同的物理内存,这就完成了内存共享机制了。

4、信号量

共享内存最大的问题是什么?没错,就是多进程竞争内存的问题,就像类似于我们平时说的线程安全问题。如何解决这个问题?这个时候我们的信号量就上场了。

信号量的本质就是一个计数器,用来实现进程之间的互斥与同步。例如信号量的初始值是 1,然后 a 进程来访问内存 1 的时候,我们就把信号量的值设为 0,然后进程b 也要来访问内存1的时候,看到信号量的值为 0 就知道已经有进程在访问内存1了,这个时候进程 b 就会访问不了内存1

所以说,信号量也是进程之间的一种通信方式。

5、Socket

上面我们说的共享内存、管道、信号量、消息队列,他们都是多个进程在一台主机之间的通信,那两个相隔几千里的进程能够进行通信吗?

答是必须的,这个时候 Socket 这家伙就派上用场了,例如我们平时通过浏览器发起一个 HTTP 请求,然后服务器给你返回对应的数据,这种就是采用 Socket 的通信方式了。

所以,进程之间常见的通信方式有:

1、管道

2、消息队列

3、共享内存

4、信号量

5、Socket

回答分析

上面这个回答,一看就不是背诵的,而是自己真正理解过之后,通过自己的语言组织出来的,而且还能通过这个回答,展示我身后的计算机基础,比如知道物理内存,虚拟内存,掌握一些常见 Linux 命令,也懂线程安全问题等等。

当然,我这里的回答相对比较详细,你们在回答的时候,肯定无法这么详细,不过你们要有我这里的逻辑思维去回答,层层递进,一环扣一环。

有人可能又会说,我完全不会啊,哪怕我懂这些,但是我也说不出来啊?

还是那句话,刻意去练,我也是刻意练出来的,可以自己先文字写一遍,然后不断去练,练个二三十道题,你就会了。

发表评论

后才能评论