簡體   English   中英

內核如何將線程與進程分開

[英]How does the kernel separate threads from processes

假設我有一個像Firefox這樣的瀏覽器進程,它有pid = 123. Firefox有5個打開的標簽,每個標簽都在一個單獨的線程中運行,所以它總共有5個線程。

  1. 所以我想深入了解內核如何將進程分離到要在struct task_struct或thread_info中執行的線程。

  2. struct task_struct類似,是任務列表的任務描述符。 struct task_struct在哪里包含對這五個線程的引用或鏈接。

  3. 像Firefox這樣的進程的struct thread_struct是否包含對所有5個線程的引用

    要么

    每個線程都被視為Linux內核中的進程。

與Windows不同,Linux在內核中沒有“線程”的實現。 內核為我們提供了有時稱為“輕量級進程”的東西,它們是“進程”和“線程”概念的概括,可以用來實現。

當您閱讀內核代碼並且一方面看到諸如thread_struct之類的thread_struct ,另一方面看到pid (進程ID)時,可能會thread_struct感到困惑。 實際上,兩者都是同一個。 不要被術語混淆。

每個輕量級進程都有一個完全不同的thread_infotask_struct (帶有嵌入式thread_struct )。 您似乎認為一個輕量級進程的task_struct應該指向同一(用戶空間)“進程”中其他(用戶空間)“線程”的task_struct 不是這種情況。 在內核中,每個“線程”都是一個單獨的進程,調度程序分別處理每個“線程”。

Linux有一個名為clone的系統調用,用於創建新的輕量級進程。 調用clone ,必須提供各種標志,指示新進程與現有進程之間將共享的內容。 他們可以共享他們的地址空間,或者他們每個人都可以擁有不同的地址空間。 他們可以共享他們的打開文件,或者他們每個人都有自己的打開文件列表。 他們可以共享信號處理程序,也可以各自擁有自己的信號處理程序。 它們可以位於相同的“線程組”中,也可以位於不同的線程組中。 等等...

雖然“線程”和“進程”在Linux中是相同的,但是您可以通過使用clone創建不共享其地址空間,打開文件,信號處理程序等的進程來實現我們通常認為的“進程”。

您還可以通過使用clone創建共享其地址空間,打開文件,信號處理程序等的進程來實現我們通常認為的“線程”。

如果你看一下task_struct的定義,你會發現它有指向其他結構的指針,例如mm_struct (地址空間), files_struct (打開文件), sighand_struct (信號處理程序)等等。 clone新的“進程”時,將復制所有這些結構。 當您clone一個新的“線程”時,這些結構將在新舊task_struct之間共享 - 它們將指向相同的mm_struct ,相同的files_struct ,依此類推。 無論哪種方式,您只是提供不同的標記來clone ,告訴它要復制什么,以及分享什么。

我剛剛提到了上面的“線程組”,所以你可能會對此感到好奇。 簡而言之,“進程”中的每個“線程”都有自己的PID,但它們都共享相同的TGID(線程組ID)。 TGID都等於第一個程序線程的PID。 用戶空間“PID”,如ps/proc ,實際上是內核中的“TGID”。 當然, clone有一個標志來確定一個新的輕量級進程是否會有一個新的TGID(因此將它放在一個新的“線程組”中)。

UNIX進程也有“父”和“子”。 Linux task_struct有一些指針用於實現父子關系。 而且,正如您可能已經猜到的那樣, clone有一個標志來確定新輕量級進程的父級是什么。 它可以是其稱為進程clone ,或者是所謂的進程的 clone 你能弄清楚在創建“進程”時使用了哪個,在創建“線程”時使用了哪個?

查看手冊頁進行clone ; 這將是非常有教育意義的。 也可以嘗試strace上采用並行線程看到一個節目clone使用。

(其中很多都是從記憶中寫出來的;其他人可以根據需要隨意修改)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM