![](/img/trans.png)
[英]Implementing shell in C and need help handling input/output redirection
[英]Implementing shell in C - pipelined input has correct output but exits loop
我正在嘗試在C中實現一個可處理多個管道的基本shell。 它等待輸入並在for循環中執行命令。 收到EOF時,它將停止等待輸入並退出。
現在,當我輸入管道命令時,例如ls | wc | grep ...
shell會輸出正確的輸出ls | wc | grep ...
ls | wc | grep ...
ls | wc | grep ...
但它停止等待輸入,並退出外部while循環,而不是等待下一行輸入。
我發現發生這種情況是因為while循環中的fget返回null(stdin以某種方式得到EOF嗎?)。 創建派生,創建管道或執行時,我沒有任何錯誤。
但是,如果我一次輸入一個命令而沒有任何管道(例如ls
,它將成功打印出正確的輸出, 並按需要等待下一行輸入。
我的程序在嘗試執行每個命令之前將輸入的每一行解析為一個struct
(在下面省略)。 設計該struct
是為了使我可以輕松將解析后的參數傳遞給execvp
,在此不再贅述。
這是我的代碼的簡化版本,省略了大多數錯誤檢查:
FILE* input;
char line[MAX_LINE];
input = stdin;
printf("> ");
fflush(stdout);
while (fgets(line, sizeof(line), input)) {
int i;
struct cmdLine;
/* struct defined elsewhere
** commands = # of commands in parsed input
** start = index where a command and its args start
** args[] = array holding each command/arg
*/
/* parse input line into cmdLine */
...
/* exec all commands in pipeline except the last */
for (i = 0; i < cmdLine.commands-1; ++i) {
int pd[2];
pipe(pd);
if (fork() == 0) {
dup2(pd[1], 1);
execvp(cmdLine.args[cmdLine.start[i]], &(cmdLine.args[cmdLine.start[i]]));
} else {
wait(NULL);
}
dup2(pd[0], 0);
close(pd[1]);
}
/* exec last command */
if (fork() == 0) {
execvp(cmdLine.args[cmdLine.start[i]], &(cmdLine.args[cmdLine.start[i]]));
} else {
wait(NULL);
}
if (stdin == input) {
printf("> "); /* print shell prompt */
fflush(stdout);
}
}
幾乎可以肯定,我在欺騙某個地方弄得一團糟,但是我已經嘗試了好幾個小時,而且我不明白自己在做什么錯。 EOF是否以某種方式發送到stdin,以便封閉的fgets
返回NULL
?
通過使用0(= stdin
)作為第二個參數調用dup2
,您將在for
循環的每次迭代結束時關閉原始的stdin
,因此您不再可以通過原始的stdin與您的程序進行實際交談。
代碼中的問題是,您試圖將所有管道連接在一起並傳遞給其他人。 那是行不通的。 這是應該起作用的方法:
stdin
,並將下一個管道的輸入連接到其stdout
(如果要處理管道鏈中的最后一個進程,則將其連接到主程序的stdout
)。 poll()
進行讀取,從具有活動的任何管道上讀取,然后寫入下一個管道的輸入(最后是您自己的stdout
)。 如果在其中一個管道上得到EOF,請關閉下一個管道的輸入(並從輸出數組中刪除EOF管道輸出)。 一旦所有FD關閉,退出循環。 編輯:我只是想到了另一種更簡單的方法,它需要更少的代碼更改,但我還沒有完全考慮。 :)問題在於您正在銷毀自己的標准輸入。 如果您在派生的子級中執行所有這些操作(即整個“處理一行命令”),則在進程之間替換stdin根本不會影響父進程。但是,這仍然需要內核中的大量緩沖,因此它可能不會擴展。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.