在傳統的Linux系統中,一個進程只包含一個線程,但如今的系統中,包含多個線程的多線程程序司空見慣
而在Linux系統中線程只不過是一種特殊的進程罷了
在現代操做系統中,進程提供兩種虛擬機制:linux
虛擬內存算法
內核把進程的列表存放在叫作任務隊列的雙向循環鏈表中緩存
進程描述符中包含一個具體進程的全部信息數據結構
Linux以經過slab分配器分配task_struct結構,這樣能達到對到對象複用和緩存着色的目的,這樣作是爲了讓那些像x86那樣寄存器較少的硬件體系結結構只要經過棧指針就能夠估算出他的位置
每一個任務的thread_info結構在他的內核棧的尾端分配多線程
內核經過一個惟一的進程標識值或PID來標識每一個進程,內核把每一個進程的PID存放在它們各自的進程描述符中函數
在內核中,訪問任務一般須要得到指向其task_struct的指針,實際上,內核中大部分處理進程程描述符的速度就顯得尤其重要操作系統
進程描述符中state域描述了進程的當前狀態。
五種進程狀態:線程
中止指針
系統調用和異常處理程序是對內核明肯定義的接口
進程只有經過這些接口才能陷入內核執行——對內核的全部訪問都必須經過這些接口
進程家族樹
在Unⅸ系統的進程之間存在—個明顯的繼承關係,在Linux系統中也是如此,全部的進程都是PID爲1的init進程的後代
內核在系統啓動的最後階段啓動init進程
該進程讀取系統的初始化腳本並執行其餘的相關程序,最終完成系統啓動的整個過程對象
Linux的fork()使用寫時拷貝頁實現,寫時拷貝是一種能夠推遲甚至免除拷貝數據的技術,內核此時並不複製整個進程地址空間,而是讓父進程和子進程共享同一個拷貝
只有在須要寫入的時候,數據纔會被複制,從而使各個進程擁有各自的拷貝,也就是說資源的複製只有在須要寫入的時候才進行,在此以前,只是以只讀方式共享,這種技術使地址空間上的頁的拷貝被推遲到實際發生寫入的時候才進行在頁根本不會被寫入的狀況下它們就無須複製了
Linux實現線程的從內核的角度來講,它並無線程這個概念,Linux把全部的線程都當作進程來實現,內核並無準備特別的調度算法或是定義特別的數據結構來表徵線程,相反,線程僅僅被視爲―個與其餘進程共享某些資源的進程,每一個線程都擁有惟一隸屬於本身task_struct,因此在內核中,它看起來就像是一個普通的進程(只是線程和其餘一些進程共享某些資源,如地址空間)
刪除進程描述符:調用release_task函數
若是父進程在子進程以前退出,必須有機制來保證子進程能找到一個新的父親不然這些成爲孤兒的進程就會在退出時永遠處於僵死狀態,白白地耗費內存,前面的部分已經有所暗示於這個問題,解決方法是給子進程在當前線程組內找—個線程做爲父親,若是不行就讓init作它們的父進程 總結 --------- 咱們學到了操做系統中的核心概念——進程,咱們它爲什麼如此重要,以及進程與線程之間的關係,討論了Linux如何存放和表示進程,如何建立進程,如何把新的執行映像裝入到地址空間,如何表示進程的層次關係,父進程又是如何收集其後代的信息以及進程最終如何消亡。