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

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.

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

时间: 2024-08-27 19:57:11

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

linux程序设计——文件操作(第三章)

第三章    文件操作 3.1 linux文件结构 与UNIX一样,linux环境中的文件具有特别重要的意义,因为它们为操作系统服务和设备提供了一个简单而一致的接口.在linux中,一切都是文件. 这意味着,通常程序可以像使用文件那样使用磁盘文件.串行口.打印机等等. 目录也是文件,但它是一种特殊类型的文件.在现代UNIX(包括linux)版本中,即使是超级用户可能也不再被允许直接对目录进行写左操作了.所有用户通常都使用上层的opendir/readdir接口来读取目录,而无需了解特定系统中目录

linux程序设计——数据报(第十五章)

15.5    数据报 在本章中,重点介绍了如何编写与客户之间维持连接的应用程序.使用面向连接的TCP套接字来完成这一工作.但在某些情况下,在程序中花费时间来建立和维持一个套接字连接是不必要的. 早先,在程序getdate.c中所使用的daytime服务就是一个很好的例子,首先创建一个套接字,然后建立连接,读取一个响应,读取一个响应,最后关闭连接.在这一过程中,使用了很多操作步骤,仅仅为了获取一个日期. daytime服务还可以用数据报通过UUDP来访问.为了访问它,发送一个数据报给该服务,然后

linux程序设计——文件锁定(第七章)

7.2 文件锁定 这篇为linux的文件锁定,代码在文件锁定代码下载.文件锁定是多用户.多任务操作系统中一个非常重要的组成部分.程序经常需要共享数据,而这通常是通过文件来实现的.因此,对于这些程序来说,建立某种控制文件的方式就非常重要.只有这样,文件才可以通过一种安全的方式更新,或者说,当一个程序正在对文件进行写操作时,文件就会进入一个暂时状态,在这个状态下,如果另外一个程序尝试读这个文件,它就会自动停下来等待这个状态的结束. linux提供了多种特性来实现文件锁定,其中最简单的方式就是以原子操

C++程序设计原理与实践 第二十三章部分答案

1 #include <iostream> 2 #include <vector> 3 #include <string> 4 #include <list> 5 #include<fstream> 6 #include <set> 7 #include<algorithm> 8 #include<stdexcept> 9 #include <map> 10 #include<boost/re

linux程序设计——多线程(第十二章)

12.8    多线程 之前,总是让程序的主线程仅仅创建一个线程,这节将演示如何在同一个程序中创建多个线程,然后如何以不同于其启动顺序将它们合并在一起.此外,还演示多线程编程时容易出现的时序问题. 编写程序thread8.c /************************************************************************* > File Name: thread8.c > Description: thread8.c程序创建多个线程,然后以不同

javascript高级程序设计 第十三章--事件

javascript高级程序设计 第十三章--事件js与HTML的交互就是通过事件实现的,事件就是文档或浏览器窗口中发生的一些特定的交互瞬间. 事件流:事件流描述的是从页面中接收事件的顺序,IE的是事件冒泡流,Netscape的是事件捕获流,这个两个是完全相反的事件流概念. 事件冒泡:由最具体的元素接收,然后逐级向上传播到更高级的节点,即事件沿DOM树向上传播,直到document对象. 事件捕获:不大具体的节点应该更早接收到事件,相当于沿DOM节点树向下级传播直到事件的实际目标,在浏览器中,是

《Linux程序设计 第四版》之第二章的最后练习题

这篇文章是<Linux程序设计 第四版>中的第二章的最后练习题(2.8综合应用), 题目是编写一个CD数据库应用程序, 首先:用两个文件来保存存储的数据,一个是title_file.cdb,一个是column_file.cdb! title_file.cdb里面保存的是唱片的基本信息:拥有如下四个字段: CD的目录编号,标题,唱片类型,作曲家或艺术家: column_file.cdb里面保存的是唱片的详细信息即唱片包含的歌曲信息:拥有如下三个字段: CD的目录编号,曲目编号,歌曲名 其次: 有

linux程序设计——第一个线程程序(第十二章)

第12章    POSIX线程 在第11章中,介绍了如何在linux中处理进程.但有时人们认为,用fork调用来创建新进程的代价太高.在这种情况下,如果能让一个进程同时做两件事情或者至少看起来是这样会非常有用,而且,人们页希望能有两件或更多的事情以一种非常紧密的方式同时发生,这就需要线程发挥作用了. 12.1    什么是线程 在一个程序中多个执行路线就叫做线程(thread).更准确的定义是:线程是一个进程内部的一个控制序列.虽然linux和许多其他的操作系统一样,都擅长同时运行多个进程,但迄

《javascript高级程序设计》第十三章知识点

第十三章知识点总结 1.事件流: ①事件冒泡:事件开始时由最具体的事件接受,逐级向上传播到较为不具体的节点. ②事件捕获:不太具体的节点更早的接受事件,最具体的节点应该最后接到事件. 事件流包括三个阶段:事件捕获阶段.处于目标阶段.事件冒泡阶段. 2.事件处理程序 3.事件对象 IE 属性 除了上面的鼠标/事件属性,IE 浏览器还支持下面的属性: 属性 描述 cancelBubble 如果事件句柄想阻止事件传播到包容对象,必须把该属性设为 true. fromElement 对于 mouseov