一、管道定义
当从一个进程连接数据流到另一个进程时,我们使用管道(pipe)。
二、进程管道
1、popen函数(在两个程序之间数据传递)
原型
1 #include <stdio.h> 2 FILE *popen(const char *command, const char *open_mode);
返回值是文件流指针
command表示命令行字符串,可以直接在shell中执行的那种
open_mode 为r表示调用程序可以使用stdio库函数(如fread)来读取被调用程序的输出
open_mode 为w表示调用程序可以使用stdio库函数(如fwrite)向被调用程序发送数据
2、pclose函数
原型
1 #include <stdio.h> 2 int pclose(FILE *stream_to_close);
参数为popen中返回的文件流指针。只有popen启动的进程结束后才返回。
返回值是关闭的文件流所在进程的退出码。
3、popen详解
用popen调用运行一个程序时,首先启动shell,然后将command字符串作为一个参数传给他shell。
好处:字符串参数扩展都是由shell解析的,可以用popen启动非常复杂的shell命令
坏处:每次多启动两个进程,成本略高,比正常调用慢一些
4、pipe调用(在父子进程之间)
原型
1 #include <unistd.h> 2 int pipe(int file_descriptor[2]);
参数:由两个整数类型的文件描述符组成的数组的指针
作用:该函数在数组中填上两个文件描述符后返回0,失败返回-1。
参数联系:写入file_descriptor[1]的所有数据都可以从file_descriptor[0]中读回来。数据基于队列先进先出(FIFO)
参数是文件描述符而不是文件流,所以用read和write函数
优势:
- 不需要启动shell,并且支持更多对读写的控制
- 当程序用fork调用创建新进程时,原先打开的文件描述符仍然打开。如果创建管道,再调用fork创建新进程,即可在进程间传递数据
可以在不同进程之间进行读写操作
5、父进程与子进程
利用execl调用在子进程中运行一个与父进程完全不同的程序
excel的参数:
- 要启动的程序
- argv[1]:程序名
- argv[1]:包含我们想要被调用程序去读取的文件描述符
- (char *)0:这个参数的作用是终止被调用程序的参数列表
1 (void)excel("pipe4","pipe4",buffer,(char *)0);
5.1、管道关闭后的读操作
没有数据可读时,read调用会阻塞。对一个已关闭写数据的管道做read调用将返回0而不是阻塞。
如果跨越fork调用使用管道,就会有两个文件描述符可以用于向管道写数据,只有父子进程中的针对管道的写文件描述符都关闭,管道才会被认为是关闭的,对管道的read调用才会失败。
5.2、把管道作为标准输入和标准输出
dup函数原型
1 #include <unistd.h> 2 int dup(int file_description); 3 int dup2(int file_description_one,int file_description_two);
dup调用创建的新文件描述符与作为他的参数的那个已有的文件描述符指向同一个文件(或管道)。对于dup来说,新文件描述符总是取最小的可用值。对于dup2来说,新文件描述符总是或者与参数file_description_two相同,或者是第一个大于该参数的值。
6、命名管道FIFO
命名管道可以在不相关的程序之间交换数据。
6.1、创建命名管道文件
1 mkfifo filename 2 //函数原型 3 #include <sys/types.h> 4 #include <sys/stat.h> 5 6 int mkfifo(const char *filename, mode_t mode | S_IFIFO, (dev_t 0);