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

命名管道(FIFO)和无名管道(pipe)有一些特点是相同的,不一样的地方在于:

1、FIFO 在文件系统中作为一个特殊的文件而存在,但 FIFO 中的内容却存放在内存中。

2、当使用 FIFO 的进程退出后,FIFO 文件将继续保存在文件系统中以便以后使用。

3、FIFO 有名字,不相关的进程可以通过打开命名管道进行通信。

int mkfifo(const char *pathname, mode_t mode);用于创建一个管道

int open(const char *pathname, int flags);用于打开一个管道

打开FIFO文件和普通文件的区别有2点:

第一个是不能以O_RDWR模式打开FIFO文件进行读写操作。这样做的行为是未定义的。

因为我们通常使用FIFO只是为了单向传递数据,所以没有必要使用这个模式。

如果确实需要在程序之间双向传递数据,最好使用一对FIFO或管道,一个方向使用一个。或者采用先关闭在重新打开FIFO的方法来明确改变数据流的方向。

第二是对标志位的O_NONBLOCK选项的用法。

使用这个选项不仅改变open调用的处理方式,还会改变对这次open调用返回的文件描述符进行的读写请求的处理方式。

O_RDONLY、O_WRONLY和O_NONBLOCK标志共有四种合法的组合方式:

  • flags=O_RDONLY:open将会调用阻塞,除非有另外一个进程以写的方式打开同一个FIFO,否则一直等待。
  • flags=O_WRONLY:open将会调用阻塞,除非有另外一个进程以读的方式打开同一个FIFO,否则一直等待。
  • flags=O_RDONLY|O_NONBLOCK:如果此时没有其他进程以写的方式打开FIFO,此时open也会成功返回,此时FIFO被读打开,而不会返回错误。
  • flags=O_WRONLY|O_NONBLOCK:立即返回,如果此时没有其他进程以读的方式打开,open会失败打开,此时FIFO没有被打开,返回-1。

open函数调用中的参数标志O_NONBLOCK会影响FIFO的读写操作。

规则如下:

  • 对一个空的阻塞的FIFO的read调用将等待,直到有数据可以读的时候才继续执行/
  • 对一个空的非阻塞的FIFO的read调用立即返回0字节。
  • 对一个完全阻塞的FIFO的write调用将等待,直到数据可以被写入时才开始执行。
    • 系统规定:如果写入的数据长度小于等于PIPE_BUF字节,那么或者写入全部字节,要么一个字节都不写入。

注意这个限制的作用:
当只使用一个FIF并允许多个不同的程序向一个FIFO读进程发送请求的时候,为了保证来自不同程序的数据块 不相互交错,即每个操作都原子化,这个限制就很重要了。如果能够包子所有的写请求是发往一个阻塞的FIFO的,并且每个写请求的数据长父小于等于PIPE_BUF字节,系统就可以确保数据绝不会交错在一起。通常将每次通过FIFO传递的数据长度限制为PIPE_BUF是一个好办法。

  • 在非阻塞的write调用情况下,如果FIFO 不能接收所有写入的数据,将按照下面的规则进行:

    • 请求写入的数据的长度小于PIPE_BUF字节,调用失败,数据不能被写入。
    • 请求写入的数据的长度大于PIPE_BUF字节,将写入部分数据,返回实际写入的字节数,返回值也可能是0。

其中。PIPE_BUF是FIFO的长度,它在头文件limits.h中被定义。在linux或其他类UNIX系统中,它的值通常是4096字节。

上面都是网上找的资料,有时间再整理吧,下面是自己写的一个测试代码:

write.c

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h> #define FIFO_NAME "/tmp/myfifo"
int main(){
if(access(FIFO_NAME,F_OK) != 0){//如果文件存在
int err = mkfifo(FIFO_NAME,0777);
if(err != 0){
perror("Create fifo failed");
return -1;
}
}
printf("create fifo succeed!\n");
int fifo_fd = open(FIFO_NAME,O_WRONLY);
printf("open fifo succeed!\n");
if(fifo_fd < 0){
printf("open fifo failed!\n");
return -1;
}
int i = 1;
for(;i < 100; i++){
if(write(fifo_fd,&i,sizeof(int)) != -1)
sleep(1);
else
perror("Write failed");
}
printf("write succeed: %d\n",i);
close(fifo_fd);
return 0; }

  

read.c

#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h> #define FIFO_NAME "/tmp/myfifo"
int main(){
int fifo_fd = open(FIFO_NAME,O_RDONLY | O_NONBLOCK );
if(fifo_fd < 0){
printf("open fifo failed!\n");
return -1;
}
int i;
sleep(5);
while(1){
int size = read(fifo_fd,&i,sizeof(int));
if(size > 0)
printf("读到:%d\n",i);
}
close(fifo_fd);
return 0; }

  通信过程中,当所有读进程退出后,写进程向命名管道内写数据时,写进程也会(收到 SIGPIPE 信号)退出。

  本例子中,写进程退出后,读进程继续循环,当再次有写进程启动时,读进程就会再次读到数据。

