Linux(进程间的通信)学习笔记

  1. 本地进程间通信

1)传统的进程间通信方式
无名管道(pipe)、有名管道(fifo)和信号(signal)
2)system V IPC 进程间通信
共享内存(share memory)、消息队列(message queue)和信号灯(semaphore)
3)BSD
套接字(socket)

  1. 管道
    2.1 无名管道(pipe)
    2.1.1 什么是无名管道 ?
    一个管道实际上就是一种特殊的文件,它不属于某一种文件系统,而是一种独立的文件系统,
    是个只存在于内存中的文件。类似时空隧道的概念,建立两个进程之间的通讯桥梁。
    2.1.2 无名管道的特点
    1)只能用于具有亲缘关系的进程之间的通信
    2)半双工的通信模式,具有固定的读端和写端:传输方向同时只能是一个方向。
    3)管道可以看成是一种特殊的文件,对于它的读写可以使用文件IO如read、write函数,不支持如lseek() 操作。
    4)一个进程向管道中写的内容被管道另一端的进程读出。写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据。

单工 : 传输方向是固定的,只能是一个方向传输。
半双工 : 传输方向同时只能是一个方向。
全双工 : 同时既能发送数据,也能接收,传输方向是双向的

2.1.3 创建无名管道
#include <unistd.h>

int pipe(int pipefd[2]);
函数功能:
创建无名管道
函数参数:
[1] pipefd : 用于保存管道的读端 和 写端
然后通过pipefd参数传出给用户程序两个文件描述符,pipefd[0]指向管道的读端,pipefd[1]指向管道的写端
通过read(pipefd[0])从读端读数据;或者write(pipefd[1])向写端写数据
返回值:
成功 返回 0
失败 返回 -1

step1: 父进程创建一个pipe,其中fd[0]固定用于读管道,而fd[1]固定用于写管道。
Step2:父进程fork,子进程继承了父进程的管道
Step3:之后取决于我们想要的数据流方向来关闭相应的端。

2.1.4 管道的读写注意事项
A.管道的大小
管道的大小为PIPE_BUF(ubuntu操作系统为65536)
B.从管道中读取数据
(1)写端存在时,当管道中无数据时,读操作就会阻塞。
当读端请求读取的数据大于管道中的数据时,此时读取管道中实际的数据。
当读端请求读取的数据小于管道中的数据时,此时返回请求读取的数据。
(2)写端已被关闭的管道时,在所有数据都被读取后, read返回0,以指示达到了文件结束处。
C.向管道中写数据
(1)读端存在时,向管道中写入数据时,管道缓冲区一有空闲区域,写进程就会试图向管道写入数据。
如果管道缓冲区数据达到PIPE_BUF,读进程不读走管道缓冲区中的数据,那么写操作将会一直阻塞。
(2)读端已被关闭的管道,试图向管道写数据,内核会向当前进程发送一个SIGPIPE信号(管道破裂信号)(默认动作 终止进程)

2.2 有名管道(fifo)

2.2.1 为什么引入有名管道
为了克服无名管道的不足之处,可以使互不相关的两个进程互相通信。
2.2.2 有名管道的特点
有名管道特点与无名管道类似,Linux中专门设立了一个专门的特殊文件系统–管道文件
以FIFO的文件形式存在于文件系统中,不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过FIFO相互通信。
有名管道管道内的数据还是在内存中。

2.2.3 创建有名管道
(1)有名管道可以从命令行上创建,命令行方法是使用下面这个命令:
mkfifo [可选项] 文件名
-m 权限
(2)有名管道也可以从程序里创建,相关API有
#include <sys/types.h>
#include <sys/stat.h>

int mkfifo(const char *pathname, mode_t mode);

函数功能:
创建有名管道
函数参数:
[1] pathname : 管道的路径
[2] mode : 访问权限
返回值:
成功 返回 0
失败 返回 -1
注意:
如果mkfifo的一个参数是一个已经存在路径名时,会返回EEXIST错误

#include <unistd.h>

int access(const char *pathname, int mode);

函数功能:
测试用于对文件的访问权限
函数参数:
[1] pathname : 文件路径
[2] mode : 测试的权限 (R_OK | W_OK | X_OK |F_OK)
R_OK 是否可读
W_OK 是否可写
X_OK 是否可执行
F_OK 是否存在
返回值:
成功 (所有测试的权限都满足) 返回 0
出错 (只要有一项不满足) 返回 -1

2.2.4 FIFO的open打开规则
O_RDONLY、O_WRONLY标志共有两种合法的组合方式:
O_RDONLY : 打开管道的读端,如果写端没有被打开,open函数会被阻塞
O_WRONLY : 打开管道的写端,入股读端没有被打开,open函数会被阻塞
总结:必须打开管道的两端,否则另一端将会被阻塞

2.2.5 有名管道的读写规则
有名管道的读写原则和无名管道的读写原则基本一致,主要参考无名管道的读写原则即可。

2.2.6 无名管道与有名管道的区别与联系
1.PIPE和FIFO的区别:
对于FIFO和无名管道的区别:
(1)创建并打开一个无名管道只需调用pipe。创建并打开一个FIFO则需在调用mkfifo后再调用open。
(2)无名管道在所有进程最终都关闭它之后自动消失。FIFO的名字则只有通过调用unlink才文件系统删除。
FIFO需要额外调用的好处是:FIFO在文件系统中有一个名字,该名字允许某个进程创建个FIFO,与它无亲缘关系的另一个进程来打开这个FIFO。
对于管道来说,这是不可能的。
2.PIPE和FIFO的相同点:
(1)虽然管道,特别是有名管道可以很方便地在双向上打开读写,但其内核实现依然是单向的。严格遵循先进先出(first in first out),
对管道及FIFO的读总是从开始处返回数据,对它们的写则把数据添加到末尾。
(2)pipe, fifo都不支持诸如lseek()等文件定位操作。
(3)对于pipe或者fifo,如果在读端或者写端打开了多个读写端(进程),之间的读写是不确定的,需要通过其他的同步机制实现多进程通讯的同步。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值