管道

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. [jOOQ中文]2. jOOQ与Spring和Druid整合

    https://segmentfault.com/a/1190000010496053 jOOQ和Spring很容易整合. 在这个例子中,我们将整合: Alibaba Druid(但您也可以使用其他连 ...

  2. c++经典排序算法全集(转)

    C++排序算法全集 排序算法是一种基本并且常用的算法.由于实际工作中处理的数量巨大,所以排序算法对算法本身的速度要求很高. 一.简单排序算法 由于程序比较简单,所以没有加什么注释.所有的程序都给出了完 ...

  3. 用logger在控制台打印信息

    第一步: 导入jar包,maven项目可以直接添加 <dependency> <groupId>log4j</groupId> <artifactId> ...

  4. 关于std:auto_ptr std:shared_ptr std:unique_ptr

    很多人听说过标准auto_ptr智能指针机制,但并不是每个人都天天使用它.这真是个遗憾,因为auto_ptr优雅地解决了C++设计和编码中常见的问题,正确地使用它可以生成健壮的代码.本文阐述了如何正确 ...

  5. 解决Notepad++ Plugin Manager无法加载插件的方法

    今天正好安装了Notepad++,结果发现Plugin Manager里插件一个也没有,网上对应的方法都没有,最后无意间看到Plugin Manager Settings 里的提示,试了一下居然成功了 ...

  6. random.nextint()

    自从JDK最初版本发布起,我们就可以使用java.util.Random类产生随机数了.在JDK1.2中,Random类有了一个名为nextInt()的方法: public int nextInt(i ...

  7. Unix高级编程Note3

    [Unix高级编程Note3] 1.RECURSIVE锁可以递归,普通锁只会死锁 2.线程安全函数 3.线程私有数据 4.pthread_once 5.线程取消点 6.线程信号 7.pread 8.d ...

  8. 生产者消费者模式做一个golang的定时器

    在主程序启动的时候开一个goroutine作为消费者,用管道连接生产者和消费者,消费者处于无限循环,从管道中获取channel传过来定时event 注意:channel在消费者创建的时候就连通生产者和 ...

  9. unity平行光太亮?物体发白?可能你使用了2个或多个平行光

    unity平行光太亮?物体发白?可能你使用了2个或多个平行光 今天做项目时就遇到了这个问题,光亮得让物体发白 发现加载的场景 里面有个 平行光,删了就好了 要是感觉还是太亮,就把主平行光的Intens ...

  10. 为Eclipse安装功能扩展插件

    ---------siwuxie095                 关于 Eclipse 的下载.安装与配置,详见本人博客分类:利剑出鞘, 里面的 Eclipse的配置         本人博客( ...