linux有名管道fifo,进程间通信的更多相关文章

  1. linux 有名管道(FIFO)

    http://blog.csdn.net/firefoxbug/article/details/8137762 linux 有名管道(FIFO) 管道的缓冲区是有限的(管道制存在于内存中,在管道创建时 ...

  2. Linux有名管道的 阻塞VS非阻塞 读写

    参考文章: 关于有名管道open时阻塞的问题 Linux有名管道(FIFO)的阻塞和非阻塞读写 挖坑,日后填

  3. 有名管道FIFO

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

  4. 有名管道FIFO进程间数据传输实例

    紧接着上面一个博客的简单介绍,下面进行一个没有血缘关系的进程间通信的实例,实现文件拷贝传输. 有两个进程,一个主要是fifow进程:读文件Makefile内容,写入管道;另一个进程fifor:读管道内 ...

  5. 进程间通讯:有名管道FIFO

    接收端: #include <sys/stat.h> #include <sys/types.h> #include <stdio.h> #include < ...

  6. Linux 进程间通信 有名管道(fifo)

    有名管道特点: 1)无名管道只能用于具有亲缘关系的进程之间,这就限制了无名管道的使用范围 2)有名管道可以使互不相关的两个进程互相通信. 3)有名管道可以通过路径名来指出,并且在文件系统中可见,但内容 ...

  7. Linux进程间通信---管道和有名管道

    一.管道 管道:管道是一种半双工的通信方式,数据只能单方向流动,而且只能在具有亲缘关系的进程间使用,因为管道 传递数据的单向性,管道又称为半双工管道.进程的亲缘关系通常是指父子进程关系. 管道的特点决 ...

  8. linux进程间通信-有名管道(FIFO)

    有名管道(FIFO) 命名管道也被称为FIFO文件,是一种特殊的文件.由于linux所有的事物都可以被视为文件,所以对命名管道的使用也就变得与文件操作非常统一. (1)创建命名管道 用如下两个函数中的 ...

  9. Unix/Linux进程间通信(二):匿名管道、有名管道 pipe()、mkfifo()

    1. 管道概述及相关API应用 1.1 管道相关的关键概念 管道是Linux支持的最初Unix IPC形式之一,具有以下特点: 管道是半双工的,数据只能向一个方向流动:需要双方通信时,需要建立起两个管 ...

随机推荐

  1. ----关于position的四个标签----

    从[ two1-4 ]分别为absolute,fixed,static,relative标签 四个标签下位移值相同,[ two2 ]和[ two1 ]都出现在左上角,[ two2 ] 盖住了[ two ...

  2. 20175316盛茂淞 2018-2019-2 《Java程序设计》第2周课上测试总结

    20175316 2018-2019-2 <Java程序设计>第2周课上测试总结 上周考试题目总结 题目1 题目要求: 在Ubuntu中用自己的有位学号建一个文件,教材p29 Exampl ...

  3. ABP框架系列之五:(Unit Of Work-工作单元)

    Introduction Connection and transaction management is one of the most important concepts in an appli ...

  4. (PMP)第6章-----项目进度管理

    6.1 规划进度管理 输入 工具与技术 输出 1.项目章程 2.项目管理计划 (范围管理计划, 开发方法) 3.事业环境因素 4.组织过程资产 1.专家判断 2.数据分析 3.会议 1.进度管理计划 ...

  5. vue子传父多个值

    子组件:this.$emit("methdosName",data1,data2,data3) 父组件: <child @methodsName="xxx(argu ...

  6. s11 Docker+DevOps实战--过程和工具

    开发人员本地提交代码,本地使用容器模拟生产环境测试,测试通过提交到git master 分支,就会触发pipeline执行集成构建.集成工具: gitlab-vi,travis,或Jenkins.自动 ...

  7. 嵌入式FIFO核的调用

    本次设计源码下载地址:http://download.csdn.net/detail/noticeable/9915523 课程目标:学习调用quartus II 软件的FIFO(先进先出)IP核,并 ...

  8. 前端vue框架 脚手架

    1.安装node.js最新版本2.cmd下输入 1.node -v得到版本号检测是否安装成功 版本号要在6.9以上 2.npm -v 版本号要在3.10以上3.安装脚手架 1.npm install ...

  9. Centos6.5安装中文支持和中文输入法

     先来讲中文支持:    之前在网上查了不少资料,很多网友在网上都说,在shell命令下输入: # vi /etc/sysconfig/i18n 然后修改LANG="en_US.UTF-8& ...

  10. WebView 错误码整理

    在使用WebView中,我们不可避免的会接触到WebView加载失败的异常处理的需求,这时候,需要我们监听失败的方法也就是onReceivedError方法: public class CustomW ...