进程间通信——管道

管道

管道的本质其实就是一个文件,进程可以对其进行读或写,从而实现进程间的通信。

无名管道和有名管道

无名管道

创建单向数据流无名管道代码为:

int pipe(int fd[2]);

该函数返回两个文件描述符:fd[0]用于读,fd[1]用于写。管道被创建与内核态。
管道一个典型而常见的例子:

ls | sort | grep xxx

其中,shell将执行上述步骤,创建三个进程和两个管道,并且将每个管道的读出端复制到相应进程的标准输入,将每个管道的写入端复制到相应进程的标准输出。

管道实现进程间通信,是通过内核运作完成的,读写管道时,数据都要穿过用户-接口。

无名管道只能用于有一个共同祖先进程的各个进程之间,无法在无亲缘关系的两个(或多个)进程间进行通信,通常用于父进程和子进程之间的通信(因为创建管道时,没有返回固定的文件名,注意:这是在不考虑描述符传递的基础上)。

有名管道(FIFO)

FIFO(First In First Out)是一个单向数据流,因为每个FIFO都有一个路径名与之关联,所以没有亲缘关系的进程之间,也可以访问同一个FIFO,从而实现进程间的通信。

创建有名管道代码为:

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

内核为管道和FIFO维护一个访问计数器,它的值是访问同一个管道或FIFO的打开着的描述符个数。有了这个计数器,即使某个进程删除了FIFO的一个路径名,但目前仍打开着的描述符却不会被影响,也就是说,不会影响这在使用该FIFO的其他进程。

半双工管道和全双工管道

上面说的pipe函数创建的是半双工管道(单向数据流),但也有一些系统实现的pipe函数是创建一个全双工管道(双向数据流)。

全双工管道是由两个半双工管道构成的,fd[1]写入的数据,只能从fd[0]读出;写入fd[0]的数据只能从fd[1]读出。

记录传递:字节流

管道通常以字节流I/O模型来传递信息,字节流I/O模型的特点是:不存在记录边界,读写操作根本不检查数据,系统也不对其进行解释。这些解释和检查工作,都由读写的应用进程负责。

那如果要传递的信息长度可变,且读数据的进程需要知道消息边界,以判定在什么时候读出单条消息?可以有三种解决方法:

  • 使用一个或多个特殊字符来分割消息,如使用换行符,或者回车符后加换行符的方式(http协议中用于分隔文本记录的一种方式);

  • 消息记录头部加上用于表明这条消息长度的固定长度字段,这样就可以不需要分割字符,也免去了前面转移字符的麻烦。

  • 每次连接值传输一个记录,传完就关闭(HTTP1.0用的就是这种方法)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值