本系列文章主要是学习记录Linux下进程间通信的方式。

常用的进程间通信方式:管道、FIFO、消息队列、信号量以及共享存储。

参考文档:《UNIX环境高级编程(第三版)》

参考视频:Linux进程通信  推荐看看,老师讲得很不错

Linux核心版本:2.6.32-431.el6.x86_64

注:本文档只是简单介绍IPC,更详细的内容请查看参考文档和相应视频。

本文介绍利用FIFO(命名管道)进行进程间的通信。

1  介绍

FIFO也称为命名管道。未命名的管道只能在两个相关的进程之间使用,而且这两个相关进程有一个共同的祖先进程。但是,FIFO可在不相关的进程间交换数据。

本质是内核中的一块缓存,另在文件系统中以一个特殊的设备文件(管道文件)存在。

在文件系统中只有一个索引块存放文件的路径,没有数据块,所有数据存放在内核中。

命令管道必须读和写同时打开,否则单独读或者单独写会引发阻塞。

2  函数原型

1 #include <sys/types.h>
2 #include <sys/stat.h>
3 int mkfifo(const char *pathname, mode_t mode);
4 int mkfifoat(int dirfd, const char *pathname, mode_t mode);
5 说明:创建一个FIFO
6 返回值:成功返回0;出错返回-1。
7 参数[in]:mode参数和open参数相同;
8 参数[in]:pathname文件路径名。
9 参数[in]:dirfd打开目录的有效文件描述符,若pathname是绝对路径名,此参数被忽略;若是相对路径路径名,此参数是一个打开目录的有效文件描述符。

3  操作

创建FIFO时,要用open来打开它。当write一个没有进程为读而打开的FIFO时,会产生信号SIGPIPE;当某个FIFO的最后一个写进程关闭了该FIFO,则将为该FIFO的读进程产生一个文件结束标志。

一旦已经用mkfifo创建了一个FIFO,就可用open打开它,一般的文件I/O函数(close、read、write、unlink等)。

4  测试代码

分别创建一个读和一个写进程,对同一个命令管道进行读写操作。

读进程fifo_read.c:

 1 #include <sys/types.h>
2 #include <sys/stat.h>
3 #include <fcntl.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6
7 int main(int argc, char *argv[])
8 {
9 if (argc < 2) {
10 printf("usage:%s fifo\n", argv[0]);
11 exit(1);
12 }
13 printf("open fifo read...\n");
14 int fd = open(argv[1], O_RDONLY);
15 if (fd < 0) {
16 perror("open error");
17 exit(1);
18 } else {
19 printf("open file success: %d\n", fd);
20 }
21 //从命名管道中读取数据
22 char buf[512] = {0};
23 while (read(fd, buf, sizeof(buf)) < 0) {
24 perror("read error");
25 }
26 printf("%s\n", buf);
27 close(fd);
28
29 return 0;
30 }

写进程fifo_write.c:

 1 #include <sys/types.h>
2 #include <sys/stat.h>
3 #include <fcntl.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7
8 int main(int argc, char *argv[])
9 {
10 if (argc < 2) {
11 printf("usage: %s fifo\n", argv[0]);
12 exit(1);
13 }
14 printf("open fifo write...\n");
15 int fd = open(argv[1], O_WRONLY);
16 if (fd < 0) {
17 perror("open error");
18 exit(1);
19 } else {
20 printf("open fifo success: %d\n", fd);
21 }
22 char *s = "123456789";
23 size_t size = strlen(s);
24 if (write(fd, s, size) != size) {
25 perror("write error");
26 }
27 close(fd);
28
29 return 0;
30 }

测试步骤:

1、先分别编译这两个程序:

[root@192 ipc]# gcc -o bin/fifo_read fifo_read.c

[root@192 ipc]# gcc -o bin/fifo_write fifo_write.c

2、使用mkfifo创建一个命名管道:[root@192 ipc]# mkfifo s.pipe

3、单独只执行其中的一个进程,会阻塞住:

4、另外打开一个终端,执行写进程:

这时读进程也得到了执行:

5  匿名管道和命名管道读写的相同点

(1)默认都是阻塞性读写;

(2)阻塞不完整管道(有一端关闭)

  • 单纯读时,在所有数据被读取后,read返回0,以表示到达了文件尾部;
  • 单纯写时,则产生信号SIGPIPE,如果忽略该信号或捕捉该信号并从处理程序返回,则write返回-1,同时errno设置为EPIPE。

(3)阻塞完整管道(两端都开启)

  • 单纯读时,要么阻塞,要么读取到数据;
  • 单纯写时,写到管道满时会出错。

(4)非阻塞不完整管道(有一端关闭)

  • 单纯读时直接报错;
  • 单纯写时,则产生信号SIGPIPE,如果忽略该信号或捕捉该信号并从处理程序返回,则write返回-1,同时errno设置为EPIPE。

(5)非阻塞完整管道(两端都开启)

  • 单纯读时直接报错;
  • 单纯写时,写到管道满时会报错。

