Linux 命名管道
前文中笔者介绍了管道,本文接着介绍命名管道。文中演示所用环境为 Ubuntu 18.04 desktop。
命名管道(named pipe)又被称为先进先出队列(FIFO),是一种特殊的管道,存在于文件系统中。命名管道与管道非常类似,但是又有自身的显著特征:
- 命名管道可以用于任何两个进程间的通信,而不限于同源的两个进程。
- 命名管道作为一种特殊的文件存放在文件系统中,而不是像管道那样存放在内核中。当进程对命名管道的使用结束后,命名管道依然存在于文件系统中,除非对其进行删除操作,否则该命名管道不会自行消失。
和管道一样,命名管道也只能用于数据的单向传输,如果要用命名管道实现两个进程间数据的双向传输,建议使用两个单向的命名管道。
创建命名管道
在命令行上创建命名管道
可以通过命令行命令 mkfifo 或 mknod 创建命名管道:
$ mkfifo /tmp/testp
$ mknod /tmp/testp p
可以通过 ls 命令查看命名管道的文件属性:

输出中的第一个字符为 p,表示这个文件的类型为管道。最后的 | 符号是有 ls 命令的 -F 选项添加的,也表示这个一个管道。
在程序中创建命名管道
在程序中创建命名管道,可以使用 mkfifo 函数,其签名如下:
#include <sys/types.h>
#include <sys/stat.h> int mkfifo(const char *pathname, mode_t mode);
参数 pathname 是一个字符串指针,用于存放命名管道的文件路径。参数 mode 用于表示指定所创建文件的权限。该函数调用成功时返回 0;调用失败时返回 -1。
mkfifo 函数是一个专门用来创建命名管道的函数,而另外一个函数 mknod 却可以兼职创建命名文件,其函数签名如下:
#include <sys/types.h>
#include <sys/stat.h> int mknod(char *pathname, mode_t mode, dev_t dev);
创建命名管道只是 mknod 函数的功能之一,它的前两个参数和 mkfifo 函数相同。在创建命名管道时,为第三个参数 dev 传递 0 就可以了。该函数调用成功时返回 0;调用失败时返回 -1。
在程序中使用命名管道
下面的 demo 模拟一个生产者进程和消费者进程,二者通过命名管道传输数据。生产者的代码如下:
#include <limits.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h> #define FIFO_NAME "/tmp/testp"
#define BUFFER_SIZE 4096
#define TEN_MEG (1024 * 1024 * 10) int main(void)
{
int pipe_fd;
int res;
int open_mode = O_WRONLY;
int bytes_sent = ;
char buffer[BUFFER_SIZE + ]; if(access(FIFO_NAME, F_OK) == -)
{
res = mkfifo(FIFO_NAME, );
if(res != )
{
fprintf(stderr, "Could not create fifo %s\n", FIFO_NAME);
exit(EXIT_FAILURE);
}
} printf("Process %d opening FIFO O_WRONLY\n", getpid());
pipe_fd = open(FIFO_NAME, open_mode);
printf("Process %d opened fd %d\n", getpid(), pipe_fd); if(pipe_fd != -)
{
while(bytes_sent < TEN_MEG)
{
res = write(pipe_fd, buffer, BUFFER_SIZE);
if(res == -)
{
fprintf(stderr, "Write error on pipe\n");
exit(EXIT_FAILURE);
}
bytes_sent += res;
}
(void)close(pipe_fd);
}
else
{
exit(EXIT_FAILURE);
}
printf("Process %d finished\n", getpid());
exit(EXIT_SUCCESS);
}
把上面的代码保存到文件 namedpipedemo.c 中。
消费者的代码如下:
#include <limits.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h> #define FIFO_NAME "/tmp/testp"
#define BUFFER_SIZE 4096 int main(void)
{
int pipe_fd;
int res;
int open_mode = O_RDONLY;
int bytes_read = ;
char buffer[BUFFER_SIZE + ]; memset(buffer, '\0', sizeof(buffer)); printf("Process %d opening FIFO O_RDONLY\n", getpid());
pipe_fd = open(FIFO_NAME, open_mode);
printf("Process %d opened fd %d\n", getpid(), pipe_fd); if(pipe_fd != -)
{
do
{
res = read(pipe_fd, buffer, BUFFER_SIZE);
bytes_read += res;
} while (res > );
(void)close(pipe_fd);
}
else
{
exit(EXIT_FAILURE);
}
printf("Process %d finished, %d bytes read\n", getpid(), bytes_read);
exit(EXIT_SUCCESS);
}
把上面的代码保存到文件 namedpipedemo2.c 中。并分别编译这两个程序:
$ gcc -Wall namedpipedemo.c -o pipe1
$ gcc -Wall namedpipedemo2.c -o pipe2
先在一个终端中执行生产者:

然后在另一个终端中执行消费者:

结果是二者完成数据传输后都返回了:

