linux系统编程之管道(三):命名管道FIFO和mkfifo函数
进程间通信必须通过内核提供的通道,而且必须有一种办法在进程中标识内核提供的某个通道,前面讲过的匿名管道是用打开的文件描述符来标识的。如果要互相通信的几个进程没有从公共祖先那里继承文件描述符,它们怎么通信呢?内核提供一条通道不成问题,问题是如何标识这条通道才能使各进程都可以访问它?文件系统中的路径名是全局的,各进程都可以访问,因此可以用文件系统中的路径名来标识一个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时增加标志位就可以了。
需要注意的是 命令管道与匿名管道的读写规则是一样的,参见这里。
下面示例命名管道完成拷贝文件的功能:
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; char buf[ 1024]; close(infd); return 0; |
程序使用mkfifo函数创建一个命名管道文件tp,将Makefile 的文件都读取到tp文件中。
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); int infd; char buf[ 1024]; close(infd); |
可以看到跟上面的程序是相反的,即从tp读取到Makefile2,完成拷贝文件的功能,这里用到了一个unlink函数,属于inode_operations系列的一个函数,即inode引用计数减1,当引用计数为0且进程已经关闭文件描述符时,文件将被删除。
参考:《APUE》
linux系统编程之管道(三):命名管道FIFO和mkfifo函数相关推荐
- 【Linux系统编程】进程间通信之命名管道
00. 目录 文章目录 00. 目录 01. 命名管道概述 02. 命名管道创建 03. 命名管道特性 04. 命名管道非阻塞 05. 附录 01. 命名管道概述 无名管道,由于没有名字,只能用于亲缘 ...
- 【Linux系统编程】进程间通信之无名管道
00. 目录 文章目录 00. 目录 01. 管道概述 02. 管道创建函数 03. 管道的特性 04. 管道设置非阻塞 05. 附录 01. 管道概述 管道也叫无名管道,它是是 UNIX 系统 IP ...
- 【Linux系统编程】进程通信之管道
1.进程间通信介绍 1.1 进程通信的基本概念 在之前我们已经学习过进程地址空间.Linux 环境下,进程地址空间相互独立,每个进程各自有不同的用户地址空间.任何一个进程的全局变量在另一个进程中都看不 ...
- Linux系统编程27:进程间通信之管道的基本概念和匿名管道与命名管道及管道特性
文章目录 (1)管道是什么 (2)匿名管道 A:读端和写端 B:建立匿名管道的函数 C:最简单的进程间通信-演示 D:管道四大特性 E:管道的特点 F:从内核角度理解管道 G:管道总结 (3)命名管道 ...
- Linux系统编程:代码实现多重管道功能
代码功能介绍 我们在linux命令中可以使用 | 进行数据的流动,比如命令 ls -l | grep fifo | wc -l 如下图.这就是多重管道,今天我们用代码来实现类似的功能. 代码实现思路 ...
- 【Linux系统编程】可重入和不可重入函数
00. 目录 文章目录 00. 目录 01. 不可重入函数 02. 可重入函数 03. 判断条件 04. Linux常用可重入函数 05. 附录 01. 不可重入函数 在实时系统的设计中,经常会出现多 ...
- Linux系统编程之进程控制(进程创建,fork函数,进程中止,进程等待,程序替换)
进程创建 fork()------复制,返回值,写时复制 vfork()创建子进程-子进程与父进程共用同一块虚拟地址空间, 为了防止调用栈混乱,因此阻塞父进程直到子进程调用exit()退出或者进行程序 ...
- linux系统编程之进程(五):exec系列函数(execl,execlp,execle,execv,execvp)使用
本节目标: exec替换进程映像 exec关联函数组(execl.execlp.execle.execv.execvp) 一,exec替换进程映像 在进程的创建上Unix采用了一个独特的方法,它将进程 ...
- linux sleep alarm,Linux环境编程之信号处理(三、利用alarm()和pause()函数实现sleep()函数)...
sleep()是执行挂起一段时间,而alarm()函数是定时器,pause()函数则是挂起进程,当出现信号打断时,才会继续往前执行: 先来分享下alarm()函数,alarm()函数用来设置一个定时器 ...
- Linux系统编程34:进程信号之可重入函数,volatile关键字的作用和SIGHLD
文章目录 (1)可重入函数 (2)volatile关键字 A:背景知识 B:产生的问题 C:volatile关键字 (3)SIGHLD信号 A:复习僵尸进程 B:清理僵尸状态的新方法-SIGCHLD ...
最新文章
- 英雄多少钱steam_¥50元到手蓝宝石显卡?玩转GTAV轻松CSGO英雄联盟帧数144fps
- boost::lockfree::spsc_queue用法的测试程序
- C#将WebBowser控件替换为Chrome内核
- php解析js的 arraybuffer_JS的所谓的第七种数据类型Symbol
- zkServer.cmd 闪退
- C#.NET验证码智能识别学习笔记---01C#.NET验证码识别介绍
- Office groove系统的术语
- 从零基础入门Tensorflow2.0 ----四、16.tfrecord基础API使用
- C语言题目教室数量编程,北京理工大学网教室C语言编程题库及答案(绝对经典).doc...
- 《产品结构设计》——黎恢来,笔记
- 手机端html怎么复制到剪贴板,移动端和pc端的复制到剪贴板功能
- 华为自己的能力开放平台eSDK
- centos8安装中文版man帮助手册
- Oracle 数据库备份脚本
- 三万文字透视前瞻:区块链及隐私计算在传统企业中的技术认知与进阶思考
- dashu java_Java中的大数
- 【基础】(C语言)高精度算法
- 程序员都有一张早衰的脸?但入职前,谁还不是个吴彦祖呢?
- 穿越到东汉末年的Jackson
- 说服的传播模型(转载)
热门文章
- MySQL事务、MySQL索引、MySQL索引数据结构详解
- 『软件推荐』PanDownload出安卓版了
- JavaScript的全局作用域、全局对象window
- 每日一题 No.4 男女搭配干活不累
- 【CSS】 画优惠券锯齿边框样式
- 游戏客户端安全方案。
- cf(穿越火线)进游戏乱码问题解决方案
- 『方案』《女友十年精华》 ORC 图片 文字识别 详解
- QQ小程序 应用类型不匹配
- 对计算机专业最难的,计算机专业: 最好的7所大学! 也是全中国“最难考”的大学!...