如何使用popen?

How to use popen?

我正在尝试与 stdinstdout 进行进程间通信。我找到的 Posix 函数是 popen,但我没能写出有效的示例代码。请帮助我完成这项工作。


我必须使用 dup 吗?我可以看到一些使用 Google 找到的例子。但是 dup 的 Linux 手册确实无法帮助我理解如何使用它。

a.c

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

int main(void){
    char *s;

    for(;;){
        scanf("%ms",&s);
        printf("%s\n",s);
        if(!strcmp(s,"quit")){
            free(s);
            printf("bye~\n");
            exit(EXIT_SUCCESS);
        }
        free(s);
    }
}

b.c

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

int main(void){
    FILE *fRead;
    FILE *fWrite;
    char *s;
    int i;

    fRead=popen("~/a.out","r");
    fWrite=popen("~/a.out","w");
    for(i=1;i<=10;++i){
        fprintf(fWrite,"%d",i);
        fscanf(fRead,"%ms",&s);
        printf("%s\n",s);
        free(s);
    }
}

根据 POSIX 的定义,管道是一种单向通信机制——它们只在一个方向上工作。为了同时重定向标准输入和标准输出,您需要创建两个管道 — 而 popen 函数无法做到这一点。

虽然不太方便,但直接使用系统调用forkpipedup2exec不难达到你想要的效果:

rc = pipe(p1);
if(rc < 0) ...
rc = pipe(p2);
if(rc < 0) ...

rc = fork();
if(rc < 0) {
    ...
} else if(rc == 0) {
    /* child */
    close(p1[0]);
    close(p2[1]);
    dup2(p1[1], 1);
    dup2(p2[0], 0);
    execlp(...);
    exit(1);
} else {
    /* parent */
    close(p1[1]);
    close(p2[0]);
    ...
}

还有其他解决方案 — 您可以使用 socketpair 系统调用来避免对两个管道的需要,甚至可以直接使用 Unix 域套接字。