
據我了解,進程描述符儲存在雙向鍊錶資料結構中。但fork
可以用來為同一個進程建立多個子進程,這讓我覺得存在一種樹狀結構,因為多個進程會指向一個父進程。哪個是對的?進程描述符與進程有什麼不同嗎?
答案1
fork()
透過複製進程描述符來建立一個新進程。因此,這兩個進程確實共享(至少在最初)一些數據,但是一旦一個進程啟動改變它的寫入時複製機制確保更改僅本地化到實際進行更改的進程。它是 UNIX 上進程產生的標準機制。
這當然在進程之間創建了一種相當自然的父子關係,但這與核心中的內部表示無關。進程描述符可以實作為鍊錶、樹、雜湊表或任何其他(或多或少)合適的結構。真正需要的只是放置在指向父行程(也可能還有子行程)的核心行程描述符中。是否將其用作結構的關鍵部分是設計決策。在決定這樣的事情時,要考慮的許多事情之一是,例如,一旦父進程退出就會發生什麼——在 UNIX 上,進程init
採用孤立進程(及其所有子進程)。
答案2
您的困惑源自於混合兩件事:(1)保持進程描述符的組織,以及(2)父/子關係。
您不需要父/子關係來決定接下來要執行哪個進程,或(通常)要向哪個進程傳遞訊號。因此,Linux task_struct
(我linux/sched.h
在 3.11.5 核心原始碼中找到)具有:
struct task_struct __rcu *real_parent; /* real parent process */
struct task_struct __rcu *parent; /* recipient of SIGCHLD, wait4() reports */
/*
* children/sibling forms the list of my natural children
*/
struct list_head children; /* list of my children */
struct list_head sibling; /* linkage in my parent's children list */
你是對的,存在一個用於子/父關係的樹結構,但它似乎隱藏在另一個列表中,並且有一個指向父項的指標。
著名的雙向鍊錶在 3.11.5struct task_struct
結構定義中並不明顯。如果我正確地閱讀了程式碼,則未註釋的結構元素struct list_head tasks;
是「組織」雙向鍊錶,但我可能是錯的。