[英]Fork never enters child's process
我正在編寫模仿外殼行為的代碼,特別是&和|。
我的函數接收用戶命令,並檢查末尾是否有&,然后子進程應在后台運行,父進程不應等待其完成並繼續執行命令。
還應該檢查是否有| 在輸入數組中運行兩個子進程,同時對它們的stdin和stdout進行管道傳輸。
我已經實現了&的行為,但是每當我編譯並運行代碼時,我只會從父進程獲取printf語句。
我想聽聽如何解決此問題的想法,此外,我希望您對實施|提出任何建議。 (煙斗)以及如何防止僵屍。
int process_arglist(int count, char** arglist) {
int pid = fork();
printf("%d", pid);
switch (pid) {
case -1:
fprintf(stderr, "ERROR: fork failed\n");
return 1;
break;
case 0: // Son's proccess
printf("I got to son");
//check last arglist argument
if (strcmp(arglist[count - 1], "&") == 0) {
setpgid(0, 0);
arglist[count - 1] = NULL;
if (execvp(*arglist, arglist) < 0) { //execute the command
fprintf(stderr, "ERROR: execvp failed\n");
exit(1);
}
} else { //There's no & at the end, look for pipes
int i = 0;
while (i < count) {
if (strcmp(arglist[i], "|") == 0) {
int pid2 = fork();
if (pid2 < 0) {
//fork failed, handle error
}
if (pid2 == 0) { // Son's proccess
} else { //Parent's code
}
}
}
}
break;
//in case no & and no |, call execvp
default: //Parent's code
printf("I go to parent");
return 1;
break;
}
return 0;
}
輸出總是“我去父母”
我假設您的代碼適用於Linux或其他POSIX系統。 閱讀一些有關Linux編程的好書(也許是舊的Advanced Linux Programming ,可以免費下載或更新)。
stdio(3)是緩沖的 , stdout
和printf
通常(但並非總是)是行緩沖的。 出於效率方面的原因而發生緩沖(非常頻繁地調用write(2) ,例如,每個輸出字節一次, 非常慢;您應該更喜歡對幾千字節的塊執行write
-s)。
順便說一句,通過使用errno(3)至perror(3) (或errno
上的strerror(3)) ,您將更好地處理系統調用失敗(請參閱intro(2)和syscalls(2) )。 您(和您的Shell用戶)需要被告知失敗原因(您當前的代碼未顯示)。
我建議經常以\\n
結束printf
格式控制字符串(當stdout是行緩沖時有效)或在適當的地方調用fflush(3) 。
根據經驗,我建議使用fflush(NULL);
在每次調用fork(2)之前 。
你觀察到的行為是與假設,一些一致printf
-ed數據留在緩沖區(例如stdout
)。
您可以在程序(或其他程序,例如某些現有的shell進程)上使用strace(1)來了解完成了哪些系統調用 。
你應該與所有警告和調試信息(如編譯gcc -Wall -Wextra -g
與GCC ),改善你的代碼,以獲得沒有警告,並使用調試器gdb
(小心,它可以在分叉過程中使用)。
我正在編寫模仿外殼行為的代碼
您可能正在編寫一些shell。 然后從靈感中研究現有自由軟件外殼的源代碼(大多數Linux外殼都是自由軟件)。
我將不勝感激有關實施|的建議。 (煙斗)以及如何防止僵屍。
解釋所有需要大量空間的內容(一本書的幾個章節,或者一本書的整個章節),並且不適合在這里或任何其他論壇中使用。 因此,請閱讀一本好的Linux或POSIX 編程書 。 關於管道,請讀取pipe(7) (應在fork
之前使用pipe(2)創建)。 關於避免僵屍進程 ,您需要仔細調用waitpid(2)或類似的調用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.