popen -- 强大的跨平台命令执行器

来源:互联网 发布:腾讯程序员工资多少 编辑:程序博客网 时间:2024/05/17 22:02

在做远程通讯程序的时候经常有这样一类用例:

 

client端发送一个请求,需要从server获取相关信息,比如client端需要知道server根目录下目录结构等等,这样怎么做呢?

首先,在这里忽略网络通讯的相关细节,就关注于服务器端怎么去得到目录结构。也许你会利用opendir, readdir再加上if else, while, for 之类的字符码了一堆功能貌似强大的代码,当然这完全能满足你的要求!但是有什么更好的方法呢?试想如果你需要执行非常复杂的一套命令怎么办?比如在client端时刻监控到server端的网络连接状态,难道非得利用socket来发送heartbeat消息来监控么?那样代价就太大了。

 

也许这是你会想到我们有ls, ping命令,对了,linux中这些实用的命令,还有shell脚本提供了强大的功能,如果我们能在server端执行这些脚本并且得到他们的输出就太好了!是的,执行一个命令太简单了,exec函数族就可以解决问题,但是关键问题是如何获得命令的输出呢?

 

好,说到输出,这些命令的输出都是写在进程标准输出上文件描述符上。那就好办了,我们让命令输出到自定义的文件描述符上,然后去读取这个文件描述符!而这里涉及到父子进程的通讯,我们利用管道就可以实现了。现在整理一下顺序:

1,父进程创建一个pipe

2,fork子进程

3,父进程读取pipe,等待子进程写入数据

4,子进程中重定向stdout为pipe的写端

5,子进程执行命令

6,子进程执行完毕,推出

7,父进程读取pipe完毕,退出

 

到这一步我们就获得了一个功能强大的命令执行器,它可以执行任何程序以及shell脚本,然后对返回的字符串分析重构得到我们想要的格式,大功告成!这样解决“在client端时刻监控到server端的网络连接状态“的问题就易如反掌了,只需要执行ping -t然后分析返回的字符串,就可以了!就这么简单。

 

但是,有更好的解决方案吗? 当然有!请看popen函数

#include <stdio.h>

FILE* popen(const char* cmdstring, const char type);

popen内部先执行fork,然后调用exec执行cmdstring,并且返回一个标准i/o文件指针,如果type是"r",则返回cmdstring的标准输出,如果type是“w”,则返回cmdstring的标准输入。这不正是我们上面做的工作吗? demo代码如下:


#include <stdio.h>

int main( void )
{

char psBuffer[128];
FILE *pPipe;

if( (pPipe = popen( "ls -l /", "r" )) == NULL )
return 0;


while(fgets(psBuffer, 128, pPipe))
printf(psBuffer);

pclose(pPipe);

return 0;
}

原来一切如此简单! 更难得的是popen是c标准函数库提供的,也就是说也适用于windows平台,轻松做到平台无关!

 

 

................................................................................

后记

这是我在两年前的一个项目中遇到的问题,server端需要执行各种各样复杂的命令,由于是在windows系统中,当时的方案是利用重定向管道和createprocess包装了一个command executer,工作非常稳定!但是在平台移植的时候遇到问题,最终找了popen!

 

原创粉丝点击