在之前的总结中我们已经总结了线程间通信的方式和提点,下面这篇博文我们来总结下进程间通信的方式方法和特点。同样我们不把函数作为重点,重点在于对特征的中介。
进程间通信(IPC)的方式很多。下面进行归类总结。
在传统的进程间通信中有 无名管道,有名管道,信号通信。后来system v 退出了自己的IPC 方式 消息队列,共享内存和信号灯集合但是system v的通信方式也存在自己的缺点。POSIX 在此基础上退出了自己的posix的消息队列,共享内存和信号灯集。另外,进程间还可以通过对文件的操作实现沟通,这里用到了文件锁。还有后期的内存映射方式。在网络上BSD率先提出了socket的方法,成为后来为流行的套接字通信方式,这种方式既可以在本机上的进程间,也可以在网络上。
IPC 通信工具分类
下面对我们常用的集中进程间通信方式的特征进行总结
pipe
1.32位linux系统下默认大小为64M
2.如果写满会阻塞知道有人读走再写
3.如果读写都有那么写不会影响,读的话会阻塞
4.如果没有读端那么管道写入后会管道破裂发送一个信号SIGPIPE导致进程结束
5.如果没有写端那么管道读取会退出,如果管道里有东西那么会先读出来然后退出
6.fd[0]为读端 fd[1]为写端是固定的
7.Pipe创建之后,在内核中。当所有的读端和写端都关闭的时候,pipe将被释放掉
fifo
mkfifo既是函数又是命令
1.fifo不能用标准IO操作。适用于非亲缘关系的进程间,大为64M
2.fifo的打开有只读只写方式
如果只读方式打开没有写端会阻塞,如果只写方式没有读端会阻塞这种阻塞是以open处阻塞。
如果以读写方式打开则不会阻塞,但是我们一般不会这样做,用fifo更多用来多个进程间进行单向的通信
3.fifo 文件不能通过lseek函数进行操作,管道属于 内核空间开辟,如果读写端都关闭那么内容会被清除
4.可以通过打开时候设置全新啊O_NONBLOCK 将打开方式设置为非阻塞模式,这种模式打开的时候如果另一端已经打开那么没有影响
如果非阻塞为读,而写段没打开,那么读同样会成功(就是不会open处阻塞)
如果非阻塞为写,而读端没有打开,那么会返回一个错误信号管道破裂ENXIO open调用失败
信号
1.引起内核产生信号的事件 硬件异常 终端输入特殊字符 软件事件如定时器到期,窗口改变
2.信号的默认操作 :忽略信号 终止进程 暂停进程 对之前暂停的进程重新启动
3.信号是一种异步行为
共享内存
1.共享内存是一种为高效的进程间通信方式,内核专门留出的一块内存区域,这块内存可以由需要的访问的进程将其映射到自己的私有空间,因此进程可以直接读取数据不需要复制,所以提高了效率
2.key值是一个非负整数,通常生成的方法是有ftok生成(传入一个文件,和一个整数,通过inod节点结合算法)。这样同样的参数确保生成的key一样,而不同的传入产生不同的key。这样可以确保打开相同的key即指向相同的共享内存(或者消息队列或者信号量)。这是一种成熟的技术
3.共享内存多个进程可以对其操作,因此需要同步互斥机制
4.生成key---创建或打开---映射---解除映射----删除 这是共享内存使用的一般步骤
5.映射后一个参数可设置只读,0表示可读可写
6.创建时候key如果设置成私有的,那么只有在这个进程中可用,对进程间通信没有多大意义
7.共享内存的大小限制: usr/include/linux/shm.h中
#define SHMMAX 0x2000000 大32MB
#define SHMMIN 1 小1个字节
消息队列
1.消息队列中一次只能读取一条消息,不能一次读取多条或者不到一条
2.消息队列中的消息既可以按照先进先出读取也可以按照类型
3.msgsnd 发送消息事后,第三个参数为消息的字节数,一次发送一个消息所以返回为0,而不需要为发送的字节数,
第四个参数可以设置为非阻塞模式IPC_NOWAIT,这样当消息队列满的时候会立即返回EAGAIN错误
4 msgrcv 也可以设置非阻塞模式,,如果阻塞那么消息队列中没有消息会阻塞,如果设置为非阻塞则立即返回ENOMSG错误
5.消息队列和共享内存如果不手动释放不会随进程结束,除非系统重启
6.消息队列结构体重的消息类型项必须为第一项
信号
1.信号量更多是用来同步进程间资源的,如共享内存。也可以同步父子进程的执行
2信号灯限制: usr/include/linux/sem.h中
semget申请的信号灯的编号从0开始
semctl中的cmd 命令的常用用法
另外在poxis中也有消息队列,共享内存和信号量的机制
消息队列中system v 的移植性比较好,可以选择消息类型,但是poxis 的消息队列可以被poll select 等进行监听
共享内存中system v 的支持范围比较广泛,但是poxis 不必再创建时候就定下共享内存的大小
信号量中 poxis 有些像线程的信号量,通过相互通知的机制进行pv操作,相对而言不那么复杂。system v中是定义一个信号量的集合