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

原创 2015年07月09日 20:31:17

13.3    将输出送往popen

看过捕获外部程序输出的例子后,再来看一个将输出发送到外部程序的示例程序popen2.c,它将数据通过管道送到另一个程序.在这里使用的是od(八进制)命令.
编写程序popen2.c,它非常类似popen1.c,唯一的不同是这个程序将数据写入管道,而不是从管道中读取.
/*************************************************************************
 > File Name:    popen2.c
 > Description:  popen2.c程序将数据写入管道
 > Author:       Liubingbing
 > Created Time: 2015年07月09日 星期四 19时43分51秒
 > Other:        popen2.c程序的作用等同于在命令行上输入echo "Once upon a time, there was..." | od -c
 ************************************************************************/

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

int main(){
	FILE *write_fp;
	char buffer[BUFSIZ + 1];
	
	/* 将字符串写入buffer */
	sprintf(buffer, "Once upon a time, there was...\n");

	/* 函数popen允许一个程序给另一个程序传输数据
	 * 第二个参数"w"表明调用程序可以用fwrite调用向被调用程序发送数据
	 * 即将文件流指针write_fp指向的数据作为命令"od -c"的标准输入 */
	write_fp = popen("od -c", "w");
	if (write_fp != NULL) {
		/* fwrite向一个文件写入数据块
		 * 即将buffer中的数据写入到write_fp指向的文件,写入strlen(buffer)个元素,每个元素的大小为sizeof(char)个字节 */
		fwrite(buffer, sizeof(char), strlen(buffer), write_fp);
		pclose(write_fp);
		exit(EXIT_SUCCESS);
	}
	exit(EXIT_FAILURE);
}
程序使用带有参数"w"的popen启动od -c命令,这样就可以向该命令发送数据了.然后它给od -c命令发送一个字符串,该命令接收并处理它,最后把处理结果打印到自己的标准输出上.
在命令行上,可以用下面的命令得到同样的输出结果:
$ echo "Once upon a time, there was..." | od -c
程序popen2.c的结果如下所示:

13.3.1    传递更多的数据

目前所使用的机制都只是将所有数据通过一次fread或fwrite调用来发送或接收.有时,可能希望以块方式发送数据,或者根本就不知道输出数据的长度.为了避免定义一个非常大的缓冲区,可以用多个fread或fwrite调用来将数据分为几部分处理.
编写程序popen3.c,通过管道读取所有数据
/*************************************************************************
 > File Name:    popen3.c
 > Description:  popen3.c程序通过管道读取大量数据
 > Author:       Liubingbing
 > Created Time: 2015年07月09日 星期四 20时34分37秒
 > Other:        popen3.c
 ************************************************************************/

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

int main(){
	FILE *read_fp;
	char buffer[BUFSIZ + 1];
	int chars_read;
	
	memset(buffer, '\0', sizeof(buffer));
	/* popen函数访问"ps ax"命令给出的信息
	 * 第一个参数"ps ax"是要运行的程序名和相应的参数
	 * 第二个参数open_mode="r"说明被调用程序的输出可以被调用程序使用
	 * 返回值为FILE*文件流指针read_fp,利用read_fp可以读取"ps ax"的输出信息 */
	read_fp = popen("ps ax", "r");
	if (read_fp != NULL) {
		/* fread函数从文件流指针read_fp指向的文件流中读取数据 
		 * 最多读取BUFSIZ个元素,每个元素sizeof(char)个字节
		 * buffer用于接收数据的内存地址
		 * 如果成功则返回实际读取的元素的个数 */
		chars_read = fread(buffer, sizeof(char), BUFSIZ, read_fp);
		if (chars_read > 0) {
			buffer[chars_read - 1] = '\0';
			printf("Reading %d:-\n %s\n", BUFSIZ, buffer);
			chars_read = fread(buffer, sizeof(char), BUFSIZ, read_fp);
		}
		/* pclose关闭与popen关联的文件流(read_fp指向的文件流) */
		pclose(read_fp);
		exit(EXIT_SUCCESS);
	}
	exit(EXIT_FAILURE);
}
在这个程序中,从被调用的进程ps ax中读取数据.该进程输出的数据有多少事先无法知道,所以必须对管道进行多次读取.
这个程序调用popen函数时使用了"r"参数,这与popen1.c程序做法一样.这次,它连续从文件流中读取数据,直到没有数据可读为止.注意,虽然ps命令的执行要花费一些时间,但linux会安排好进程间的调度,让两个程序在可以运行时继续运行.如果读进程popen3没有数据可读,它将被挂起直到有数据到达.如果写进程ps产生的数据超过了可用缓冲区的长度,它也会被挂起直到读进程读取了一些数据.
在本例中,可能不会看到Reading:-信息的第二次出现.如果BUFSIZ的值超过了ps命令输出的长度,这种情况就会发生.

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

