我有这个任务,我必须使用fork创建两个孩子。父母必须向这些孩子发送一些信件并收回一个号码。沟通必须使用管道完成。 我无法弄清楚的是,为什么我的代码设法将信件发送给孩子,但随后却无所事事。起初我以为是因为waitpid()调用,但似乎并非如此。令我感到困惑的是,如果我停止阅读其中一个子进程并只发送一个随机数,其他一切都按预期工作。
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <string.h>
#define PIPE_1 0 // write to 1st child
#define PIPE_2 1 // write to parent from 1st child
#define PIPE_3 2 // write to 2nd child
#define PIPE_4 3 // write to parent from 2nd child
int main()
{
pid_t p1, p2;
int pipes[4][2];
FILE *read[4], *write[4];
int k;
for (k = 0; k < 4; k++){
if (-1 == pipe(pipes[k]) ){
perror("Error creating pipe");
exit(k+1);
}
read[k] = fdopen(pipes[k][0], "r");
write[k] = fdopen(pipes[k][1], "w");
}
if (-1 == (p1 = fork()) ){
perror("Error, failed to fork first child");
exit(5);
}
if (p1 == 0){
// 1st child
fclose(write[PIPE_1]);
int caseChange = 0;
char c;
while( fscanf(read[PIPE_1], "%c", &c) != EOF){
if (c >= 97 && c <= 122){
c -= 32;
caseChange++;
}
printf("[Process (%d)]: %c\n", getpid(), c);
}
fclose(read[PIPE_1]);
fclose(read[PIPE_2]);
fprintf(write[PIPE_2],"%d",caseChange);
fflush(write[PIPE_2]);
fclose(write[PIPE_2]);
}
else{
if (-1 == (p2 = fork()) ){
perror("Error, failed to fork second child");
exit(6);
}
if (p2 == 0){
// 2nd child
fclose(write[PIPE_3]);
int caseChange = 0;
char c;
while( fscanf(read[PIPE_3], "%c", &c) != EOF){
if (c >= 97 && c <= 122){
c -= 32;
caseChange++;
}
printf("[Process (%d)]: %c\n", getpid(), c);
}
fclose(read[PIPE_3]);
fclose(read[PIPE_4]);
fprintf(write[PIPE_4],"%d",caseChange);
fflush(write[PIPE_4]);
fclose(write[PIPE_4]);
}
else{
// Parent
//char *string = (char*) malloc(100);
char string[100];
scanf("%s", string);
int i;
int readCaseChange, caseChange = 0;
fclose(read[PIPE_1]);
for (i = 0; i < strlen(string); i+=2){
fprintf(write[PIPE_1],"%c",string[i]);
fflush(write[PIPE_1]);
}
fclose(write[PIPE_1]);
fclose(read[PIPE_3]);
for (i = 1; i < strlen(string); i+=2){
fprintf(write[PIPE_3],"%c",string[i]);
fflush(write[PIPE_3]);
}
fclose(write[PIPE_3]);
waitpid(p1, NULL, 0);
fclose(write[PIPE_2]);
fscanf(read[PIPE_2], "%d", &readCaseChange);
fclose(read[PIPE_2]);
caseChange += readCaseChange;
waitpid(p2, NULL, 0);
fclose(write[PIPE_4]);
fscanf(read[PIPE_4], "%d", &readCaseChange);
fclose(read[PIPE_4]);
caseChange += readCaseChange;
printf("%d\n", caseChange);
fflush(stdout);
}
}
return 0;
}
答案 0 :(得分:1)
您希望关闭每个孩子中没有使用的任何内容,尤其是父进程的作者方:
// 1st child
fclose(write[PIPE_1]);
fclose(write[PIPE_3]);
// 2nd child
fclose(write[PIPE_1]);
fclose(write[PIPE_3]);
否则,子进程将使编写器端保持打开状态并防止管道完全关闭,从而使其无法在子进程中获得EOF。你部分这样做,但是因为第二个孩子写了[PIPE_1],所以PIPE_1从未完全关闭。