在C++中,我们可以使用管道来实现子进程与父进程之间的通信。通常,我们会使用pipe()
函数来创建一个管道,然后使用fork()
函数创建一个子进程。子进程可以通过dup2()
函数将管道的一端复制到标准输出或标准错误,这样子进程就可以将输出写入管道,父进程可以通过管道读出子进程的输出。
但是,如果我们不想让子进程的输出写入标准输出或标准错误,而是想让它写入其他文件描述符,该如何解决呢?
2. 解决方案
一种可能的解决方案是,我们在创建管道时,指定管道的一端的文件描述符。然后,我们在子进程中使用dup2()
函数将这个文件描述符复制到标准输出或标准错误,这样子进程就可以将输出写入这个文件描述符。在父进程中,我们可以打开这个文件描述符,并从中读取子进程的输出。
例如,以下代码演示了如何使用管道在子进程与父进程之间进行通信,并让子进程将输出写入一个指定的文件描述符:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
int cout_pipe[2];
pipe(cout_pipe);
fork();
if (child) {
dup2(cout_pipe[1], STDOUT_FILENO);
execv("./child", NULL);
}
if (parent) {
close(cout_pipe[1]);
FILE *cout_file = fdopen(cout_pipe[0], "r");
char buf[1024];
while (fgets(buf, sizeof(buf), cout_file) != NULL) {
printf("%s", buf);
}
fclose(cout_file);
}
return 0;
}
在上面的代码中,我们使用pipe()
函数创建了一个管道,并使用fork()
函数创建了一个子进程。在子进程中,我们使用dup2()
函数将管道的一端的文件描述符复制到标准输出,然后执行了一个名为"./child"的程序。在父进程中,我们关闭了管道的一端,然后使用fdopen()
函数将管道另一端的文件描述符打开为一个文件流,并从中读取子进程的输出。
我们还可以将管道的一端的文件描述符传递给子进程,作为命令行参数。在子进程中,我们可以使用sys.argv
数组来获取命令行参数,并将其转换为整数。然后,我们可以使用os.fdopen()
函数将这个整数转换为一个文件流,并从中读取数据。
例如,以下代码演示了如何使用管道在子进程与父进程之间进行通信,并让子进程将输出写入一个由父进程指定的文件描述符:
# child.py
import sys
import os
fd = int(sys.argv[1])
f = os.fdopen(fd, "w")
f.write("Hello from child process!\n")
f.close()
# parent.cpp
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
int cout_pipe[2];
pipe(cout_pipe);
fork();
if (child) {
char fd_str[10];
sprintf(fd_str, "%d", cout_pipe[1]);
execlp("python", "python", "child.py", fd_str, NULL);
}
if (parent) {
close(cout_pipe[1]);
FILE *cout_file = fdopen(cout_pipe[0], "r");
char buf[1024];
while (fgets(buf, sizeof(buf), cout_file) != NULL) {
printf("%s", buf);
}
fclose(cout_file);
}
return 0;
}
在上面的代码中,我们在父进程中创建一个管道,并使用fork()
函数创建了一个子进程。在子进程中,我们使用execlp()
函数执行一个名为"python"的程序,并传递管道的一端的文件描述符作为命令行参数。在父进程中,我们关闭了管道的一端,然后使用fdopen()
函数将管道另一端的文件描述符打开为一个文件流,并从中读取子进程的输出。