popen——C程序中获取Shell命令的输出

以前在C程序中习惯用system来调用执行shell命令,但是这样有个缺点,就是只能得到执行的shell命令的返回值,如果想得到其输出,只能通过一些间接的方法,比如修改shell命令让它的输出重定向到...
  • weiyuefei
  • weiyuefei
  • 2016年10月26日 16:28
  • 1460

popen函数执行命令,读取流数据

int Volume::createDeviceNode(const char *path, int major, int minor) { mode_t mode = 0666 | S_IF...
  • yiwuxue
  • yiwuxue
  • 2014年11月19日 15:06
  • 541

Linux下使用popen()执行shell命令

简单说一下popen()函数 函数定义 #include FILE * popen(const char *command , const char *type ); int pclose...
  • dddxxxx
  • dddxxxx
  • 2016年06月29日 17:32
  • 996

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

13.5.1    管道关闭后的读操作 接下来先研究一下打开的文件描述符,此前一直采取的是让读进程读取一些数据然后直接退出的方式,并假设linux会把清理文件当作是在进程结束时应该做的工作的一部分. ...
  • yiranant
  • yiranant
  • 2015年07月12日 23:11
  • 1744

尝试linux下c编程之管道

今天试了下管道,感觉挺有意思的~ 现在才发现,原来进程也有这么多的功能可以实现。管道分类: 根据进程的相互关系,可以分为:匿名管道与命名管道。1   匿名管道:管道是父进程和子进程间,或是子进程与子进...
  • wencool
  • wencool
  • 2008年04月12日 22:44
  • 5634

管道-popen

管道:把一个进程的输出连接到另一个进程的输入    单向 实现管道的方式之一:popen FILE *popen(const char *command, const char *open_mod...
  • wellmikelan
  • wellmikelan
  • 2012年09月06日 17:11
  • 1835

基于管道的popen和pclose函数

标准I/O函数库提供了popen函数,它启动另外一个进程去执行一个shell命令行。 这里我们称调用popen的进程为父进程,由popen启动的进程称为子进程。 popen函数还创建一个管道用于父...
  • jiangxinyu
  • jiangxinyu
  • 2012年05月29日 13:44
  • 8062

fopen、open和popen区别

open:直接操作物理设备,比如磁盘、设备文件  一般设备/设备文件都通过open来操作  fopen:则通过缓冲区来操作,读写都在缓冲区上  popen:会调用fork()产生子进程,然后从子进程中...
  • kaiandshan
  • kaiandshan
  • 2015年01月28日 10:11
  • 2605

unix环境高级编程——库函数的缓冲区

1.对于库函数,如果标准输出连到终端设备,则它是行缓冲的(遇到回车换行符或者是缓冲区满了才输出);否则是全缓冲的(缓冲区填满或者是程序运行结束了才输出)。 2.程序运行结束时,会刷新所有的缓冲区。...
  • a987860319
  • a987860319
  • 2015年04月13日 11:24
  • 848

popen 重定向标准错误输出到管道流的方法

FILE *popen(const char *command, const char *type); 当使用type 参数为 “r" 时,popen 会把执行 command 后的标准输出重定向到...
  • hiflower
  • hiflower
  • 2012年02月07日 22:27
  • 6111
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:linux程序设计——管道输出数据到popen(第十三章)
举报原因:
原因补充:

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