Linux下的进程间通信(1)
IPC(进程间通信)
Linux下的多个进程间的通信机制叫做IPC,它是多个进程之间进行互相沟通的一种方法。通过进程间通信实现不同进程之间传播和交换信息。
进程间通信(IPC)的目的总结
1:数据传输
2:资源共享
3:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件
4:进程控制
进程间通信的方式
在Linux下有多个进程间通信的方法:半双工管道、FIFO(命名管道)、消息队列、信号量、共享内存、socket、信号等
适用于一台机器上
1:管道(无名和命名)
2:信号
kill -l #查看机器支持的信号
3:消息队列
4:共享内存
5:信号量
操作系统中是PV操作
常用于不同机器间通信
6:socket(网络通信)
各种通信的特点描述
????管道 |
无名管道可用于具有亲缘关系进程间的通信
命名管道可用于无亲缘关系进程间的通信
????信号signal
信号是比较复杂的通信方式,用于通知接受进程有某种事件发生
异步通信
signal和kill
sigaction和sigqueue
????消息队列
消息队列是消息的链表
优点:消息队列克服了信号承载信息量少,管道只能承载五个师自己流以及缓冲区大小受限制等缺点
????共享内存
使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。
注意:往往与其他通信机制,如信号量结合使用,来达到进程间的同步以及互斥
????信号量
只要作为进程间以及统一进程不同线程之间的同步手段
????套接口也(Socket)
一般的进程通信机制,可用于不同机器之间的进程间通信,也就是网络通信
案例 :
管道 |
管道是一种把两个进程之间的标准输入和标准输出连接起来的机制
shell中管道用”|”表示
将左侧who命令的结果,作为管道右侧命令的输入
注意:
某些特定的IO操作管道是不支持的,例如偏移函数lseek()
查看内存缓冲区 可以查看PIPE_BUF(内核管道缓冲区)的大小,这是内核设定的为8512byte=4k
pipe capacity(管道)164k=64K
管道的使用要符合命令的要求
管道特点
1:只能在有亲缘关系的进程之间进行通信(也就是在父子进程之间通信) 2:单向通信一个读端,一个写端,如果要双向通信就要建立两个管道
3:接收数据流,与数据格式无关
4:一般而言,进程退出,管道释放,因此管道的生命周期随进程5:同步互斥原则,内核会对管道操作进行同步和互斥
无名管道的特点
1、没有名字,因此无法使用open()打开
2、只能用于亲缘进程间(如父子进程、兄弟进程、祖孙进程等)通信
3、半双工工作方式,读写端是分开的,pipefd[0]为读端,pipefd[1]为写端
4、写入操作不具有原子性,因此只能用于一对一的简单通信
5、不能用lseek()来定位
案例一:
案例二:
案例三:
在使用管道的时候,如果使用了管道的输入端,那么就需要将管道的输出端关闭,反之一样
案例四:
功能相当于ls -l | wc这个命令
统计文本中,行数,字数,及字节数
命名管道
命名管道提供了一个路径名与之关联,以FIFO的文件形式存在于文件系统中,
在文件系统中产生一个物理文件,其他进程只要访问该文件路径,就能彼此通过管道通信通过命令创建管道
mkfifo my-named-pipe,类型是p
终端1,数据写入管道,此时进入阻塞,等待另一端读取
终端2:读取管道中的数据,读取完之后终端1正常退
案例五:
消息队列
消息队列是内核地址空间中的内部链表,通过linux内核在各个进程之间传递内容,
消息顺序地发送到消息队列中,并且以几种不同的方式,从队列中获取,
每个消息队列可以用IPC标识符唯一的进行标识,内核中的消息队列是通过IPC的标识符来区别的,
不同的消息队列之间是相互独立的,每个消息队列中的消息又构成一个独立的链表。
消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法。
每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型的数据结构。
我们可以通过发送消息来避免命名管道的同步和阻塞问题。
但是消息队列与命名管道一样,每个数据块都有一个最大长度的限制。
????ipcs和ipcrm命令
ipcs -m 查看系统共享内存信息
ipcs -q 查看系统消息队列信息
ipcs -s 查看系统信号量信息
ipcs [-a] 系统默认输出信息,显示系统内所有的IPC信息