我将此与之前涉及管道的帖子相比较,我似乎无法找到问题。父母的一切似乎都应该关闭。当我输入一个有效的命令(ex“ls | grep a)但它不是一个有效的命令(ex”ls | grup a)时,程序会停止响应用户输入(它继续运行,但它只是没有“)当你输入一个命令时做任何事情)
主要功能:
int main() {
int i;
char **args;
int pipeCheck = 0;
int argCount = -1;
int blank = 0;
while(1) {
args = getln();
if (args[0] != NULL){
blank = 1;
if (strcmp(args[0],"exit")==0) exit(0);
}
for(i = 0; args[i] != NULL; i++) {
if (strcmp(args[i], "|")==0){
pipeCheck = i;
}
}
if (pipeCheck != 0){
args[pipeCheck] = NULL;
directPipe(args, pipeCheck, argCount, ampCheck);
}
}
} 这是我的程序中的管道功能:</ p>
int directPipe(char ** args, int fileNumber, int argCount,int ampCheck){
int fd[2];
int child1,child2;
int status;
int i;
char * piped[10000];
int count = 0;
for (i = (fileNumber+1); args[i] != NULL; i++){
piped[count] = args[i];
count++;
}
piped[count] = NULL;
printf("\nPipe attempted...\n");
pipe(fd);
child1 = fork();
if (child1==0){
close(1);
dup(fd[1]);
close(fd[0]);
close(fd[1]);
execvp(args[0], args);
printf("Unknown command, please try again.");
exit(0);
}
child2 = fork();
if (child2 ==0){
close(0);
close(fd[1]);
dup(fd[0]);
close(fd[0]);
execvp(piped[0], piped);
printf("Unknown command, please try again.");
exit(0);
}
close(fd[1]);
close(fd[0]);
if (ampCheck == 0){
while (wait(&status) != child1);
while (wait(&status) != child2);
}
else{
printf("\nampCheck = %d",ampCheck);
sigset(child2, printer());
}
return (0);
}
答案 0 :(得分:0)
你的问题是wait()
循环对:
while (wait(&status) != child1);
while (wait(&status) != child2);
在你的场景中,第二个孩子在第一个孩子出现之前死亡,所以你在第一个循环中收集它的尸体,但忽略它。然后第二个循环进入忙碌的等待状态,因为不再有孩子了。
至少,您需要:
int corpse;
while ((corpse = wait(&status)) != -1 && corpse != child1 && corpse != child2)
;
while ((corpse = wait(&status)) != -1 && corpse != child1 && corpse != child2)
;
这可以处理以任何顺序死亡的儿童 - 但只有两个孩子。对于更通用的管道(三个或更多进程),您必须更加努力 - 并使用单个循环。更一般的形式将是:
int corpse;
while ((corpse = wait(&status)) != -1)
{
if (record_death_of_child(corpse, status) == -1)
break;
}
您的流程创建代码记录所创建流程的PID,record_death_of_child()
代码处理该PIDS列表,并且当当前管道中没有更多子代值时返回-1(和0)除此以外)。或者你可以让它使用其他一些启发式来确定何时退出循环。请注意,如果您在后台运行长时间的作业,则其中任何一个都可能死亡,并且该循环将收集该尸体。 “记录死亡”功能也需要处理这样的过程 - 例如,它们不能再被带到前台,你需要报告它们已经退出等等。
您也可能最终使用waitpid()
,因为您可以安排在WNOHANG
仍在运行的后台进程时不挂起。