所以我知道什麼時候在 shell 中運行一個可執行文件,然後 shell 將其分叉到一個子進程中,然後執行 exec 來獲取可執行檔的程式和資料記憶體。因此,如果我的 shell 現在關閉/退出,那麼它的所有關聯子進程也會被終止。
我讀到在linux中每個行程都是透過fork() exec()建立的。我很好奇,並且想知道每當透過雙擊其圖標啟動應用程式時,哪個進程 forks() exec() 它,我知道它是某個作業系統進程,我想知道哪個進程
謝謝你!
回答 追蹤到 /sbin/upstart
答案1
首先,有一點術語。
可執行檔是系統中一個簡單的檔案。簡而言之,進程是執行嵌入在可執行檔中的程式的外殼。
你是對的啟動可執行檔的方式:
以雙擊可執行圖示的圖形介面為例,您可以從顯示您單擊的圖示的進程中分叉可執行文件,基本上使用以下原始程式碼:
const char *exe_path = taken_from_icon();
int pid = fork();
if(pid == 0)
{
// I am the new child
execl(exe_path, exe_path, NULL);
// exec only return in case of failure
exit(EXIT_FAILURE);
}
// I am the graphical interface,
// Continue and wait for another clic
但是死亡與親子關係孩子的情況並不完全像你說的。
基本上,當父進程仍然處於活動狀態時,子進程是其父親的子進程(是的!-)它的 PPID(父進程 ID)設定為派生它的仍然活動的進程。
當父進程終止時,情況就會改變。子進程繼續存活,但其 PPID 被設定為仍然存活的祖父進程。總有一個,因為init
進程永遠不會消亡。
事實上,當 shell 本身死亡時,shell 子代也會死亡,這是一個特定的事實。我認為有兩個原因:
第一個:shell 通常維護它派生的 PID 清單。當貝殼死亡時,它會殺死所有的人。主要 shell 有一個
disown
內建指令,可以從該清單中刪除子進程,並在 shell 終止時讓它繼續存在。看bash 手冊頁:預設情況下,shell 在收到 SIGHUP 後退出。在退出之前,互動式 shell 會重新傳送給所有正在執行或已停止的作業 SIGHUP。停止的作業將會被傳送 SIGCONT 以確保它們收到 SIGHUP。為了防止 shell 向特定作業發送訊號,應該使用 disown 內建指令將其從作業表中刪除(請參閱下方的 SHELL BUILTIN 指令),或使用 disown -h 將其標記為不接收 SIGHUP。
第二個:shell 子級通常將其 stdin、stdout 和 stderr 透過管道連接到 shell 本身。如果 shell 停止使用子 stdout(通常是列印它),或關閉其管道端,則子進程在寫入其 stdout 時可能會失敗,這可能會阻止或殺死它。