linux程序设计——如何实现popen(第十三章)

原创 2015年07月09日 21:34:06

13.3.2    如何实现popen

请求popen调用运行一个程序时,它首先启动shell,即系统中的sh命令,然后将command字符串作为一个参数传递给它,这有两个效果,一个好,一个不好.
在linux中,所有的参数扩展都是由shell来完成的.所以,在启动程序之前先启动shell来分析命令字符串,就可以使各种shell扩展(如*.c所指的是哪些文件)在程序启动之前就全部完成.这个功能非常有用,它允许通过popen启动非常复杂的shell命令.而其他一些创建进程的函数(如execl)调用起来就复杂的多,因为调用进程必须自己去完成shell扩展.
使用shell的一个不太好的影响是,针对每个popen调用,不仅要启动一个被请求的程序,还要启动一个shell,即每个popen调用将多启动两个进程.从节省系统资源的角度来看,popen函数的调用成本略高,而且对目标命令的调用比正常方式要慢一些.
程序popen4.c来演示popen函数的行为.这个程序对所有popen示例程序的源文件的总行数进行统计,方法是用cat命令显示文件的内容并将输出通过管道传递给命令wc -l,由后者统计总行数.如果是在命令行上完成这一任务,可以用如下命令:
$ cat popen*.c | wc -l
事实上,输入命令wc -l popen*.c更简单而且更有效率,但是为了通过这个例子演示popen函数的工作原理还是如上使用.
编写程序popen4.c.
/*************************************************************************
 > File Name:    popen4.c
 > Description:  popen4.c程序演示popen函数的行为,它对所有popen示例程序的源文件的总行数进行统计
 > Author:       Liubingbing
 > Created Time: 2015年07月09日 星期四 20时39分42秒
 > Other:        popen4.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;

	memset(buffer, '\0', sizeof(buffer));
	read_fp = popen("cat popen*.c | wc -l", "r");
	if (read_fp != NULL) {
		chars_read = fread(buffer, sizeof(char), BUFSIZ, read_fp);
		printf("chars_read = %d\n", chars_read);
		while (chars_read > 0) {
			buffer[chars_read - 1] = '\0';
			printf("Reading:-\n %s\n", buffer);
			chars_read = fread(buffer, sizeof(char), BUFSIZ, read_fp);
		}
		pclose(read_fp);
		exit(EXIT_SUCCESS);
	}
	exit(EXIT_FAILURE);
}
这个程序显示,shell在启动后将popen*.c扩展为一个文件列表,列表中的文件名都以popen开头,以.c结尾,shell还处理了管道符|,并将cat命令的输出传递给wc命令.在一个popen调用中启动了shell,cat程序和wc程序,并进行了一次输出重定向.而调用这些命令的程序只看到最终的输出结果.
程序popen4.c结果如下所示:(read_fp指向的文件中保存的应该就是cat popen*.c | wc -l返回的数值146.

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

linux pthread 多线程操作

简要说明一下进程和线程的区别,以及为何有了进程还需要线程。 一句话概括,进程是系统资源分配的最小单位,线程是CPU调度的最小单位。一个进程可以有多个线程,每个线程有自己的堆栈he...

UNIX网络编程卷2进程间通信读书笔记-管道

一.管道        管道的名称很形象,它就像是一个水管,我们从一端到水然后水从令一端流出。不同的是这里说的管道的两边都是进程。从一端往管道里写数据,其它进程可以从管道的另一端的把数据读出,从而实...

linux程序设计——管道输出数据到popen(第十三章)

13.3    将输出送往popen 看过捕获外部程序输出的例子后,再来看一个将输出发送到外部程序的示例程序popen2.c,它将数据通过管道送到另一个程序.在这里使用的是od(八进制)命令. 编写程...

linux程序设计——对FIFO进行读写操作(第十三章)

4.对FIFO进行读写操作 使用O_NONBLOCK模式会影响的对FIFO的read和write调用. 对一个空的,阻塞的FIFO(即没有用O_NONBLOCK标志打开)的read调用将等待,直到...

linux程序设计——pipe调用在两进程之间通信(第十三章)

13.4    pipe调用 在看过高级的popen函数之后,再来看看底层的pipe函数.通过这个函数在两个程序之间传递数据不需要启动一个shell来解释请求的命令.它同时提供了对读写数据的更多控制....

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

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

linux程序设计——使用FIFO的客户/服务器的应用程序(第十三章)

13.6.2    使用FIFO的客户/服务器应用程序 作为学习FIFO的最后一部分内容,现在考虑怎样通过命名管道来编写一个非常简答的客户/服务器应用程序。用一个服务器进程来接受请求,对它们进行处理...

《Javascript高级程序设计》第十三章——事件学习笔记(待续)

一、事件流 事件流描述的是从页面中接收事件的顺序。 1.事件冒泡

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

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

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

程序小白,希望和大家多交流,共同学习 (只是将13.1的内容加以修改,具体的就是 implements Comparable; 然后我又在Rectangle类中重写了toString()方...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:linux程序设计——如何实现popen(第十三章)
举报原因:
原因补充:

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