Chinaunix

标题: 请教各位一个关于管道的问题,如何获取系统命令的结果??谢谢 [打印本页]

作者: fwizard    时间: 2005-04-04 17:17
标题: 请教各位一个关于管道的问题,如何获取系统命令的结果??谢谢
我希望把一个字符串,比如"ls -al",通过管道让系统去执行,然后再通过管道,把执行结果保存在一个缓冲或文件里,应该如何去实现呢,希望哪位高手能给个大致流程,关于管道重定向我是知道一点的,但就是感觉乱,理不清头绪.
谢谢各位!
作者: kj501    时间: 2005-04-04 17:26
标题: 请教各位一个关于管道的问题,如何获取系统命令的结果??谢谢
man popen
作者: kert_t8    时间: 2005-04-05 07:08
标题: 请教各位一个关于管道的问题,如何获取系统命令的结果??谢谢
/* example usage of popen() */

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

int
main()
{

        FILE *f;
        char buf[1024];
        char cmd[] = "ls -al";

        f = popen( cmd, "r" );

        while( fgets( buf, 1024, f ) != NULL )
                fputs( buf, stdout );

        pclose( f );

        return 0;
}
作者: fwizard    时间: 2005-04-05 08:39
标题: 请教各位一个关于管道的问题,如何获取系统命令的结果??谢谢
谢谢楼上两位的回复.popen实现了我所要的功能.但是,这个函数好象比较占资源,一是要启动一个shell,二是执行命令.
不知道有没有知道,如何用管道(pipe)的方式,去实现这个功能,这样一是会减少资源占用率,二是灵活性更大.
谢谢
作者: kj501    时间: 2005-04-05 10:20
标题: 请教各位一个关于管道的问题,如何获取系统命令的结果??谢谢
1.pipe
2.fork
3.dup2重定向
4.exec要执行的命令
作者: fwizard    时间: 2005-04-05 11:01
标题: 请教各位一个关于管道的问题,如何获取系统命令的结果??谢谢
原帖由 "kj501" 发表:
1.pipe
2.fork
3.dup2重定向
4.exec要执行的命令

exec要处理参数且不说,它的执行结果怎么取出来呢?
作者: isnowran    时间: 2005-04-05 14:04
标题: 请教各位一个关于管道的问题,如何获取系统命令的结果??谢谢
父进程通过waitpid得到子进程的exec结果
作者: bleem1998    时间: 2005-04-05 14:08
标题: 请教各位一个关于管道的问题,如何获取系统命令的结果??谢谢
很早以前写的了
是一个通用的函数
取名lazy提醒自己少用这样的方式
果然一次也没用过
hoho


  1. #include "../my.h"

  2. /*功能说明:这个函数用来调用外部程序(任何程序都可以,包括各种脚本),并且将外部程序的标准输出结果保存到一块内存中(内存可写),函数返回
  3. 这块内存的指针,调用者可以直接printf这个指针,!!!!!!!!!!!!!!!!最后一定要记得free!!!!!!!!!!!!

  4. 两种使用方法:lazy("ls -al /root"),lazy("ls",{"ls", "-al", "/root", (char *)0})

  5. 思路简述:用了两个进程一个管道,子进程调用system或者exec执行shell,并且把输出重定向到管道,父进程则从管道将数据读出,根据读出数据的数量自动扩展缓冲区大小

  6. 两个地方值得回味:1,关闭文件描述符,一些不用的文件描述符要关闭,很多时候都出现了管道阻塞,这个时候去proc里看看到底是哪些多余的描述符没有关闭,关掉它们那就好了
  7.                         2,如何打开被关闭的标准输出,有两种办法(a,用dup复制,以后再用dup2拷贝回来,本程序就是用这个办法.b,调用ttyname(1)查看当前打开的是哪个终端,然后再用open打开就行了)

  8. 命名来历:用这个函数之前问问自己,我写的还是C语言程序吗?
  9. */

  10. char *lazy(char *pCmd, char **env) {
  11.         char *pResult, *p;
  12.         int fd[2], fd_stdout;
  13.         int count=0;
  14.         int a1 = 0, a2 = 0;     //a1缓冲区总大小,a2缓冲区使用了多少
  15.         int maxlen = 4096;      //为什么使用4096?因为这刚好是管道的大小,可以参考~/code/ipc/pipe/question.c里的Q4

  16.         fd_stdout = dup(1);     //备份stdout,关闭之后想要再使用标准输出要靠这个备份的
  17.         pipe(fd);
  18.         close(1);
  19.         dup2(fd[1],1);
  20.         if (fork() == 0) {
  21.                 close(fd[1]);
  22.                 close(fd[0]);
  23.                 close(fd_stdout);
  24.                 if (env == NULL)        //exec和system都可以,不同的调用方法用不同的实现吧,呵呵
  25.                         system(pCmd);   //调用方法:lazy("ls -al /root")
  26.                 else
  27.                         execvp(pCmd, env);      //调用方法:lazy("ls",{"ls", "-al", "/root", (char *)0})

  28.                 exit(1);
  29.         }
  30.         close(fd[1]);
  31.         close(1);
  32.         fflush(stdout);
  33.         dup2(fd_stdout, 1);     //打开stdout

  34.         pResult = malloc(maxlen + 1);
  35.         a1 += maxlen + 1;
  36.         p = pResult;
  37.         while ((count = read(fd[0], pResult, maxlen)) >; 0) {    //如果在read过程中超过了缓冲区边缘会返回-1,调试了很久才发现这个问题
  38.                 a2 += count;
  39.                 if (a1 - a2 <= maxlen) {
  40.                         p = realloc(p, a1 + maxlen);    //为什么要用个临时变量p来帮忙呢?:)这是一个小发现呵呵,看<Linux函数库参考手册>;P33的笔记
  41.                         pResult = p + a2;
  42.                         a1 += maxlen;
  43.                         continue;
  44.                 }
  45.                 pResult += count;
  46.         }
  47.         *pResult = 0;   //打上字符串结束符
  48.         close(fd[0]);
  49.         wait(&count);

  50.         return p;
  51. }

  52. int main(void) {
  53.         char *result;
  54.         char *cmd = "ls";
  55.         char *cmd2 = "ls /dev";
  56.         char *env[] = {"ls", "-al", "/dev", (char *)0};

  57.         //result = lazy(cmd, env);
  58.         result = lazy(cmd2, NULL);

  59.         printf("%s", result);
  60.         free(result);
  61.         return 0;
  62. }


复制代码

作者: sfeng    时间: 2005-04-05 15:18
标题: 请教各位一个关于管道的问题,如何获取系统命令的结果??谢谢
楼上的代码强哟,可以试试先。

不过,我遇到类似的情况,一般都是使用popen,或许是对运行时间要求不是那么高,所以也不觉得有多慢。^_^
作者: fwizard    时间: 2005-04-05 17:05
标题: 请教各位一个关于管道的问题,如何获取系统命令的结果??谢谢
谢谢楼上几位,现在算是搞明白了几分了,下来作几个程序就可以理解彻底了.再次表示感谢




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2