进程间通信必须通过内核提供的通道,而且必须有一种办法在进程中标识内核提供的某个通道,前面讲过的匿名管道是用打开的文件描述符来标识的。如果要互相通信的几个进程没有从公共祖先那里继承文件描述符,它们怎么通信呢?内核提供一条通道不成问题,问题是如何标识这条通道才能使各进程都可以访问它?文件系统中的路径名是全局的,各进程都可以访问,因此可以用文件系统中的路径名来标识一个IPC通道。

FIFO和UNIX Domain Socket这两种IPC机制都是利用文件系统中的特殊文件来标识的。

FIFO文件在磁盘上没有数据块,仅用来标识内核中的一条通道,如 prw-rw-r-- 1 simba simba      0 May 21 10:13 p2,文件类型标识为p表示FIFO,文件大小为0。各进程可以打开这个文件进行read/write,实际上是在读写内核通道(根本原因在于这个file结构体所指向的read、write函数和常规文件不一样),这样就实现了进程间通信。UNIX
Domain Socket和FIFO的原理类似,也需要一个特殊的socket文件来标识内核中的通道,例如/run目录下有很多系统服务的socket文件:

srw-rw-rw- 1 root       root          0 May 21 09:59 acpid.socket

....................

文件类型s表示socket,这些文件在磁盘上也没有数据块。

一、命名管道(FIFO)

匿名管道应用的一个限制就是只能在具有共同祖先(具有亲缘关系)的进程间通信。
如果我们想在不相关的进程之间交换数据,可以使用FIFO文件来做这项工作,它经常被称为命名管道。

命名管道可以从命令行上创建,命令行方法是使用下面这个命令:
$ mkfifo filename
命名管道也可以从程序里创建,相关函数有:
int mkfifo(const char *filename,mode_t mode);

二、命名管道和匿名管道

匿名管道由pipe函数创建并打开。
命名管道由mkfifo函数创建,打开用open。
FIFO(命名管道)与pipe(匿名管道)之间唯一的区别在它们创建与打开的方式不同,这些工作完成之后,它们具有相同的语义。

The  only difference between pipes and
FIFOs is the manner in which they are created and opened.  Once these
tasks have been accomplished, I/O on pipes and FIFOs has exactly the
same semantics.

三、命名管道的打开规则

如果当前打开操作是为读而打开FIFO时
O_NONBLOCK disable:阻塞直到有相应进程为写而打开该FIFO
O_NONBLOCK enable:立刻返回成功
如果当前打开操作是为写而打开FIFO时
O_NONBLOCK disable:阻塞直到有相应进程为读而打开该FIFO
O_NONBLOCK enable:立刻返回失败,错误码为ENXIO

需要注意的是打开的文件描述符默认是阻塞的,大家可以写两个很简单的小程序测试一下,主要也就一条语句

int fd = open("p2", O_WRONLY);
假设p2是命名管道文件,把打开标志换成 O_RDONLY 就是另一个程序了,可以先运行RD程序,此时会阻塞,再在另一个窗口运行WR程序,此时两个程序都会从open返回成功。非阻塞时也不难测试,open时增加标志位就可以了。

需要注意的是 命令管道与匿名管道的读写规则是一样的,参见这里

下面示例命名管道完成拷贝文件的功能:

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
 
/*************************************************************************
    > File Name: process_.c
    > Author: Simba
    > Mail: dameng34@163.com
    > Created Time: Sat 23 Feb 2013 02:34:02 PM CST
 ************************************************************************/
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<signal.h>
#define ERR_EXIT(m) \
    do { \
        perror(m); \
        exit(EXIT_FAILURE); \
    } while(0)

int main(int argc, char *argv[])
{
    mkfifo("tp", 0644);
    int infd = open("Makefile", O_RDONLY);
    if (infd == -1)
        ERR_EXIT("open error");

int outfd;
    outfd = open("tp", O_WRONLY);
    if (outfd == -1)
        ERR_EXIT("open error");

char buf[1024];
    int n;
    while ((n = read(infd, buf, 1024)) > 0)
        write(outfd, buf, n);

close(infd);
    close(outfd);

return 0;
}

程序使用mkfifo函数创建一个命名管道文件tp,将Makefile 的文件都读取到tp文件中。

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
 
/*************************************************************************
    > File Name: process_.c
    > Author: Simba
    > Mail: dameng34@163.com
    > Created Time: Sat 23 Feb 2013 02:34:02 PM CST
 ************************************************************************/
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<signal.h>
#define ERR_EXIT(m) \
    do { \
        perror(m); \
        exit(EXIT_FAILURE); \
    } while(0)

