stdlib 库有个很多人用过的函数:system.
如果希望这段代码能够跨平台,而希望让程序能等个1秒,一个很好的方法就是,system("sleep 1");这样,无论是windows还是linux,我们都可以很好的执行"等待1秒",而不必多写好多参数什么的.
但是,有时候,我们希望能够得到这个命令的输出,而不是只是"执行它".那么,我们需要点新的东西了.
管道 即是一个由标准输入输出链接起来的进程集合,所以每一个进程的输出(stdout)被直接作为下一个进程的输入(stdin)。 每一个链接都由未命名管道实现。过滤程序经常被用于这种设置。[1]
我们可以通过一些系统提供的管道函数,获得这个输出.
这不是一个标准库函数,而是系统相关的.
POSIX 下一个比较方便的函数是 popen.
popen的函数原型是:
FILE *popen(const char *command, const char *type);
manual 下的描述是
the popen() function opens a process by creating a pipe, forking, and invoking the shell. Since a pipe is by definition unidirectional, the type argument may specify only reading or writing, not both; the resulting stream is correspondingly read-only or write-only.
大意是fork出一个线程,执行然后得到结果,存储到管道文件中,返回文件只读或者只写句柄.或者失败,返回NULL.
popen的方法很简单,和fopen一样,传入两个字符串,得到一个文件句柄.只不过fopen第一个参数是文件名,而popen是命令.然后其他用法 -- 都已经得到了 FILE * 了还有什么不会的么?
windows下也有个很相似的函数,不过是函数名是_popen,我们可以简单的通过宏搞定跨平台.
扯淡完毕,代码本身其实可以简单的说明一切
#include <stdlib.h> #include <stdio.h> #include <string.h> #ifndef WIN32 // headers for linux #include <sys/types.h> #include <unistd.h> #endif // WIN32 #ifdef WIN32 // windows #define _exec(cmd) _popen(cmd, "r") #else // linux #define _exec(cmd) popen(cmd, "r") #endif // WIN32 int main(int argc,char *argv[]) { FILE *stream; char buf[1024]; memset(buf,'\0',sizeof(buf));//初始化buf,以免后面写如乱码到文件中 stream = _exec("echo \"hello, world !\""); //将参数内容命令的输出,得到管道文件句柄 if(stream != NULL) { //将刚刚FILE* stream的数据流读取到buf中 fread( buf, sizeof(char), sizeof(buf), stream); fwrite( buf, 1, sizeof(buf), stdout );//将buf中的数据写到stdout //关闭流 pclose(stream); }else { //执行失败 printf("error!\n"); } return 0; }
代码是使用管道执行
echo "hello, world!"
这个命令. 然后读取执行结果,输出.
一个需要注意的问题是,因为原理是fork一个线程,所以环境变量是直接复制的,权限问题什么的要注意一下.
4 Comments
原创博客 · August 6, 2013 at 10:53
很有用啊
Leniy · July 29, 2013 at 08:07
哈,rss最近20篇全部更新了
yu · July 29, 2013 at 08:17
估计是我调整了下RSS输出的原因吧
Leniy · July 29, 2013 at 08:18
恩,应该了