[英]Problems with piping for basic shell program
我已將其與以前涉及管道的帖子進行了比較,但似乎找不到問題。 父母中的一切似乎都應該關閉。 當我輸入有效命令(例如“ ls | grep a”)時,它可以正常工作,但是如果它不是有效命令(例如“ ls | grep 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);
}
}
這是我程序中用於管道的函數:
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);
}
您的問題是一對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
仍在運行的后台進程時不掛起。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.