管道

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

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

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

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

管道的局限性:

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

缓冲区是有限

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

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

所传送的是无格式字节流

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

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

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

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

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

4. 如果有指向管道读端的文件描述符没关闭(管道读端引用计数大于0),而持有管道读端的进程也没有从管道中读数据,这时有进程向管道写端写数据,那么在管道被写满时再次write会阻塞,直到管道中有空位置了才写入数据并返回。
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是会直接删除这个路径名,但是仍打开着的描述符不受影响。 实际上FIFO的路径名也会使得引用计数+1,因此上面那段文字就很好理解了。

  

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

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

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

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

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

请求写入大小小于或等于 PIPE_BUF时,write保证是原子的。如果大于,则不保证原子。
如果设置了o_NONBLOCK
  待写的字节数小于等于PIPE_BUF:
    如果管道或FIFO中没有足以存放所有请求字节数的空间,那么立即返回一个EAGAIN错误。(因为保证不了原子性,所以返回错误)
  待写的字节数大于PIPE_BUF
    如果管道或FIFO中至少有1字节。那么写入能容纳的字节,同时把字节数作为返回值。(因为不需要保证原子性,所以直接写入就行)
    如果管道或FIFO已满,则立即返回一个EAGAIN错误。
如果向一个没有为读打开着的管道或FIFO写入,则内核产生一个SIGPIPE信号。该信号默认是终止进程
如果向一个没有为写打开着的管道或FIFO读入,则要么阻塞(等待写描述符且等待写入),要么返回EOF(原本的写描述符关闭了),如果再有写的描述符打开,则继续阻塞。
所以有个技巧就是,服务器的写描述符不关闭。这样当客户端close之后就不会出现服务端read到0,然后被迫重打开FIFO阻塞到read。如果服务器的写描述符不关闭,则客户端都close之后,read会阻塞直到来了新的客户端。 管道及FIFO限制
OPEN_MAX 一个进程在任意时刻能打开的最大描述符数
PIPE_BUG 可原子地写往一个管道或FIFO的最大数据量
他们都是数据流,数据流,流。类似socket的东西

管道/FIFO注意事项的更多相关文章

  1. Linux学习笔记25——命名管道(FIFO)

    1 命名管道(FIFO) 管道应用的一个重大缺陷就是没有名字,因此只能用于亲缘进程之间的通信.后来从管道为基础提出命名管道(named pipe,FIFO)的概念,该限制得到了克服.FIFO不同于管道 ...

  2. 进程间通信系列 之 命名管道FIFO及其应用实例

    进程间通信系列 之 概述与对比   http://blog.csdn.net/younger_china/article/details/15808685  进程间通信系列 之 共享内存及其实例   ...

  3. Linux进程间通信之管道(pipe)、命名管道(FIFO)与信号(Signal)

    整理自网络 Unix IPC包括:管道(pipe).命名管道(FIFO)与信号(Signal) 管道(pipe) 管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道 ...

  4. 进程间通信___命名管道(FIFO)

    命名管道(FIFO) 基本概念 命名管道和一般的管道基本相同,但也有一些显著的不同: 命名管道是在文件系统中作为一个特殊的设备文件而存在的. 不同祖先的进程之间可以通过管道共享数据. 当共享管道的进程 ...

  5. 命名管道FIFO

    首先我得检讨一下自己,这几天有些颓呀,打不起精神,板子出了点问题,果真自学还是很困难呀,硬件方面难解决呀,理想与现实还是很有差距的,伤透了,凌乱了. 一直在理解进程间通信的问题.发现上次忽略了一个问题 ...

  6. 管道/FIFO

    管道: #include<stdio.h> #include<unistd.h> #include<stdlib.h> #include<string.h&g ...

  7. linux有名管道fifo,进程间通信

    命名管道(FIFO)不同于无名管道之处在于它提供了一个路径名与之关联,以 FIFO 的文件形式存在于文件系统中,这样,即使与 FIFO 的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通 ...

  8. 进程间通信IPC-命名管道FIFO

    FIFO又被称为命名管道,未命名的管道只能在两个相关的进程之间使用,而这两个相关的进程还要有一个共同创建了它们的祖先进程,但是FIFO,不相关的进程之间也能交换数据. FIFO是一种文件类型.通过st ...

  9. 有名管道FIFO

    管道和FIFO的特征之一是它们的数据是一个字节流.这是UNIX的原生I/O模型.进程往其中写入的是字节流,系统不对它作解释. FIFO不存数据,只是通过它找到内核文件. 一.建立有名管道 1.命令mk ...

随机推荐

  1. halcon控制显示精度(精确到小数点后6位,精度足够了)

    实践应用 set_tposition (WindowHandle3,50, 50) write_string (WindowHandle3, '半径 D1=' +Ra[i]$'#f') set_tpo ...

  2. 「小程序JAVA实战」小程序的横向视频和页面拦截(59)

    转自:https://idig8.com/2018/09/24/xiaochengxujavashizhanxiaochengxudehengxiangshipinheyemianlanjie58/ ...

  3. Python新利器之pipenv(转)

    pipenv 都包含什么? pipenv 是 Pipfile 主要倡导者.requests 作者 Kenneth Reitz 写的一个命令行工具,主要包含了Pipfile.pip.click.requ ...

  4. Firefox 被Snap.do 劫持

    Firefox IE 被劫持 windows的控制面板,卸载程序, 找任何跟「Snap.do」有关的软件,找到後先移除「Snap.Do Engine」再移除「Snap.Do」. 注册表里查找 Snap ...

  5. 其他标签a实现提交功能

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. UNITY C#内存泄漏

    http://www.360doc.com/content/15/0717/09/10504424_485422031.shtml

  7. UGUI 事件穿透规则

    UGUI事件分为两大类:点击和拖拽. 点击包括 pointerdown, pointerup. 拖拽包括 begindrag, drag, enddrag. 点击事件无穿透:只会被最上层UI响应,不会 ...

  8. 迷你MVVM框架 avalonjs 0.83发布

    本版本做了如下改进: 重构计算属性, 这是@soom提出的BUG,发现计算属性被某个监控属性向上驱动更新自己时,不会解发$watch回调.详见这里. 强化ms-bind绑定,当第一次扫描时也会执行它的 ...

  9. Redis服务器操作

    [Redis服务器操作] 1.TIME 返回当前服务器时间. 2.DBSIZE 返回当前数据库的 key 的数量. 3.LASTSAVE 返回最近一次 Redis 成功将数据保存到磁盘上的时间,以 U ...

  10. linux之badblocks命令

    简介 该命令用来检测硬盘坏道.硬盘坏道问题,如忽视,会随着使用而扩大面积,严重损坏硬盘.一般采用检测坏道,进而屏蔽重分区的方式复用硬盘. 语法 badblock(选项)(参数) -b<区块大小& ...