linux程序设计——进程管道(第十三章)

原创 2015年07月08日 21:25:35

第13章    进程间通信:管道

在第11章,看到了一种在两个进程间发送消息的非常简单的方法:使用信号量.创建通知时间,通过它引起响应,但传送的信息只限于一个信号值.
在本章中,将介绍管道,通过它进程之间可以交换更有用的数据.

13.1    什么是管道

当从一个进程连接数据流到另一个进程时,使用术语管道(pipe)。通常是把一个进程的输出通过管道连接到另一个进程的输入
这实际上就是把一个进程的输出直接传递给另一个进程的输入。对于shell命令来说,命令的连接是通过管道字符来完成的,如下所示:
cmd1 | cmd2
shell负责安排两个命令的标准输入和标准输出。
cmd1的标准输入来自终端键盘
cmd1的标准输出传递给cmd2,作为它的标准输入
cmd2的标准输出连接到终端屏幕
shell所做的工作实际上就是对标准输入和标准输出流进行了重新连接,使数据流从键盘输入通过两个命令最终输出到屏幕上。

13.2    进程管道

可能最简单的在两个程序之间传递数据的方法是使用popen和pclose函数了。它们的原型如下所示:
#include <stdio.h>
FILE *popen(const char *command, const char *open_mode);
int pclose(FILE *stream_to_close);

1.popen函数

popen函数允许一个程序将另一个程序作为新进程来启程,并可以传递数据给它或者通过它接收数据。command字符串是要运行的程序名和相应的参数。open_mode必须是"r"或者"w"。
如果open_mode是"r"被调用程序的输出就可以被调用函数使用,调用程序利用popen函数返回的FILE*文件流指针,就可以通过常用的stdio库函数(如fread)来读取被调用程序的输出。如果open_mode是"w"调用程序就可以用fwrite调用向被调用程序发送数据,而被调用程序就可以在自己的标准输入上读取这些数据,被调用的程序通常不会意识到自己正在从另一个进程读取数据,它只是在标准输入流上读取数据,然后做出相应的操作。
每个popen调用都必须指定"r"或"w",在popen函数的标准实现中不支持任何其他选项。这意味着不能调用另一个程序并同时对它进行读写操作。popen函数在失败时返回一个空指针。如果想通过管道实现双向通信,最普通的解决方法是使用两个管道,每个管道负责一个方向的数据流。

2.pclose函数

用popen启动的进程结束时,可以用pclose函数关闭与之关联的文件流。pclose调用只在popen启动的进程结束后才返回。如果调用pclose时它仍在运行,pclose调用将等待该进程的结束。
pclose调用的返回值通常是它所关闭的文件流所在进程的退出码。如果调用进程在调用pclose之前执行了一个wait语句,被调用进程的退出状态就会丢失,因为被调用进程已结束。此时,pclose将返回-1并设置errno为ECHILD。
读取外部程序的输出
编写示例程序popen1.c,在程序中用popen访问uname命令给出的信息.命令uname -a的作用是打印系统信息,包括计算机型号,操作系统名称,版本,发行号,计算机的网络名.
/*************************************************************************
 > File Name:    popen1.c
 > Description:  popen1.c程序用popen访问uname命令给出的信息,然后用返回的文件流读取最多BUFSIZE个字符的数据,并将它们打印出来显示在屏幕上
 > Author:       Liubingbing
 > Created Time: 2015/7/8 19:54:24
 > Other:        popen1.c程序
 ************************************************************************/

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

