【Operating System】进程 - 进程/线程间通信

Posted by 西维蜀黍 on 2019-02-13, Last Modified on 2021-09-21

需求

一个进程(process)可以创建了多个子进程(child processes),而这些子进程又可以创建子子进程,最终,就形成了一个进程树,如下图所示:

这些相关联的子进程可能需要进行相互通讯以同步状态,这就涉及到进程间通信(Interprocess Communication, IPC)

类似地,进程有时也需要和其他独立的进程进行通信(两个通信的进程没有父子关系)。比如,在 shell 管道(pipeline),一个进程的输出作为另一个进程的输入,这也是进程间通信。

对于线程而言,这也是类似的。因为同一个进程中的线程们共享同一块内存地址空间(address space)。因此,适用于进程间的通信机制当然也适用于线程之间。

进程间通信(Interprocess Communication, IPC)

进程间通信用于实现进程的同步和进程的互斥。

进程的同步与互斥的区别

进程的同步(synchronization)- 进程间的协作

进程的同步(synchronization),是进程之间的具有协作关系,是指系统中多个进程中发生的事件存在某种时序关系,需要相互合作,共同完成一项任务。

具体地说,一个进程运行到某一点时,要求另一个伙伴进程为它提供消息,在未获得消息之前,该进程进入阻塞态,获得消息后被唤醒进入就绪态。

进程的互斥(mutual exclusion)- 进程间的竞争

进程的互斥(mutual exclusion)是指进程之间具有竞争关系,即进程之间在任一时间,只能有一个进程进入临界区(critical regions)

进程的互斥(mutual exclusion)可以看做是一种特殊的进程同步(synchronization)

进程间通信方式

进程间通信可以通过以下几种方式:

  • 数据传输(Data transfer)
    • 管道(pipe):管道是一种半双工的通信方式,数据只能单向流动,联系一个进程的输出和另一个进程的输入。写入在管道的尾部,读出在管道的头部。管道只能传送无格式的字节流。
    • 套接字(socket):也是进程间的通信机制,与其它通信机制不同的是,它可以用于不同机器间的进程通信。
  • 共享内存(Shared memory)
  • 消息通信(Message comunication)
    • 消息队列(message queue)
    • 操作系统提供的信息通信:send()/receive()
    • 信号(Signal)
    • 信号量(semaphores)和管程(monitors)

数据传输(Data transfer)

管道(pipe)

管道(pipe),是一种半双工的通信方式,数据只能单向流动,联系一个进程的输出和另一个进程的输入。写入在管道的尾部,读出在管道的头部。管道只能传送无格式的字节流。

在Linux上的管道分两种类型:

  • 无名管道 PIPE(可用于父子间进程通信)
  • 有名管道 FIFO(可用于任意两个进程间通信)

套接字(socket)

**套接字(socket)**也是进程间的通信机制,与其它通信机制不同的是,它还可以用于不同机器间的进程通信。

共享内存(Shared memory)

**共享内存(Shared memory)**就是映射一段可被其它进程所访问的内存,共享内存由一个进程创建,但是多个进程都可以访问。共享内存是最快的进程间通信方式(IPC),它是针对其它进程通信方式运行效率低的而专门设计的。它往往与其它通信机制。如信号量,配合使用,来实现进程间的同步和通信。

  • 在进程间共享内存
  • 在线程之间共享内存(全局内存)

消息通信(Message comunication)

消息通信(Message comunication)具体又可细分为以下方式:

  • 消息队列(message queue)
  • 操作系统提供的信息通信:send()/receive()
  • 信号(Signal)
  • 锁(Lock)、信号量(semaphores)和管程(monitors)

消息队列(message queue)

早期的 Unix 通信机制一直用的信号能够传送的信息量有限,而管道则只能传送无格式的字节流,且受缓冲区大小限制。消息队列的出现就是为了克服这些缺点。消息队列实质是一个链表(linked list),并把消息看做链表中的每一个记录,具有特定的格式。消息消费后就会被删除。

主要有两种消息队列:

  • POSIX 消息队列
  • 系统 V 消息队列

方式 2 被广泛应用。系统 V 消息队列是随内核持续的,随人工删除、重启机器则会被删除,要求每个消息队列都在系统范围内对应唯一的键值。

信号(signal)

**信号(signal)**可用于进程间进行异步事件通知。比如在按下某个键、硬件异常(如除数为 0,无效的存储)、进程或用户 kill 函数等从而触发一个事件并且发送一个信号给另一个进程。一个信号的产生叫生成,接收到一个信号叫捕获。Linux 下常见的信号有 SIGKILL、SIGSTOP、SIGALRM 等等。信号是进程间通信机制中唯一的异步通信机制,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知道信号到底什么时候到达。

信号量(semaphore)

**信号量(semaphore)**本质是一个计数器,可以用来控制多个进程对共享资源的访问。它也可以作为一种锁的机制,防止某进程正在访问临界区(共享资源)时,其它进程也访问该资源。因此它主要作为进程/线程之间同步的手段。

Reference