管道
管道传输数据是单向的
所谓的管道,就是内核里面的一串缓存
缺点:效率低,FIFO
消息队列
消息队列是保存在内核中的消息链表
在发送数据时,会分成一个一个独立的数据单元,也就是消息体(数据块),消息体是用户自定义的数据类型,消息的发送方和接收方要约定好消息体的数据类型,所以每个消息体都是固定大小的存储块,不像管道是无格式的字节流数据。如果进程从消息队列中读取了消息体,内核就会把这个消息体删除
缺点:
- 消息队列不适合比较大数据的传输
- 消息队列通信过程中,存在用户态与内核态之间的数据拷贝开销
共享内存
共享内存的机制,就是拿出一块虚拟地址空间来,映射到相同的物理内存中
缺点:
- 如果多个进程同时修改同一个共享内存,很有可能就冲突
信号量
信号量其实是一个整型的计数器,主要用于实现进程间的互斥与同步,而不是用于缓存进程间通信的数据
信号量表示资源的数量,控制信号量的方式有两种原子操作:
- 一个是 P 操作,这个操作会把信号量减去 1,相减后如果信号量 < 0,则表明资源已被占用,进程需阻塞等待;相减后如果信号量 >= 0,则表明还有资源可使用,进程可正常继续执行。
- 另一个是 V 操作,这个操作会把信号量加上 1,相加后如果信号量 <= 0,则表明当前有阻塞中的进程,于是会将该进程唤醒运行;相加后如果信号量 > 0,则表明当前没有阻塞中的进程
P 操作是用在进入共享资源之前,V 操作是用在离开共享资源之后,这两个操作是必须成对出现的。
信号初始化为 1,就代表着是互斥信号量
信号初始化为 0,就代表着是同步信号量
信号
对于异常情况下的工作模式,就需要用「信号」的方式来通知进程
在 Linux 操作系统中, 为了响应各种各样的事件,提供了几十种信号,分别代表不同的意义。
信号是进程间通信机制中唯一的异步通信机制,因为可以在任何时候发送信号给某一进程,一旦有信号产生,我们就有下面这几种,用户进程对信号的处理方式。
1.执行默认操作。Linux 对每种信号都规定了默认操作,例如,上面列表中的 SIGTERM 信号,就是终止进程的意思。
2.捕捉信号。我们可以为信号定义一个信号处理函数。当信号发生时,我们就执行相应的信号处理函数。
3.忽略信号。当我们不希望处理某些信号的时候,就可以忽略该信号,不做任何处理。有两个信号是应用进程无法捕捉和忽略的,即 SIGKILL 和 SEGSTOP,它们用于在任何时候中断或结束某一进程
socket
跨网络与不同主机上的进程之间通信,就需要 Socket 通信了