进程用户态空间独立,内核态空间共享,可以借助内核空间实现进程间的通信。
管道
-
匿名管道:特殊文件只存在于内存,FIFO,单向数据,无格式的流且大小受限
- 只能父进程与子进程通信或者子进程之间通信
-
命名管道:不相关的进程间也能相互通信
缺点:效率低,不适合进程间频繁地交换数据。
消息队列
消息队列是保存在内核中的消息链表,以消息体(数据块,用户自定义的数据类型)为单位发送,消息的发送方和接收方要约定好消息体的数据类型
缺点:
- 不适合比较大数据的传输,MSGMAX 和 MSGMNB限制单条、队列内的数据最大长度
- 消息队列通信过程中,存在用户态与内核态之间的数据拷贝开销
共享内存
Why?
避免了用户态与内核态内存复制的开销。
How?
共享内存:拿出一块虚拟地址空间来,映射到相同的物理内存中。
信号量
Why?
共享内存同时被多进程使用会产生冲突
How?
使用信号量保护共享内存在同一时刻只能有一个进程访问
信号量大小1,访问前P操作,访问后V操作。
信号
信号:进程间通信机制中唯一的异步通信机制,例如kill
- Ctrl+C 产生 SIGINT 信号,表示终止该进程;
- Ctrl+Z 产生 SIGTSTP 信号,表示停止该进程,但还未结束;
进程对信号的处理:
-
执行默认操作
-
执行预定义的信号函数内容
-
忽略信号(SIGINT 、SIGTSTP不可忽略)
Socket
Why?
前面的方式都是同一主机上的进程间通信,无法做到跨主机通信
How?
int socket(int domain, int type, int protocal)
- domain 参数用来指定协议族,比如 AF_INET 用于 IPV4、AF_INET6 用于 IPV6、AF_LOCAL/AF_UNIX 用于本机;
- type 参数用来指定通信特性,比如 SOCK_STREAM 表示的是字节流,对应 TCP、SOCK_DGRAM 表示的是数据报,对应 UDP、SOCK_RAW 表示的是原始套接字;
- protocal 基本废弃,写成 0 即可;
- 实现 TCP 字节流通信:socket 类型是 AF_INET 和 SOCK_STREAM;
- 实现 UDP 数据报通信:socket 类型是 AF_INET 和 SOCK_DGRAM;
- 实现本地进程间通信:「本地字节流 socket 」类型是 AF_LOCAL 和 SOCK_STREAM,「本地数据报 socket 」类型是 AF_LOCAL 和 SOCK_DGRAM。另外,AF_UNIX 和 AF_LOCAL 是等价的,所以 AF_UNIX 也属于本地 socket;