曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 5922|回复: 0
打印 上一主题 下一主题

[进程] popen() 与 pclose()

[复制链接]

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34395
跳转到指定楼层
楼主
发表于 2009-10-11 21:06:27 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
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[i], 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
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2025-5-6 09:48 , Processed in 0.069605 second(s), 23 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表