一个进程的输出结果在另一个进程中显示

#include "../my.h"

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

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

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

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

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

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

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

                exit(1);
        }
        close(fd[1]);
        close(1);
        fflush(stdout);
        dup2(fd_stdout, 1);     //打开stdout

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

        return p;
}

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

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

        printf("%s", result);
        free(result);
        return 0;
}

 

 

#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;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值