删除命名管道
删除命名管道和删除一个普通文件没有什么区别:
$ rm /tmp/testp
这就可以了!
参考:
《Linux 程序设计》
《Linux 环境下 C 编程指南》
Linux 命名管道的更多相关文章
- linux命名管道通信过程
前一个道,这节学习命名管道. 二命名管道 无名管道仅仅能用来在父子进程或兄弟进程之间进行通信,这就给没有亲缘关系的进程之间数据的交换带来了麻烦.解决问题就是本节要学习的还有一种管道通信:命名管道. 命 ...
- Linux学习笔记(13)-进程通信|命名管道
匿名管道只能在具有亲属关系的进程间通信,那么如果想要在不具有亲戚关系,想在陌生人之间通信,那又该怎么办呢? 别慌,Linux身为世界上*强大的操作系统,当然提供了这种机制,那便是命名管道-- 所谓命名 ...
- Linux进程间通信(四):命名管道 mkfifo()、open()、read()、close()
在前一篇文章—— Linux进程间通信 -- 使用匿名管道 中,我们看到了如何使用匿名管道来在进程之间传递数据,同时也看到了这个方式的一个缺陷,就是这些进程都由一个共同的祖先进程启动,这给我们在不相关 ...
- 【LINUX/UNIX网络编程】之使用消息队列,信号量和命名管道实现的多进程服务器(多人群聊系统)
RT,使用消息队列,信号量和命名管道实现的多人群聊系统. 本学期Linux.unix网络编程的第三个作业. 先上实验要求: 实验三 多进程服务器 [实验目的] 1.熟练掌握进程的创建与终止方法: 2 ...
- Linux进程间通信——使用命名管道
在前一篇文章——Linux进程间通信——使用匿名管道中,我们看到了如何使用匿名管道来在进程之间传递数据,同时也看到了这个方式的一个缺陷,就是这些进程都由一个共同的祖先进程启动,这给我们在不相关的的进程 ...
- Linux学习记录--命名管道通信
命名管道通信 什么是命名管道 一个主要的限制是,它是匿名管道的应用还没有名字,因此,只有它可以用于进程间通信的方式与亲缘关系.在命名管道(named pipe或FIFO)提出后,该限制得到了克服.FI ...
- Linux环境进程间通信(一):管道及命名管道
linux下进程间通信的几种主要手段: 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允 ...
- 【linux】mkfifo 命令创建命名管道实现进程之间通信
mkfifo 命令 mkfifo命令创建一个FIFO特殊文件,是一个命名管道(可以用来做进程之间通信的桥梁) 管道也是一种文件,一般是linux中的一个页大小,4k,管道数据一旦被读取就没了.(管道大 ...
- Linux中的pipe(管道)与named pipe(FIFO 命名管道)
catalogue . pipe匿名管道 . named pipe(FIFO)有名管道 1. pipe匿名管道 管道是Linux中很重要的一种通信方式,是把一个程序的输出直接连接到另一个程序的输入,常 ...
随机推荐
- MHA在监控和故障转移时都做了什么
转自 https://blog.csdn.net/ashic/article/details/75645479 以下是MHA(masterha_manager)在监控和故障切换上的基本流程 验证复制配 ...
- vmstat/top/iostat/route/sar 常用命令
[vmstat]Virtual Meomory Statistics(虚拟内存统计)的缩写,可对操作系统的虚拟内存.进程.CPU活动进行监控.是对系统的整体情况进行统计,不足之处是无法对某个进程进行深 ...
- SQL Server之批量清理数据库的死锁
DECLARE killspid CURSOR FOR (SELECT CONVERT(VARCHAR(100), request_session_id) FROM sys.dm_tran_l ...
- 原创【cocos2d-x】CCMenuItemToggle 在lua中的使用
说明:1,所使用的cocos2dx版本为2.1.3 ;09:48:05 2,本人仍是在学习中的小菜鸟,此博客只是为了记录我学习过程中的点滴,同时也希望同样lua开发的童鞋,一起交流: 3,本人whj0 ...
- Appium(一):java环境、AndroidSDK环境
1. java环境 java的下载和安装可以看我以前写的Java基础:<java下载和安装>. 2. AndroidSDK环境 2.1 AndroidSDK下载 我们进入:https:// ...
- OOAD 面向对象的分析与设计
OOAD 面向对象的分析与设计 OOA-----分析阶段(针对业务问题清晰视图, 列出系统完成任务, 整理业务的公共词汇, 列出解决业务的解决方法) O ...
- 【Java】导入项目时,出现The project cannot be built until build path errors are resolved错误解决方法
先检查jar包,jar包的地址如果不一样需要remove后重新导入的,右键项目→Build Path. 看额外的jar包有没有×,地址正不正确,要是不正确,remove错误jar包,再点击Add Ex ...
- 使用Castle DynamicProxy (AOP)
在本文中,我将引导您了解.NET环境中的面向方面编程(AOP)概念,以及如何使用Castle DynamicProxy创建和附加方面.在我们开始之前,让我快速介绍AOP和 IoC.如果您已经熟悉这些 ...
- Charles 使用笔记
一.介绍 Charles 属于抓包软件. Charles 多平台支持,mac.windows.linux. Charles 是收费软件,可以免费试用 30 天.试用期过后,未付费的用户仍然可以继续使 ...
- ej3-0开端
开始 编码多年,总有一些最佳实践,Java也是,比如设计模式,比如Effective Java 3 (ej3) . 设计模式先后看过<大话设计模式>,<HeadFirst 设计模式& ...