【发布时间】:2020-02-06 22:59:17
【问题描述】:
问题
我只在终端输出中得到这个。我相信该程序在fork() 调用时卡住了,但我不知道具体原因。
程序名称是q9:
prompt>$ ./q9 inputString
Parent: writing to pipe 'inputString'
任务
- 从终端读取输入到父子管道。
- fork() 创建子进程。
- 从父子管道读取输入。
- 将一些其他字符串连接到从管道读取的字符串。
- 将新连接的字符串写入子到父管道。
- 在父级中,从子级到父级管道读取,并将从管道读取的输出打印到终端。
尝试
我已尝试通过以下方式解决此问题:
- 正在尝试关闭不同位置的管道。我以为我可能遗漏了一些东西或留下了一些东西,但我不这么认为。
- 在父级中放置一个 wait(),因为它可能没有让子级完全运行
- 尝试打印连接字符串的输出,以防万一打印结果混乱。
代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/wait.h>
int main (int argc, char *argv[]) {
// parent RUN
if(argc == 1) {
printf("usage: q9 <string>\n");
return 0;
}
// create two way pipes
int parent_fds[2], child_fds[2];
// create strings to save too
char fromParent[100];
char fromChild[100];
// read:[0] - write:[1]
if (pipe(parent_fds) != 0 && pipe(child_fds) != 0) {
fprintf(stderr, "pipes failed!\n");
}
// close unused pipe end by parent
close(parent_fds[0]);
close(child_fds[1]);
close(child_fds[0]);
// write from terminal to parent pipe FOR child to read
printf("Parent: writing to pipe '%s'\n", argv[1]);
write(parent_fds[1], argv[1], strlen(argv[1]));
close(parent_fds[1]);
// fork() child process
int child = fork();
// NEVER GETS PASSED HERE :(
if (child < 0) {
fprintf(stderr, "fork failed!");
exit(1);
} else if (child == 0) {
printf("I reached the child :)");
// close unwanted pipe ends by child
close(child_fds[0]);
close(parent_fds[1]);
// read from parent pipe
int n = read(parent_fds[0], fromParent, 100);
fromParent[n] = 0;
printf("Child: reading from parent pipe '%s'\n", fromParent);
close(parent_fds[0]);
// Concatinate to what was read in
const char myText[14] = " (added this.)";
strcat(fromParent, myText);
write(child_fds[1], fromParent, strlen(fromParent));
close(child_fds[1]);
printf("Child: writing to pipe - '%s'\n", fromParent);
} else {
// read from child pipe
int n = read(child_fds[0], fromChild, 100);
fromChild[n] = 0;
printf("Parent: reading from pipe - '%s'\n", fromChild);
}
return 0;
}
出了什么问题?
【问题讨论】:
-
您的管道操作顺序不正确。你需要先
fork。然后分别进行父子close调用,然后分别调用read和write。 -
调试的时候最好写信给
stderr。当您写信给stdout(特别是;也写给stderr)时,请确保以换行符结束消息。考虑使用fflush(stdout);以确保输出可见。在输出中包含 PID 编号 - 在打印调用中使用getpid()以确保您不会在fork()调用中获得过时的值。