我们有一个这样的场景:主程序希望与子程序进行通信。我们用pipe()函数为他们创建管道,这样他们就可以通过管道来通信了。
为了演示方便我们只考虑:
子程序把数据发送到父进程中来的情况。因此要用管道把子进程的标准输出和父进程的标准输入连接起来

我们将用pipe()函数建立管道。每当我们打开数据流时,它都会加入描述符表。pipe()函数也是如此,它创建两条相连的数据流,并把它们加到描述符表中,然后只要我们往其中一条数据流中写数据,就可以从另一条数据流中读取。pipe()在描述符表中创建这两项时,会把它们的文件描述符存放在一个包含两个元素的数组中。

int fd[2];  //文件描述符将保存在fd数组中。
if(pipe(fd) == -1){fprintf(stderr,"Can't create the pipe!");exit(2);
}

pipe()函数创建了管道,并返回了两个描述符:fd[0]用来从管道读数据,fd[1]用来向管道写数据。我们将在父、子进程中使用这两个描述符。

我们通过一个实例来说明:
aaa.c

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>void open_url(char *url);
int main(){int fd[2];if(pipe(fd) == -1){ //创建管道,并把文件描述符保存在fd[0]和fd[1]中。fprintf(stderr,"%s\n","Can't create the pipe!");exit(1);}pid_t pid = fork();if(pid == -1){fprintf(stderr,"%s\n","Can't fork process!");exit(2);}if(!pid){ //能进这里,表示已在子进程中dup2(fd[1],1); //把标准输出设为管道写入端close(fd[0]); //因为子进程不会去读取管道,因此将读取端关闭if(execl("bbb","bbb",NULL) == -1){fprintf(stderr,"%s\n","Can't open subprocess");exit(1);}}//从这开始是属于父进程的dup2(fd[0],0);  //把标准输入设为管道读取端close(fd[1]);//因为父进程不会向子进程发数据,无需写入管道,因此将写入端关闭char line[255];while(fgets(line,255,stdin)){open_url(line+1);}return 0;
}
void open_url(char *url){char launch[255];//sprintf(launch,"cmd /c start %s",url);  //在windows上打开网页// system(launch);sprintf(launch,"x-www-browser '%s' &",url);//在Linux上打开网页system(launch);//sprintf(launch,"open '%s'",url); //在Mac上打开网页//system(launch);
}

bbb.c

#include <stdio.h>
int main(){char line[255];fgets(line,255,stdin);printf("%s",line);return 0;
}

编译运行:

~/Desktop/MyC$ gcc aaa.c -o aaa
~/Desktop/MyC$ gcc bbb.c -o bbb
~/Desktop/MyC$ ./aaa
|

查进程信息:

~$ ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
wong     17525  5363  0 17:47 pts/1    00:00:00 ./aaa
wong     17526 17525  0 17:47 pts/1    00:00:00 bbb

输入地址按回车:

~/Desktop/MyC$ ./aaa
http://www.baidu.com

接着就会打开浏览器。

管道是文件吗?这不一定。这取决于操作系统创建管道的方式,一般来说用pipe()创建的管道都不是文件。而创建基于文件的管道,通常叫做有名管道或FIFO文件(先进先出文件)。

因为基于文件的管道有名字,所以两个进程只要知道管道的名字也能用它来通信,即使它们是非父子进程关系。要使用有名管道,可以通过使用mkfifo()系统调用来实现。如果不是通过文件来实现管道的话,那通常是用内存,数据写到内存某个位置,然后再从另一个位置读取。

如果试图读取一个空的管道,也不会发生错误,因为程序会等待管道中出现东西。

父进程是如何知道子进程结束的?
其实,当子进程结束时,管道会关闭。fgets()将会收到EOF(End Of File,文件结束符) ,于是fgets()函数返回0,循环就结束了。

另外,管道只能单向通信。但是可以通过创建两个管道,一个从父进程连接到子进程,另一个从子进程连接到父进程来实现双向通信 。

谢谢阅读!

如何创建管道——pipe相关推荐

  1. linux操作系统进程间通信IPC之管道pipe及FIFO

    linux环境下,各进程相互独立,如果想要交换两个进程之间的数据,需要通过内核,在内存中提供一个缓存区,一个进程往缓存区中写数据,一个往缓存区读数据,内核提供的这种机制称为进程间通信(IPC),常见的 ...

  2. revit二次开发 创建管道三通,管道四通。两根管、三根管、四根管

    创建单跟水管 /// <summary>/// 创建水管Pipe/// </summary>/// <returns></returns>public ...

  3. linux系统调用创建无名管道,linux 无名管道pipe和有名管道FIFO

    1.管道(pipe) 管道是进程间通信的主要手段之一.一个管道实际上就是个只存在于内存中的文件,对这个文件的操作要通过两个已经打开文件进行,它们分别代表管道的两端.管道是一种特殊的文件,它不属于某一种 ...

  4. linux进程间通信:无名管道 pipe

    文章目录 内核层实现 结构 通信原理 特点 使用 函数声明 使用实例 单向通信 双向通信 编程注意事项 管道中无数据时读操作会阻塞 将管道的写端句柄关闭,不会影响读端数据读取 管道中没有数据,写操作关 ...

  5. Java-NIO(九):管道 (Pipe)

    Java NIO 管道是2个线程之间的单向数据连接.Pipe有一个source通道和一个sink通道.数据会被写到sink通道,从source通道读取. 代码使用示例: 1 @Test 2 publi ...

  6. NIO详解(十一):线程间通信管道Pipe

    1. 概述 Java NIO 管道是2个线程之间的单向数据连接.Pipe有一个source通道和一个sink通道.数据会被写到sink通道,从source通道读取.下面是Pipe原理的图示: 当有两个 ...

  7. 进程间的通信方式(二):管道Pipe和命令管道FIFO

    1.概述 管道是最初的Unix IPC通信,可追溯到1973年的Unix第三版.尽管对于许多操作来说很有用,但它们的根本局限于没有名字,只能由亲缘关系的进程使用.这一点随着FIFO的加入System  ...

  8. pipe 半双工_pipe 半双工_Linux管道PIPE的原理和应用

    Linux中进程的通信方式有信号,管道,共享内存,消息队列socket等.其中管道是*nix系统进程间通信的最古老形式,所有*nix都提供这种通信方式.管道是一种半双工的通信机制,也就是说,它只能一端 ...

  9. 【Linux系统编程学习】匿名管道pipe与有名管道fifo

    此为牛客Linux C++和黑马Linux系统编程课程笔记. 0. 关于进程通信 Linux环境下,进程地址空间相互独立,每个进程各自有不同的用户地址空间.任何一个进程的全局变量在另一个进程中都看不到 ...

  10. 管道(Pipe)/createPipe

    BOOL CreatePipe(PHANDLE hReadPipe, // 指向读句柄的指针 PHANDLE hWritePipe, // 指向写句柄的指针 LPSECURITY_ATTRIBUTES ...

最新文章

  1. 解读:数据科学、机器学习和AI的区别
  2. 【Xamarin】揭秘生成配置
  3. POI的入门:创建单元格设置数据
  4. 学习笔记26_MVC前台强类型参数
  5. C#如何获得系统时间
  6. C语言之获取32字节随机数的字符串
  7. c语言time_t转oletime,DateTimeFormatter可以格式化日期,但不能读取它自己的格式
  8. 域控启用ldap_Windows 10 (的域控制器 LDAP 服务器) - Windows security | Microsoft Docs
  9. Python学习笔记——输入与输出用法
  10. 如何在映像更改后升级docker容器
  11. win11更新为何检测不到 Windows11更新检测不到的解决方法
  12. java方法重载和重载方法_Java中的重载与重载
  13. 11.docker tag
  14. 未来教育计算机二级考生文件夹打不开,未来教育计算机二级office题库
  15. python编写摇骰子游戏_Python使用tkinter实现摇骰子小游戏功能的代码
  16. 强烈推荐收藏!3W 字Python 操作 Excel 报表自动化指南
  17. js对象扁平化:Javascript对象进行扁平化处理
  18. 【Proteus仿真】【51单片机】音乐盒电子琴设计
  19. 如何批量将 Word 文档转为 ePub 格式
  20. class文件魔数CAFEBABE的由来

热门文章

  1. 阅读基地畅销榜数据抓取
  2. 泛微OA流程自动汇总触发(流程触发集成)
  3. 快门(曝光时间)、光圈、感光度(ISO)的关系
  4. mysqldatareader什么意思_Mysql的MySqlDataReader对于MysqlConnection是独占式
  5. 项目开发流程_以房地产项目总的视角,谈谈项目开发流程
  6. 计算机WIN7安装,教您win7旗舰版安装教程
  7. 四级网络工程师笔记-计算机网络(下)
  8. 牛客竞赛语法入门班选择结构习题【完结】
  9. leetcode 三数之和
  10. iOS -显示隐藏文件