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

linux系统编程之管道(三):命名管道FIFO和mkfifo函数相关推荐

  1. 【Linux系统编程】进程间通信之命名管道

    00. 目录 文章目录 00. 目录 01. 命名管道概述 02. 命名管道创建 03. 命名管道特性 04. 命名管道非阻塞 05. 附录 01. 命名管道概述 无名管道,由于没有名字,只能用于亲缘 ...

  2. 【Linux系统编程】进程间通信之无名管道

    00. 目录 文章目录 00. 目录 01. 管道概述 02. 管道创建函数 03. 管道的特性 04. 管道设置非阻塞 05. 附录 01. 管道概述 管道也叫无名管道,它是是 UNIX 系统 IP ...

  3. 【Linux系统编程】进程通信之管道

    1.进程间通信介绍 1.1 进程通信的基本概念 在之前我们已经学习过进程地址空间.Linux 环境下,进程地址空间相互独立,每个进程各自有不同的用户地址空间.任何一个进程的全局变量在另一个进程中都看不 ...

  4. Linux系统编程27:进程间通信之管道的基本概念和匿名管道与命名管道及管道特性

    文章目录 (1)管道是什么 (2)匿名管道 A:读端和写端 B:建立匿名管道的函数 C:最简单的进程间通信-演示 D:管道四大特性 E:管道的特点 F:从内核角度理解管道 G:管道总结 (3)命名管道 ...

  5. Linux系统编程:代码实现多重管道功能

    代码功能介绍 我们在linux命令中可以使用 | 进行数据的流动,比如命令 ls -l | grep fifo | wc -l 如下图.这就是多重管道,今天我们用代码来实现类似的功能. 代码实现思路 ...

  6. 【Linux系统编程】可重入和不可重入函数

    00. 目录 文章目录 00. 目录 01. 不可重入函数 02. 可重入函数 03. 判断条件 04. Linux常用可重入函数 05. 附录 01. 不可重入函数 在实时系统的设计中,经常会出现多 ...

  7. Linux系统编程之进程控制(进程创建,fork函数,进程中止,进程等待,程序替换)

    进程创建 fork()------复制,返回值,写时复制 vfork()创建子进程-子进程与父进程共用同一块虚拟地址空间, 为了防止调用栈混乱,因此阻塞父进程直到子进程调用exit()退出或者进行程序 ...

  8. linux系统编程之进程(五):exec系列函数(execl,execlp,execle,execv,execvp)使用

    本节目标: exec替换进程映像 exec关联函数组(execl.execlp.execle.execv.execvp) 一,exec替换进程映像 在进程的创建上Unix采用了一个独特的方法,它将进程 ...

  9. linux sleep alarm,Linux环境编程之信号处理(三、利用alarm()和pause()函数实现sleep()函数)...

    sleep()是执行挂起一段时间,而alarm()函数是定时器,pause()函数则是挂起进程,当出现信号打断时,才会继续往前执行: 先来分享下alarm()函数,alarm()函数用来设置一个定时器 ...

  10. Linux系统编程34:进程信号之可重入函数,volatile关键字的作用和SIGHLD

    文章目录 (1)可重入函数 (2)volatile关键字 A:背景知识 B:产生的问题 C:volatile关键字 (3)SIGHLD信号 A:复习僵尸进程 B:清理僵尸状态的新方法-SIGCHLD ...

最新文章

  1. 英雄多少钱steam_¥50元到手蓝宝石显卡?玩转GTAV轻松CSGO英雄联盟帧数144fps
  2. boost::lockfree::spsc_queue用法的测试程序
  3. C#将WebBowser控件替换为Chrome内核
  4. php解析js的 arraybuffer_JS的所谓的第七种数据类型Symbol
  5. zkServer.cmd 闪退
  6. C#.NET验证码智能识别学习笔记---01C#.NET验证码识别介绍
  7. Office groove系统的术语
  8. 从零基础入门Tensorflow2.0 ----四、16.tfrecord基础API使用
  9. C语言题目教室数量编程,北京理工大学网教室C语言编程题库及答案(绝对经典).doc...
  10. 《产品结构设计》——黎恢来,笔记
  11. 手机端html怎么复制到剪贴板,移动端和pc端的复制到剪贴板功能
  12. 华为自己的能力开放平台eSDK
  13. centos8安装中文版man帮助手册
  14. Oracle 数据库备份脚本
  15. 三万文字透视前瞻:区块链及隐私计算在传统企业中的技术认知与进阶思考
  16. dashu java_Java中的大数
  17. 【基础】(C语言)高精度算法
  18. 程序员都有一张早衰的脸?但入职前,谁还不是个吴彦祖呢?
  19. 穿越到东汉末年的Jackson
  20. 说服的传播模型(转载)

热门文章

  1. MySQL事务、MySQL索引、MySQL索引数据结构详解
  2. 『软件推荐』PanDownload出安卓版了
  3. JavaScript的全局作用域、全局对象window
  4. 每日一题 No.4 男女搭配干活不累
  5. 【CSS】 画优惠券锯齿边框样式
  6. 游戏客户端安全方案。
  7. cf(穿越火线)进游戏乱码问题解决方案
  8. 『方案』《女友十年精华》 ORC 图片 文字识别 详解
  9. QQ小程序 应用类型不匹配
  10. 对计算机专业最难的,计算机专业: 最好的7所大学! 也是全中国“最难考”的大学!...