int main(int argc, char *argv[])
{

int outfd = open("Makefile2", O_WRONLY | O_CREAT | O_TRUNC, 0644);
    if (outfd == -1)
        ERR_EXIT("open error");

int infd;
    infd = open("tp", O_RDONLY);
    if (infd == -1)
        ERR_EXIT("open error");

char buf[1024];
    int n;
    while ((n = read(infd, buf, 1024)) > 0)
        write(outfd, buf, n);

close(infd);
    close(outfd);
    unlink("tp"); // delete a name and possibly the file it refers to
    return 0;
}

可以看到跟上面的程序是相反的,即从tp读取到Makefile2,完成拷贝文件的功能,这里用到了一个unlink函数,属于inode_operations系列的一个函数,即inode引用计数减1,当引用计数为0且进程已经关闭文件描述符时,文件将被删除。

参考:《APUE》

命名管道FIFO和mkfifo函数的更多相关文章

  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(2)

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

  6. 命名管道FIFO及其读写规则

    一.匿名管道的一个限制就是只能在具有共同祖先的进程间通信命名管道(FIFO):如果我们想在不相关的进程之间切换数据,可以使用FIFO文件来做这项工作注意:命名管道是一种特殊类型文件.利用命令:$ mk ...

  7. 命名管道FIFO

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

  8. Linux 命名管道

    前文中笔者介绍了管道,本文接着介绍命名管道.文中演示所用环境为 Ubuntu 18.04 desktop. 命名管道(named pipe)又被称为先进先出队列(FIFO),是一种特殊的管道,存在于文 ...

  9. shell 匿名管道和命名管道

    管道的特点:如果管道中没有数据,那么取管道数据的操作就会滞留,直到管道内进入数据,然后读出后才会终止这一操作:同理,写入管道的操作如果没有读取管道的操作,这一动作也会滞留. 1,匿名管道 匿名管道使用 ...

随机推荐

  1. C++11中万能的可调用类型声明std::function<...>

    在C++11中,callable object 包括传统C函数,C++成员函数,函数对象(实现了()运算符的类的实例),lambda表达式(特殊函数对象)共4种.程序设计,特别是程序库设计时,经常需要 ...

  2. Sql Server的弱口令入侵测试以及防范

    我之所以要做这样的测试是因为这一切都是有背景的!!!被黑客黑的代价!!!伤心ing..... 背景: 测试: 物理机:Win7 虚拟机:xp 扫描工具(我想我最好不写扫描器的名字比较好): 密码之所以 ...

  3. 解决spark中遇到的数据倾斜问题

    一. 数据倾斜的现象 多数task执行速度较快,少数task执行时间非常长,或者等待很长时间后提示你内存不足,执行失败. 二. 数据倾斜的原因 常见于各种shuffle操作,例如reduceByKey ...

  4. THINKPHP URL模块大小写导致404问题

    最近我使用THINKPHP开发了一个项目在本地的集成开发环境wampserver做开发时并没有出现问题 上传到linux系统也没有出现问题,但当上传到windows平台上就出现了问题"文件4 ...

  5. python3插入数据

    python3插入数据 insert into table(column....) values('%s','%d') %d也是需要加单引号的:

  6. Diablo 3 Web API

    这是暴雪提供的WebAPI,能够通过网页的方式訪问玩家的用户信息.结构相当清晰,非常有借鉴价值. 应用JSON(JavaScript Object Notation)做数据交换,很好理解. 以我的暗黑 ...

  7. 翻译记忆软件-塔多思TRADO经典教程_5

    TRADOS新手必读 共有篇贴子 TRADOS新手必读   译海撷英系列之软件漫谈之TRADOS新手必读 作者:苏任 我很喜欢到翻译中国网站上来四处看看,一开始主要是关心应用资料和软件,后来就对网友的 ...

  8. Struts2(五)Action二配置

    一.method参数 action package com.pb.web.action; public class HourseAction { public String add(){ System ...

  9. Hibernate(五)基本数据类型

    一.Hibernate的基本数据类型 3种数据类型之间的对应关系 Hibernate映射类型 Java类型 标准SQL类型 integer java.lang.Integer INTEGER long ...

  10. Java的类名与文件名必须一致(转)

    原文:http://blog.csdn.net/shaoxiaoning/article/details/40424087 1.Java保存的文件名必须与类名一致: 2.如果文件中只有一个类,文件名必 ...