进程间通信方式

概念

  1. 每个进程各自有不同的用户地址空间,进程之间的变量是彼此看不到的
  2. 进程之间交换数据必须通过内核,在内核中开辟一块缓冲区
  3. 一个进程把自己的数据从用户空间拷贝到内核缓冲区,另一个进程再从内核缓冲区把数据读走

简单的说,就是进程间传播或交换信息

通信目的

  • 数据传输:数据量在一个到几M字节之间
  • 共享数据:多个进程操作共享数据
  • 信息传递:通知某进程发生了某种事件(如进程终止时要通知父进程)
  • 资源共享:多个进程共享同样的资源。为了做到这一点,需要内核提供锁和同步机制
  • 进程管理:有些进程希望完全控制另一个进程的执行(如Debug进程),希望能够拦截另一个进程的所有异常,并能够及时知道它的状态变化

通信方式

1、管道

管道实质是一个内存缓冲区,需要通信的两个进程在管道两端,进程利用管道传递信息。对于两端的进程而言,管道就是一个文件,但它不属于文件系统,并且只存在与内存中

匿名管道
  • 半双工:数据只能在一个方向流动,不能反方向
  • 只能在有亲缘关系的进程间通信:父子进程、兄弟进程
命名管道
  • 半双工
  • 允许在没有亲缘关系的进程间通信:提供了一个路径名与之关联,以一种特殊设备文件形式存在于文件系统中

2、信号

内核可以利用信号来通知进程发生了什么系统事件

信号来源
  • 硬件来源:按下了键盘或其他硬件故障

  • 软件来源:比如kill、raise、alarm、setitimer、sigqueue函数,还包括一些非法运算符操作

进程对信号的响应
  • 忽略信号:但 SIGKLL 和 SIGSTOP 不能忽略
  • 捕捉信号:定义信号处理函数,当信号发生时,执行相应的处理函数
  • 执行缺省操作

3、消息队列

消息的链表,具有特定的格式

存放在内核中,由消息队列标识符(队列ID)标识

允许一个或多个进程向它写入与读取消息

4、共享内存

多个进程可以直接读写同一块内存空间:内核专门留出一块内存区,需要访问的进程可以将其映射到自己的私有地址空间,不需要进行数据的拷贝,从而大大提高效率

注意
  • 并未提供同步机制:在一个进程结束对共享内存的写操作之前,没有自动机制阻止另外的进程对它的读取
  • 需要使用其他机制来同步对共享内存的访问

5、信号量

标识可用资源数量的计数器

用来控制多个进程对共享资源的访问,不用于交换大批数据,而用于多线程之间的同步

常作为一种锁机制:防止某进程访问资源时其他进程也访问该资源

二进制信号量(二值信号量):只有 0 和 1 的信号量,可用来标识某个资源是否可用

6、套接字

可用于不同机器之间的进程通信

有两种类型的套接字:基于文件的 和 面向网络的

1、基于文件的

Unix 套接字,家族名字 AF_UNIX,代表地址家族:UNIX

2、面向网络的

家族名字 AF_INET,代表地址家族:INTERNET

不管采用哪个地址家族,都有两种不同的套接字连接:面向连接的 和 无连接的

面向连接的(SOCK_STREAM) 无连接的(SOCK_DGRAM)
进行通信前必须建立一个连接 通信前不需要建立联系
成本更加低,因为不需要维护连接的开销
提供序列化的、可靠的、不重复的数据交付,没有记录边界 传输过程中无法保证顺序行、可靠性、重复性
每条信息可以被拆分成多个片段,并且每个片段都能确保到达目的地,在目的地将信息拼接起来 保存了记录边界,意味着消息是以整体发送的,而非首先分成多个片段
主要协议:传输控制协议 TCP 主要协议:用户数据报协议 UDP