阐述匿名管道和命名管道

概述管道是 unix系统 ipc的最古老的形式,所有的unix系统都提供此种通信。所谓的管道,也就是内核里面的一串缓存,从管道的一段写入的数据,实际上是缓存在内核中的,令一端读取,也就是从内核中读取这段数据。对于管道传输的数据是无格式的流且大小受限。对于管道来说,也分为匿名管道和命名管道,其中命名管道也被叫做 fifo,下面则分别阐述这两种管道。
匿名管道
默认情况下,在 shell命令执行过程中,任何一个命令都有一个标准输入设备(键盘)、标准输出设备(显示器)和标准输出设备(显示器),使用管道|可以将两个命令连接起来,从而改变标准的输入输出方式,下面是在 linux 端运行命令行的一个截图:
上述命令中的意思也就是,将ls命令得到的结果作为 grep tags命令的输入。
连接输入输出的中间设备即为一个管道文件,综上,也就是说使用管道可以将一个命令的输出作为另一个命令的输入(在运行的时候,一个命令将创建一个进程),而这种管道是临时的,命令执行完毕之后就会自动消失,这类管道称为 无名管道 。
匿名管道例子匿名管道在使用前要先创建,其函数的声明如下:
extern int pipe (int __pipedes[2]);此函数的参数是一个整型数组,如果执行成功,pipe 将存储两个整型文件描述符于__pipedes[0]和__pipedes[1]中,他们分别指向管道的两端。如果系统调用失败,则返回 -1。
读无名管道,该函数的声明如下:
extern ssize_t read (int __fd, void *__buf, size_t __nbytes);第一个参数fd为打开的文件描述符,buf为读出数据的存储位置,nbytes为读取数据的大小,调用 read 函数将从 fd 指向的文件描述符指定的打开文件中宏读 n 字节到 buf 指向的缓冲区内。
如果试图向已经填满的管道写入,系统会自动阻塞。一个管道不能同时被两个进程打开。
extern ssize_ t write(int __fd, __const void *__buf, size_t __n);从 buf指向的缓冲区中向管道中写入nbytes字节,且每次写入的内容都附件在管道的末端。
那要如何使用管道在两个进程之间通信呢,我们可以使用 fork()创建子进程,创建的子进程会复制父进程的文件描述符,这样就做到了两个进程各有两个fd[0]与fd[1],两个进程就可以通过各自的fd写入和读取同一个管道文件实现进程通信了,具体原理如下所示:
具体的例子如下所示:
#include#include#includeint main(int argc, char *argv[]){ pid_t pid; int temp; int pipedes[2]; char s[14] = test message!; char d[14]; if (pipe(pipedes) == -1) // 创建管道 { perror(pipe); exit(exit_failure); } if (pid == fork() == -1) { perror(fork); exit(exit_failure); } else if (pid == 0) // 子进程 { printf(now,write data to pipe\\n); if (write(pipedes[1], s, 14) == -1) // 写数据到管道 { perror(write); exit(exit_failure); } else { printf(the written data is:%s\\n,s); exit(exit_sucess); } } else if (pid > 0) // 父进程 { slepp(2); printf(now, read from pipe\\n); if ((read(pipedes[0], d, 14)) == -1) { perror(read); exit(exit_failure); } printf(the data from pipe is:%s\\n,d); } return 0;}
代码运行的结果如下所示:
命名管道命名管道又被称之为是 fifo ,未命名的管道只能在两个相关的进程之间使用,而且这两个相关的进程还要又一个共同创建了他们的祖先进程,但是,通过 fifo ,不相关的进程也能交换数据。
首先,介绍下是如何创建命名管道的:
extern int mkfifo (__const char *__path, __mode_t __mode);mkfifo会根据参数建立特殊的有名管道文件,该文件必须不存在,而参数mode为该文件的权限。
下面是一个使用命名管道进行进程间通信的例子,例子分为两个程序,分别是读部分和写部分,首先看先往管道写数据的代码,代码如下所示:
#include #include #include #include #include #include int main() { int fd; // fifo file path char * myfifo = /tmp/myfifo; // creating the named file(fifo) // mkfifo(, ) mkfifo(myfifo, 0666); char arr1[80], arr2[80]; while (1) { // open fifo for write only fd = open(myfifo, o_wronly); printf(the fd is:%d\\n,fd); // take an input arr2ing from user. // 80 is maximum length fgets(arr2, 80, stdin); // write the input arr2ing on fifo // and close it write(fd, arr2, strlen(arr2)+1); close(fd); // open fifo for read only fd = open(myfifo, o_rdonly); // read from fifo read(fd, arr1, sizeof(arr1)); // print the read message printf(user2: %s, arr1); close(fd); } return 0; }然后是先往管道读数据的代码,代码如下所示:
#include #include #include #include #include #include int main() { int fd1; // fifo file path char * myfifo = /tmp/myfifo; char str1[80], str2[80]; while (1) { // first open in read only and read fd1 = open(myfifo,o_rdonly); printf(the fd is:%d\\n,fd1); read(fd1, str1, 80); // print the read string and close printf(user1: %s, str1); close(fd1); // now open in write mode and write // string taken from user. fd1 = open(myfifo,o_wronly); fgets(str2, 80, stdin); write(fd1, str2, strlen(str2)+1); close(fd1); } return 0; }下面是代码运行的一个结果:
说明一下,就是说当运行 write程序的时候,会创建fifo文件,命名管道,然后,在 write文件中就执行open操作,但是,这里存在的一个问题就是,因为在运行 write程序的时候,没有进程打开读端,也就阻塞了 open函数的运行,只有运行read操作,以读的方式读取管道的数据,这样才能使得write中的open函数继续执行。
综上,也就是命名管道在进程中通信的一个例子。
小结上述就是本次进程通信中关于管道的相关内容,其中就包括匿名管道以及命名管道,他们之间存在着差别吗,也各有各的应用,本次的分享就到这里啦~

数码摄像机液晶显示屏
工业树莓派新品S/SE系列:更强大、更优质 、更具优势!
由PSPICE过渡至NIMultisim
鸿蒙系统还未正式换装 vivo开始“搞事情”
防火墙的用户数限制
阐述匿名管道和命名管道
华为昇腾310芯片在乌镇获奖,全面拥抱AI
HDZR2008变压器直流电阻及有载分接开关综合测试仪直阻测试方法
特斯拉中国第二工厂落地沈阳?
最后期限倒计时,华为“国产替代”速度亟待加快
NVIDIA合作伙伴发布采用NVIDIA BlueField DPU的新款服务器
【虹科新闻】广师大汽车与交通学院院长、书记等一行人来访虹科进行科研洽谈
优化微型投影系统亮度的三个因素分析
微软推出两款廉价型笔记本电脑,搭载骁龙7c处理器
区块链怎样帮节能环保领域改头换面
java是什么如何学习?学习java可以做什么
华为与中国港口协会、中国交通通信信息中心签署战略合作协议
荣耀9什么时候上市?荣耀9最新消息:荣耀9工信部谍照曝光,售价比小米6还便宜!
这四个技术载体,是企业能否演化成功的决定因素
区块链如何提升游戏生态的价值