管道

管道

管道

1. 其本质是一个伪文件(实为内核缓冲区)

2. 由两个文件描述符引用,一个表示读端,一个表示写端。

3. 规定数据从管道的写端流入管道,从读端流出。

管道的原理: 管道实为内核使用环形队列机制,借助内核缓冲区(4k)实现。

管道的局限性:

 数据一旦被读走,便不在管道中存在,不可反复读取。

缓冲区是有限

由于管道采用半双工通信方式。因此,数据只能在一个方向上流动。

只能在有公共祖先的进程间使用管道。

所传送的是无格式字节流

 

关闭未使用的管道文件描述符不仅仅是为了确保进程不会耗尽其文件描述符的限制——-这对于正确使用管道是非常重要的。 

   使用管道需要注意以下4种特殊情况(假设都是阻塞I/O操作,没有设置O_NONBLOCK标志):

1. 如果所有指向管道写端的文件描述符都关闭了(管道写端引用计数为0),而仍然有进程从管道的读端读数据,那么管道中剩余的数据都被读取后,再次read会返回0,就像读到文件末尾一样。

2. 如果有指向管道写端的文件描述符没关闭(管道写端引用计数大于0),而持有管道写端的进程也没有向管道中写数据,这时有进程从管道读端读数据,那么管道中剩余的数据都被读取后,再次read会阻塞,直到管道中有数据可读了才读取数据并返回。

3. 如果所有指向管道读端的文件描述符都关闭了(管道读端引用计数为0),这时有进程向管道的写端write,那么该进程会收到信号SIGPIPE,通常会导致进程异常终止。当然也可以对SIGPIPE信号实施捕捉,不终止进程。具体方法信号章节详细介绍。

4. 如果有指向管道读端的文件描述符没关闭(管道读端引用计数大于0),而持有管道读端的进程也没有从管道中读数据,这时有进程向管道写端写数据,那么在管道被写满时再次write会阻塞,直到管道中有空位置了才写入数据并返回。

 

--------------------- 
作者:oguro 
来源:CSDN 
原文:https://blog.csdn.net/oguro/article/details/53841949 
版权声明:本文为博主原创文章,转载请附上博文链接!

 管道在它的引用计数(访问同一个管道的打开着的描述符的个数)为0后消失。

FIFO

用mkfifo函数创建一个命名管道,若已存在则返回错误。

函数参数中,第一个为文件的相对路径或绝对路径,表明在系统中创建一个管道文件,第二个参数为文件的权限信息。

    创建好管道文件之后,就可以使用了,因为是文件,所以可以打开,在一个程序中打开文件,如果以读写方式打开就不会阻塞,如果以只读方式打开就会阻塞直到有以写方式打开此文件为止,同样,如果以只写方式打开就会阻塞直到有读方式打开文件为止。   (O_RDWR mode 打开会绕开 FIFO 的阻塞行为, 因为其不具有可移植性,开发人员应该避免使用, 而是应该是用O_NONBLOCK的方式进行,所以书上是写只能  只读  或者只写)

linux 默认read/write操作是阻塞的, 可以在打开的时候设置O_NONBLOCK为非阻塞(或者之后使用 fcntl 函数进行设置)。

 

内核为管道维护了一个访问计数, 统计打开文件描述符的个数, 调用了unlink 函数后, 如果计数不为0, 不会直接删除,会等到最后一个 close 调用使得计数为0, 才调用删除 FIFO, 如果没有调用 unlink, 即使计数为0, 也不会删除FIFO。但是当管道最后一个打开的文件描述符被关闭,其中的数据被丢弃。删除FIFO是指删除这个路径名。// ???这里跟书的不同,书上是unlink是会直接删除这个路径名,但是仍打开着的描述符不受影响。

 

打开的时候要小心顺序,可能会造成死锁。DoS型攻击就是依靠这个原理的。

在设置管道文件的权限时,需要考虑umask的影响。

 https://blog.51cto.com/2627lounuo/1762949

 

管道命名管道的write都是原子操作。不会产生混淆写的情况。

FIFO是一种只能在单台主机上使用的IPC模式,

请求读出的大小大于当前可用大小时,则只返回可用的数据。

请求写入大小小于或等于 PIPE_BUF时,write保证是原子的。如果大于,则不保证原子。
如果设置了o_NONBLOCK
  待写的字节数小于等于PIPE_BUF:
    如果管道或FIFO中没有足以存放所有请求字节数的空间,那么立即返回一个EAGAIN错误。(因为保证不了原子性,所以返回错误)
  待写的字节数大于PIPE_BUF
    如果管道或FIFO中至少有1字节。那么写入能容纳的字节,同时把字节数作为返回值。(因为不需要保证原子性,所以直接写入就行)
    如果管道或FIFO已满,则立即返回一个EAGAIN错误。
如果向一个没有为读打开着的管道或FIFO写入,则内核产生一个SIGPIPE信号。该信号默认是终止进程

 

posted @ 2019-04-17 15:14 ff_d 阅读( ...) 评论( ...) 编辑 收藏
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值