如何创建管道——pipe
我们有一个这样的场景:主程序希望与子程序进行通信。我们用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相关推荐
- linux操作系统进程间通信IPC之管道pipe及FIFO
linux环境下,各进程相互独立,如果想要交换两个进程之间的数据,需要通过内核,在内存中提供一个缓存区,一个进程往缓存区中写数据,一个往缓存区读数据,内核提供的这种机制称为进程间通信(IPC),常见的 ...
- revit二次开发 创建管道三通,管道四通。两根管、三根管、四根管
创建单跟水管 /// <summary>/// 创建水管Pipe/// </summary>/// <returns></returns>public ...
- linux系统调用创建无名管道,linux 无名管道pipe和有名管道FIFO
1.管道(pipe) 管道是进程间通信的主要手段之一.一个管道实际上就是个只存在于内存中的文件,对这个文件的操作要通过两个已经打开文件进行,它们分别代表管道的两端.管道是一种特殊的文件,它不属于某一种 ...
- linux进程间通信:无名管道 pipe
文章目录 内核层实现 结构 通信原理 特点 使用 函数声明 使用实例 单向通信 双向通信 编程注意事项 管道中无数据时读操作会阻塞 将管道的写端句柄关闭,不会影响读端数据读取 管道中没有数据,写操作关 ...
- Java-NIO(九):管道 (Pipe)
Java NIO 管道是2个线程之间的单向数据连接.Pipe有一个source通道和一个sink通道.数据会被写到sink通道,从source通道读取. 代码使用示例: 1 @Test 2 publi ...
- NIO详解(十一):线程间通信管道Pipe
1. 概述 Java NIO 管道是2个线程之间的单向数据连接.Pipe有一个source通道和一个sink通道.数据会被写到sink通道,从source通道读取.下面是Pipe原理的图示: 当有两个 ...
- 进程间的通信方式(二):管道Pipe和命令管道FIFO
1.概述 管道是最初的Unix IPC通信,可追溯到1973年的Unix第三版.尽管对于许多操作来说很有用,但它们的根本局限于没有名字,只能由亲缘关系的进程使用.这一点随着FIFO的加入System ...
- pipe 半双工_pipe 半双工_Linux管道PIPE的原理和应用
Linux中进程的通信方式有信号,管道,共享内存,消息队列socket等.其中管道是*nix系统进程间通信的最古老形式,所有*nix都提供这种通信方式.管道是一种半双工的通信机制,也就是说,它只能一端 ...
- 【Linux系统编程学习】匿名管道pipe与有名管道fifo
此为牛客Linux C++和黑马Linux系统编程课程笔记. 0. 关于进程通信 Linux环境下,进程地址空间相互独立,每个进程各自有不同的用户地址空间.任何一个进程的全局变量在另一个进程中都看不到 ...
- 管道(Pipe)/createPipe
BOOL CreatePipe(PHANDLE hReadPipe, // 指向读句柄的指针 PHANDLE hWritePipe, // 指向写句柄的指针 LPSECURITY_ATTRIBUTES ...
最新文章
- 解读:数据科学、机器学习和AI的区别
- 【Xamarin】揭秘生成配置
- POI的入门:创建单元格设置数据
- 学习笔记26_MVC前台强类型参数
- C#如何获得系统时间
- C语言之获取32字节随机数的字符串
- c语言time_t转oletime,DateTimeFormatter可以格式化日期,但不能读取它自己的格式
- 域控启用ldap_Windows 10 (的域控制器 LDAP 服务器) - Windows security | Microsoft Docs
- Python学习笔记——输入与输出用法
- 如何在映像更改后升级docker容器
- win11更新为何检测不到 Windows11更新检测不到的解决方法
- java方法重载和重载方法_Java中的重载与重载
- 11.docker tag
- 未来教育计算机二级考生文件夹打不开,未来教育计算机二级office题库
- python编写摇骰子游戏_Python使用tkinter实现摇骰子小游戏功能的代码
- 强烈推荐收藏!3W 字Python 操作 Excel 报表自动化指南
- js对象扁平化:Javascript对象进行扁平化处理
- 【Proteus仿真】【51单片机】音乐盒电子琴设计
- 如何批量将 Word 文档转为 ePub 格式
- class文件魔数CAFEBABE的由来