概念
- 每个进程各自有不同的用户地址空间,进程之间的变量是彼此看不到的
- 进程之间交换数据必须通过内核,在内核中开辟一块缓冲区
- 一个进程把自己的数据从用户空间拷贝到内核缓冲区,另一个进程再从内核缓冲区把数据读走
简单的说,就是进程间传播或交换信息
通信目的
- 数据传输:数据量在一个到几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 |