博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
管道(下)
阅读量:2242 次
发布时间:2019-05-09

本文共 2459 字,大约阅读时间需要 8 分钟。

命名管道

简介

之前我们所介绍的是匿名管道,它独有的特点适用于具有血缘关系的进程之间实现进程间通信

命名管道则允许两个毫不相干的进程实现进程间通信。 
创建命名管道用mkfifo()

概念

管道的一个不足之处是没有名字,因此,只能用于具有亲缘关系的进程间通信,在命名管道(named pipe或FIFO)提出后,该限制得到了克服。FIFO不同于管道之处在于它提供一个路径名与之关联,以FIFO的文件形式存储于文件系统中。命名管道是一个设备文件,因此,即使进程与创建FIFO的进程不存在亲缘关系,只要可以访问该路径,就能够通过FIFO相互通信。值得注意的是,FIFO(first input first output)总是按照先进先出的原则操作,第一个被写入的数据将首先从管道中读出。

命名管道的创建与读写

Linux下有两种形式创建命名管道。一是在Shell下交互地建立一个命名管道,二是在程序中使用系统函数建里命名管道。Shell形式下可使用mknod或mkfifo命令,下面命令使用 
mknod创建一个命名管道: 
mknod namedpipe

创建命名管道的系统函数有两个:mknod和mkfifo。两个函数均定义在头文件sys/stat.h, 
函数原型如下:

#include 
#include
int mknod(const char *path,mode_t mod,dev_t dev); int mkfifo(const char *path,mode_t mode);

函数mknod参数中path为创建的命名管道的全路径名:mod为创建的命名管道的模式,指明其存取权限;dev为设备值,该值取决于文件创建的种类,它只在创建设备文件时才会找到。这两个函数调用成功都返回0,失败都返回-1。下面使用mknod函数创建了几个命名管道:

umask(0); if (mknod("/tmp/fifo",S_IFIFO | 0666) == -1) { perror("mkfifo error"); exit(1); } //函数mkfifo前两个参数的含义和mknod相同。下面是使用mkfifo的示例代码: umask(0); if (mkfifo("/tmp/fifo",S_IFIFO|0666) == -1) { perror("mkfifo error!"); exit(1); }

“S_IFIFO|0666”指明创建一个命名管道且存取权限为0666,即创建者、与创建者同组的用户、其他用户对该命名管道的访问权限都是可读可写(这里要注意umask对生成的管道文件权限响)。

命名管道创建后就可以使用了,命名管道和管道的使用方法基本是相同的。只是使用命名管道时,必须先调用open()将其打开。因为命名管道是一个存在于硬盘上的文件,而管道是存在于内存中的特殊文件

需要注意的是,调用open()打开命名管道的进程可能会被阻塞。但如果同时以读写方(O_RDWR)打开,则一定不会导致阻塞;如果以只读方式(O_RDONLY)打开,则调用open()函数的进程将会被阻塞直到有写方打开管道;同样以写方式(O_WRONLY)打开也会阻塞直到有读⽅式打开管道。

实现

我们现在创建两个没有血缘关系的进程,一个server用来读,一个client用来写。实现代码如下: 
server.c

#include 
#include
#include
#include
#include
#include
int main() { umask(0); if (mkfifo("./mypipe", 0666 | S_IFIFO) < 0){ perror("mkfifo"); return 1; } int fd = open("./mypipe", O_RDONLY); if (fd < 0){ perror("open"); return 2; } char buf[1024]; while (1){ ssize_t s = read(fd, buf, sizeof(buf)-1); if (s > 0){ buf[s-1] = 0; //cut down '\n' and add '0' to end of buf printf("client say : %s\n", buf); } else if(s == 0){ break; } } return 0; }

client.c

#include 
#include
#include
#include
#include
#include
int main() { int fd = open("./mypipe", O_WRONLY); if (fd < 0){ perror("open"); return 1; } char buf[1024]; while (1){ printf("please enter :" ); fflush(stdout); ssize_t s = read(0, buf, sizeof(buf)-1); if (s > 0){ buf[s] = 0; write(fd, buf, strlen(buf)); } } return 0; }

运行结果: 
注意:这里先运行server因为只有当管道创建好了才能让client往里面写。

fifo

你可能感兴趣的文章
"NetworkError: 400 Bad Request - http://172.16.47.117:8088/rhip/**/####t/approval?date=976
查看>>
mybatis 根据 数据库表 自动生成 实体
查看>>
C结构体、C++结构体、C++类的区别
查看>>
进程和线程的概念、区别和联系
查看>>
CMake 入门实战
查看>>
绑定CPU逻辑核心的利器——taskset
查看>>
Linux下perf性能测试火焰图只显示函数地址不显示函数名的问题
查看>>
c结构体、c++结构体和c++类的区别以及错误纠正
查看>>
Linux下查看根目录各文件内存占用情况
查看>>
A星算法详解(个人认为最详细,最通俗易懂的一个版本)
查看>>
利用栈实现DFS
查看>>
(PAT 1019) General Palindromic Number (进制转换)
查看>>
(PAT 1073) Scientific Notation (字符串模拟题)
查看>>
(PAT 1080) Graduate Admission (排序)
查看>>
Play on Words UVA - 10129 (欧拉路径)
查看>>
mininet+floodlight搭建sdn环境并创建简答topo
查看>>
【linux】nohup和&的作用
查看>>
Set、WeakSet、Map以及WeakMap结构基本知识点
查看>>
【NLP学习笔记】(一)Gensim基本使用方法
查看>>
【NLP学习笔记】(二)gensim使用之Topics and Transformations
查看>>