int main(){
	/* 文件流指针 */
	FILE *read_fp;
	char buffer[BUFSIZ+1];
	int chars_read;
	/* 初始化buffer */
	memset(buffer, '\0', sizeof(buffer));
	/* popen函数允许一个程序将另一个程序作为新进程来启动,并可以传递数据给它或者通过它接收数据
	 * 第一个参数command字符串为"uname -a",是要运行的程序名和相应的参数 
	 * 第二个参数"r"指定被调用程序的输出可以被调用程序使用 
	 * 函数的返回值是FILE*文件流指针,read_fp指向command命令的输出 */
	read_fp = popen("uname -a", "r");
	if (read_fp != NULL) {
		/* fread函数读取被调用程序的输出(read_fp指向被调用程序的输出) */
		chars_read = fread(buffer, sizeof(char), BUFSIZ, read_fp);
		if (chars_read > 0) {
			printf("Output was:-\n%s\n", buffer);
		}
		/* pclose函数关闭与打开的管道关联的文件流(利用popen返回的文件流指针read_fp) */
		pclose(read_fp);
		exit(EXIT_SUCCESS);
	}
	exit(EXIT_SUCCESS);
}
这个程序用popen调用启动带有-a选项的uname命令,然后用返回的文件流读取最多BUFSIZE个字符(这个常量在stdio.h中用#define语句定义的)的数据,并且将它打印出来显示在屏幕上.结果如下所示:

版权声明:本文为博主原创文章,未经博主允许不得转载。

《Erlang 程序设计》练习答案 -- 第十三章 并发程序中的错误

% (1).编写一个 my_spawn(Mod, Func, Args) 函数。它的行为类似 spawn(Mod, Func, Args), % 但有一点区别。如果分裂出的进程挂了,就应打印出一个消息...
  • wwh578867817
  • wwh578867817
  • 2015年11月18日 00:59
  • 648

Linux----进程间通信-管道与两个命名管道实现进程双向通信

在Linux系统中,有时候需要多个进程之间相互协作,共同完成某项任务,进程之间或线程之间有时候需要传递信息,有时候需要同步协调彼此工作,则就会出现进程间通信(interprocess communi...
  • qq_36782456
  • qq_36782456
  • 2017年05月29日 19:45
  • 1086

java 语言程序设计 第十三章 13.5

程序小白,希望和大家多交流,共同学习 (只是将13.1的内容加以修改,具体的就是 implements Comparable; 然后我又在Rectangle类中重写了toString()方...
  • cheng_cuo_tuo
  • cheng_cuo_tuo
  • 2017年11月13日 12:21
  • 166

《Linux程序设计》--读书笔记---第十三章进程间通信:管道

管道:进程可以通过它交换更有用的数据。 我们通常是把一个进程的输出通过管道连接到另一个进程的输入; 对shell命令来说,命令的连接是通过管道字符来完成的; cmd1    |     cmd2 ...
  • beitiandijun
  • beitiandijun
  • 2013年08月09日 17:27
  • 2453

Linux下的进程通信方式: 管道通信详解

管道是单向的、先进先出的、无结构的字节流,它把一个进程的输出和另一个进程的输入连接在一起。...
  • rl529014
  • rl529014
  • 2016年05月20日 21:03
  • 3873

Linux进程通信 有名管道实现守护进程

有名管道实现守护进程 问题:如果一个进程出现了问题怎么判断它是否在运行?能否重启这个进程?尝试用守护进程操作。   解决方案:有名管道实现守护进程          守护进程(主进程)一直读取...
  • ky_heart
  • ky_heart
  • 2016年10月26日 23:41
  • 303

Linux进程间通信:管道(把管道用作标准输入和标准输出)

#include int dup(int file_descriptor); int dup2(int file_descriptor_one , int file_descriptor_two); ...
  • querdaizhi
  • querdaizhi
  • 2012年04月24日 16:30
  • 4062

【Linux】利用管道在进程通讯拷贝文件

其实Linux-C拷贝文件根本不用这么折腾,具体参见《【Linux】利用C语言文件流复制单一文件》(点击打开链接),这个程序也没有什么卵用,直接一个cp好了,主要是借这个程序说明《【Linux】管道的...
  • yongh701
  • yongh701
  • 2016年12月19日 09:51
  • 942

linux c之通过管道实现兄弟间进程通信:

1、兄弟间进程通信:          父进程创建管道,并使用fork函数创建2个进程,在第一个子进程发消息到第二个子进程,第2个子进程读取消息并处理,在父进程中不使用管道通信,所以什么都不做,直接关...
  • u011068702
  • u011068702
  • 2017年02月10日 17:47
  • 279

linux程序设计——把管道用作标准输入和输出(第十三章)

13.5.1    管道关闭后的读操作 接下来先研究一下打开的文件描述符,此前一直采取的是让读进程读取一些数据然后直接退出的方式,并假设linux会把清理文件当作是在进程结束时应该做的工作的一部分. ...
  • yiranant
  • yiranant
  • 2015年07月12日 23:11
  • 1739
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:linux程序设计——进程管道(第十三章)
举报原因:
原因补充:

(最多只允许输入30个字)