曲径通幽论坛

标题: popen() 与 pclose() [打印本页]

作者: beyes    时间: 2009-10-11 21:06
标题: popen() 与 pclose()
system() 函数与fork() 和 exec() 一起启动了一个程序。管道也有一对类似的函数: popen() 和  pclose()

popen() 和 pclose() 的原型是
#include <stdio.h>

FILE *popen (const char *command, const char *mode)

int pclose (FILE *stream)

popen() 函数在调用进程和 command 指定的程序之间创建一个管道。实际上是当前进程先 fork 出一个子进程,然后该子进程再调用 exec  函数族中的函数去执行 command ,同时还使用 pipe() 建立了一个连通进程和 command 的一个管道。调用进程既可以从管道读取也可以写入管道,这由 mode 参数决定。当 mode 为 'r' 时为进程读 command 的输出结果;如果 mode 为 'w' 时,表示进程给 command 输送些参数。在 glibc2.9 后增加了一个 'e' 选项,该选项相当于设置了 FD_CLOEXEC  选项,也就是说,command 不会用到进程里的文件描述符。


函数返回的是普通的标准 I/O 流指针,通过它可以将需要处理的内容输送到 shell 命令进行处理。如果函数执行失败(可能是内部调用 fork() 或 pipe() 失败,抑或无法分配相应内存空间),则返回 NULL 。

最后,需要调用 pclose() 函数以等待相应进程结束及 command 的的退出状态码。

测试代码:
[C++] 纯文本查看 复制代码
#include <stdio.h>
#include <stdlib.h>

#define MAXSTR 5

int main(void)
{
        int i;
        FILE *pipe_fp;
        char *strings[MAXSTR] = {"hello", "www", "groad", "net", "good"};


        if ((pipe_fp = popen("sort", "w")) == NULL) {
                perror("popen");
                exit(EXIT_FAILURE);
        }

        for (i = 0; i < MAXSTR; i++) {
                fputs(strings, pipe_fp);
                fputc('\n', pipe_fp);
        }

        pclose(pipe_fp);

        return (0);
}

运行输出:
beyes@beyes  :~/c/popen> ./popen
good
groad
hello
net
www
上面程序,我们将要排序的字符串通过通用 popen() 返回的 I/O 流指针输送往 command 一侧,然后用 sort 命令进行排序。需要注意的是,popen() 绑定的是一个 shell,因此可以在执行的命令中使用各种扩展匹配符号及重定向符号,如我们将上面的 popen() 改成:popen("sort > /tmp/popen.txt", "w") ,那么在执行程序后,可以看到结果保存在 /tmp/popen.txt 中。

下面这个例子,创建了两个两个管道,一个用以读,一个用以写,模拟了一种全双工的工作情形:
[C++] 纯文本查看 复制代码

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

int main(void)
{
        FILE *pipe_in, *pipe_out;
        char readbuf[128];

        if ((pipe_in = popen("ls", "r")) == NULL) {
                perror("popen");
                exit(EXIT_FAILURE);
        }
        if ((pipe_out = popen("sort", "w")) == NULL) {
                perror("popen");
                exit(EXIT_FAILURE);
        }


        if (( pipe_out = popen("sort", "w")) == NULL) {
                perror("popen");
                exit(EXIT_FAILURE);
        }

        while (fgets(readbuf, 128, pipe_in))
                fputs(readbuf, pipe_out);

        pclose(pipe_in);
        pclose(pipe_out);

        return (0);
}

运行输出:
beyes@beyes  :~/c/popen> ./popen2
popen
popen2
popen2.c
popen.c





欢迎光临 曲径通幽论坛 (http://www.groad.net/bbs/) Powered by Discuz! X3.2