Linux进程间通信-FIFO(命名管道)的更多相关文章

  1. 《Linux 进程间通信》命名管道:FIFO

    命名管道的主要用途:不相关的进程之间交换数据. 命令行上创建命名管道: $ mkfifo filename  程序中创建命名管道: #include <sys/types.h> #incl ...

  2. Linux进程间通信——使用命名管道

    在前一篇文章——Linux进程间通信——使用匿名管道中,我们看到了如何使用匿名管道来在进程之间传递数据,同时也看到了这个方式的一个缺陷,就是这些进程都由一个共同的祖先进程启动,这给我们在不相关的的进程 ...

  3. Linux进程间通信——使用匿名管道

    在前面,介绍了一种进程间的通信方式:使用信号,我们创建通知事件,并通过它引起响应,但传递的信息只是一个信号值.这里将介绍另一种进程间通信的方式——匿名管道,通过它进程间可以交换更多有用的数据.   一 ...

  4. Linux系统编程——进程间通信:命名管道(FIFO)

    命名管道的概述 无名管道,因为没有名字,仅仅能用于亲缘关系的进程间通信(很多其它详情.请看<无名管道>).为了克服这个缺点.提出了命名管道(FIFO).也叫有名管道.FIFO 文件. 命名 ...

  5. Linux中的pipe(管道)与named pipe(FIFO 命名管道)

    catalogue . pipe匿名管道 . named pipe(FIFO)有名管道 1. pipe匿名管道 管道是Linux中很重要的一种通信方式,是把一个程序的输出直接连接到另一个程序的输入,常 ...

  6. 进程间通信:命名管道FIFO(2)

    一.命名管道 如果我们想在不相关的进程之间交换数据,可以用FIFO文件来完成这项工作,它通常也被称为命名管道.命名管道是一种特殊类型的文件,它在文件系统中以文件名的形式存在,但是它的行为却和我们已经见 ...

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

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

  8. Linux学习记录--命名管道通信

    命名管道通信 什么是命名管道 一个主要的限制是,它是匿名管道的应用还没有名字,因此,只有它可以用于进程间通信的方式与亲缘关系.在命名管道(named pipe或FIFO)提出后,该限制得到了克服.FI ...

  9. 练习--LINUX进程间通信之无名管道PIPE

    IBM上放的这个系统不错,刚好可以系统回温一下LINUX的系统知识. http://www.ibm.com/developerworks/cn/linux/l-ipc/part1/ 感觉年纪大了,前几 ...

  10. mkfifo - 创建FIFO(命名管道)

    SYNOPSIS(总览) mkfifo [options] file... POSIX options(选项): [-m mode] GNU options(选项)(最短格式): [-m mode] ...

随机推荐

  1. 记录如何用php做一个网站访问计数器的方法

    简介创建一个简单的网站访问计数器涉及到几个步骤,包括创建一个用于存储访问次数的文件或数据库表,以及编写PHP脚本来增加计数和显示当前的访问次数. 方法以下是使用文件存储访问次数的基本步骤: 创建一个文 ...

  2. 力扣564(java)-寻找最近的回文数(困难)

    题目: 给定一个表示整数的字符串 n ,返回与它最近的回文整数(不包括自身).如果不止一个,返回较小的那个. "最近的"定义为两个整数差的绝对值最小. 示例 1: 输入: n = ...

  3. 揭秘阿里云神龙团队拿下TPCx-BB排名第一的背后技术

    ​简介:阿里云自主研发的神龙大数据加速引擎获得了TPCx-BB SF3000世界排名第一的成绩. ​ 一  背景介绍 近日,TPC Benchmark Express-BigBench(简称TPCx- ...

  4. Spark 大数据处理最佳实践

    开源大数据社区 & 阿里云 EMR 系列直播 第十一期 主题:Spark 大数据处理最佳实践 讲师:简锋,阿里云 EMR 数据开发平台 负责人 内容框架: 大数据概览 如何摆脱技术小白 Spa ...

  5. [Linux] 日志管理: rsyslogd 服务 (检测启动/自启动/日志位置)

    查看 rsyslogd 服务是否已启动: ps aux | grep rsyslogd 查看 rsyslogd 是否设置了自启动: systemctl status rsyslog 或者 servic ...

  6. dotnet 解析 TTF 字体文件格式

    在 Windows 下,可以使用 DX 提供的强大能力,调用 DX 读取 TTF 字体文件,获取字体文件的信息以及额外的渲染信息.特别是基于 DX 的 WPF 更是加了一层封装,使用 FontFami ...

  7. WPF 加载诡异的字体无法布局

    如果在系统里面存在诡异的字体,同时自己的 WPF 中有一个控件尝试使用这个字体放在界面中,那么将会在界面布局过程炸了,整个控件或者整个界面布局都无法继续 本文本来是由吕水大大发布的,但是他没空写,于是 ...

  8. RT-Thead移植时缺少SystemCoreClockUpdate函数

    一.问题 在移植 RT-Thead 时,需要获取mcu当前的 HCLK 时钟频率来设置滴答时钟,而我使用的库函数中刚好缺少SystemCoreClockUpdate函数. 我之前在RT-Thread移 ...

  9. 国产 Web 组态软件 TopStack V5.0 发布

    简介 TopStack 是一款轻量型 Web 组态软件,提供设备数据采集.定时任务.控制策略.联动控制.设备告警.设备维护管理.设备绩效管理.能源管理.组态开发.报表开发等核心功能.支持移动端访问,支 ...

  10. visual studio 2008的试用版评估期已结束(附无法使用产品密钥)的解决方法

    visual studio 2008过了试用期后再次启动提示对话框:visual studio的试用版评估期已结束. 解决办法: 第一步,在"控制面板"中启动"添加删除程 ...