鴻蒙內核源碼註釋倉庫 >> 精讀內核源碼,中文註解分析, 深挖地基工程,大腦永久記憶, 四大源碼倉每日同步更新 < Gitee | Github | CSDN | Coding > node
鴻蒙內核源碼分析博客 >> 故事說內核,問答式導讀,生活式比喻,表格化說明,圖形化展現,主流站點每日同步更新 < CSDN | 開源中國 | WeHarmony >linux
本篇說清楚進程.
讀本篇以前建議先讀git
鴻蒙內核源碼分析(總目錄) | 精讀內核源碼 深挖地基工程 < CSDN | 開源中國 | WeHarmony > github
調度故事篇,其中有對進程生活場景式的比喻.緩存
官方基本概念
從系統的角度看,進程是資源管理單元。進程可使用或等待CPU、使用內存空間等系統資源,並獨立於其它進程運行。安全
鴻蒙內核的進程模塊能夠給用戶提供多個進程,實現了進程之間的切換和通訊,幫助用戶管理業務程序流程。這樣用戶能夠將更多的精力投入到業務功能的實現中。數據結構
鴻蒙內核中的進程採用搶佔式調度機制,支持時間片輪轉調度方式和FIFO調度機制。app
鴻蒙內核的進程一共有32個優先級(0-31),用戶進程可配置的優先級有22個(10-31),最高優先級爲10,最低優先級爲31。模塊化
高優先級的進程可搶佔低優先級進程,低優先級進程必須在高優先級進程阻塞或結束後才能獲得調度。函數
每個用戶態進程均擁有本身獨立的進程空間,相互之間不可見,實現進程間隔離。
官方概念解讀
官方文檔最重要的一句話是進程是資源管理單元,注意是管理資源的, 資源是什麼? 內存,任務,文件,信號量等等都是資源.故事篇中對進程作了一個形象的比喻(導演),負責節目(任務)的演出,負責協調節目運行時所需的各類資源.讓節目能高效順利的完成.
鴻蒙內核源碼分析定位爲深挖內核地基,構築底層網圖.就要解剖真身.進程(LosProcessCB)原始真身以下,本篇一一剖析它,看看它的五臟六腑裏到底有啥.
ProcessCB真身
typedef struct ProcessCB { CHAR processName[OS_PCB_NAME_LEN]; /**< Process name */ //進程名稱 UINT32 processID; /**< process ID = leader thread ID */ //進程ID,由進程池分配,範圍[0,64] UINT16 processStatus; /**< [15:4] process Status; [3:0] The number of threads currently running in the process *///這裏設計很巧妙.用一個16表示了兩層邏輯 數量和狀態,點贊! UINT16 priority; /**< process priority */ //進程優先級 UINT16 policy; /**< process policy */ //進程的調度方式,默認搶佔式 UINT16 timeSlice; /**< Remaining time slice *///進程時間片,默認2個tick UINT16 consoleID; /**< The console id of task belongs *///任務的控制檯id歸屬 UINT16 processMode; /**< Kernel Mode:0; User Mode:1; */ //模式指定爲內核仍是用戶進程 UINT32 parentProcessID; /**< Parent process ID */ //父進程ID UINT32 exitCode; /**< process exit status */ //進程退出狀態碼 LOS_DL_LIST pendList; /**< Block list to which the process belongs */ //進程所屬的阻塞列表,若是因拿鎖失敗,就由此節點掛到等鎖鏈表上 LOS_DL_LIST childrenList; /**< my children process list */ //孩子進程都掛到這裏,造成雙循環鏈表 LOS_DL_LIST exitChildList; /**< my exit children process list */ //那些要退出孩子進程掛到這裏,白髮人送黑髮人。 LOS_DL_LIST siblingList; /**< linkage in my parent's children list */ //兄弟進程鏈表, 56個民族是一家,來自同一個父進程. ProcessGroup *group; /**< Process group to which a process belongs */ //所屬進程組 LOS_DL_LIST subordinateGroupList; /**< linkage in my group list */ //進程是組長時,有哪些組員進程 UINT32 threadGroupID; /**< Which thread group , is the main thread ID of the process */ //哪一個線程組是進程的主線程ID UINT32 threadScheduleMap; /**< The scheduling bitmap table for the thread group of the process */ //進程的各線程調度位圖 LOS_DL_LIST threadSiblingList; /**< List of threads under this process *///進程的線程(任務)列表 LOS_DL_LIST threadPriQueueList[OS_PRIORITY_QUEUE_NUM]; /**< The process's thread group schedules the priority hash table */ //進程的線程組調度優先級哈希表 volatile UINT32 threadNumber; /**< Number of threads alive under this process */ //此進程下的活動線程數 UINT32 threadCount; /**< Total number of threads created under this process */ //在此進程下建立的線程總數 LOS_DL_LIST waitList; /**< The process holds the waitLits to support wait/waitpid *///進程持有等待鏈表以支持wait/waitpid #if (LOSCFG_KERNEL_SMP == YES) UINT32 timerCpu; /**< CPU core number of this task is delayed or pended *///統計各線程被延期或阻塞的時間 #endif UINTPTR sigHandler; /**< signal handler */ //信號處理函數,處理如 SIGSYS 等信號 sigset_t sigShare; /**< signal share bit */ //信號共享位 #if (LOSCFG_KERNEL_LITEIPC == YES) ProcIpcInfo ipcInfo; /**< memory pool for lite ipc */ //用於進程間通信的虛擬設備文件系統,設備裝載點爲 /dev/lite_ipc #endif LosVmSpace *vmSpace; /**< VMM space for processes */ //虛擬空間,描述進程虛擬內存的數據結構,linux稱爲內存描述符 #ifdef LOSCFG_FS_VFS struct files_struct *files; /**< Files held by the process */ //進程所持有的全部文件,注者稱之爲進程的文件管理器 #endif //每一個進程都有屬於本身的文件管理器,記錄對文件的操做. 注意:一個文件能夠被多個進程操做 timer_t timerID; /**< iTimer */ #ifdef LOSCFG_SECURITY_CAPABILITY //安全能力 User *user; //進程的擁有者 UINT32 capability; //安全能力範圍 對應 CAP_SETGID #endif #ifdef LOSCFG_SECURITY_VID TimerIdMap timerIdMap; #endif #ifdef LOSCFG_DRIVERS_TZDRIVER struct file *execFile; /**< Exec bin of the process */ #endif mode_t umask; } LosProcessCB;
結構體仍是比較複雜,雖一一都作了註解,但仍是不夠清晰,沒有模塊化.這裏把它分解成如下六大塊逐一分析:
第一大塊:和任務(線程)關係
UINT32 threadGroupID; /**< Which thread group , is the main thread ID of the process */ //哪一個線程組是進程的主線程ID UINT32 threadScheduleMap; /**< The scheduling bitmap table for the thread group of the process */ //進程的各線程調度位圖 LOS_DL_LIST threadSiblingList; /**< List of threads under this process *///進程的線程(任務)列表 LOS_DL_LIST threadPriQueueList[OS_PRIORITY_QUEUE_NUM]; /**< The process's thread group schedules the priority hash table */ //進程的線程組調度優先級哈希表 volatile UINT32 threadNumber; /**< Number of threads alive under this process */ //此進程下的活動線程數 UINT32 threadCount; /**< Total number of threads created under this process */ //在此進程下建立的線程總數 LOS_DL_LIST waitList; /**< The process holds the waitLits to support wait/waitpid *///進程持有等待鏈表以支持wait/waitpid
進程和線程的關係是1:N的關係,能夠有多個任務但一個任務不能同屬於多個進程. 任務就是線程,是CPU的調度單元.任務是什麼?
鴻蒙內核源碼分析(總目錄) | 精讀內核源碼 深挖地基工程 < CSDN | 開源中國 | WeHarmony >
中的線程概念篇中有詳細的介紹,可自行翻看. 任務是做爲一種資源被進程管理的,進程爲任務提供內存支持,提供文件支持,提供設備支持.
進程怎麼管理線程的,進程怎麼同步線程的狀態?
1.進程加載時會找到main函數建立第一個線程,通常爲主線程,其第一條指令就是main的第一條指令,一切從哪裏開始.
2.執行線程過程當中根據代碼建立新的線程,其本質和main函數建立的線程沒有區別,統一參與調度.
3.線程和線程的關係能夠是獨立(detached)的,也能夠是聯結(join)的.聯結指的是一個線程能夠操做另外一個線程(包括回收資源,被對方幹掉).
4.進程的主線程或全部線程運行結束後,進程轉爲殭屍態,通常只能由全部線程結束後,進程才能天然消亡.
5.進程建立後進入就緒態,發生進程切換時,就緒列表中最高優先級的進程被執行,從而進入運行態。若此時該進程中已無其它線程處於就緒態,則該進程從就緒列表刪除,只處於運行態;若此時該進程中還有其它線程處於就緒態,則該進程依舊在就緒隊列,此時進程的就緒態和運行態共存。這裏要注意的是進程能夠容許多種狀態並存! 狀態並存很天然的會想到位圖管理,系列篇中有對位圖詳細的介紹.
6.進程內全部的線程均處於阻塞態時,進程在最後一個線程轉爲阻塞態時,同步進入阻塞態,而後發生進程切換。
7.阻塞進程內的任意線程恢復就緒態時,進程被加入到就緒隊列,同步轉爲就緒態,若此時發生進程切換,則進程狀態由就緒態轉爲運行態
8.進程內的最後一個就緒態線程處於阻塞態時,進程從就緒列表中刪除,進程由就緒態轉爲阻塞態。
9.進程由運行態轉爲就緒態的狀況有如下兩種:
有更高優先級的進程建立或者恢復後,會發生進程調度,此刻就緒列表中最高優先級進程變爲運行態,那麼原先運行的進程由運行態變爲就緒態。
若進程的調度策略爲SCHED_RR,且存在同一優先級的另外一個進程處於就緒態,則該進程的時間片消耗光以後,該進程由運行態轉爲就緒態,另外一個同優先級的進程由就緒態轉爲運行態。
第二大塊:和其餘進程的關係
CHAR processName[OS_PCB_NAME_LEN]; /**< Process name */ //進程名稱 UINT32 processID; /**< process ID = leader thread ID */ //進程ID,由進程池分配,範圍[0,64] UINT16 processStatus; /**< [15:4] process Status; [3:0] The number of threads currently running in the process *///這裏設計很巧妙.用一個16表示了兩層邏輯 數量和狀態,點贊! UINT16 priority; /**< process priority */ //進程優先級 UINT16 policy; /**< process policy */ //進程的調度方式,默認搶佔式 UINT16 timeSlice; /**< Remaining time slice *///進程時間片,默認2個tick UINT16 consoleID; /**< The console id of task belongs *///任務的控制檯id歸屬 UINT16 processMode; /**< Kernel Mode:0; User Mode:1; */ //模式指定爲內核仍是用戶進程 UINT32 parentProcessID; /**< Parent process ID */ //父進程ID UINT32 exitCode; /**< process exit status */ //進程退出狀態碼 LOS_DL_LIST pendList; /**< Block list to which the process belongs */ //進程所屬的阻塞列表,若是因拿鎖失敗,就由此節點掛到等鎖鏈表上 LOS_DL_LIST childrenList; /**< my children process list */ //孩子進程都掛到這裏,造成雙循環鏈表 LOS_DL_LIST exitChildList; /**< my exit children process list */ //那些要退出孩子進程掛到這裏,白髮人送黑髮人。 LOS_DL_LIST siblingList; /**< linkage in my parent's children list */ //兄弟進程鏈表, 56個民族是一家,來自同一個父進程. #if (LOSCFG_KERNEL_LITEIPC == YES) ProcIpcInfo ipcInfo; /**< memory pool for lite ipc */ //用於進程間通信的虛擬設備文件系統,設備裝載點爲 /dev/lite_ipc #endif
進程是家族式管理的,內核進程和用戶進程分別有本身的根祖先,祖先進程在內核初始化時就建立好了,分別是1號(用戶進程祖先)和2號(內核進程祖先)進程.進程剛生下來就肯定了本身的基因,父親是誰,兄弟姐妹都有誰,固然你也本身發展本身的孩子進程,最終會造成樹狀結構,每一個進程都能找到本身的位置.進程的管理遵循如下幾點原則:
1.進程退出時會主動釋放持有的進程資源,但持有的進程pid資源須要父進程經過wait/waitpid或父進程退出時回收.
2.一個子進程的消亡要通知父進程,以便父進程在族譜上抹掉它的痕跡,一些異常狀況下的壞孩子進程消亡沒有告知父進程的,系統也會檢測到而回收其資源.
3.進程建立後,只能操做本身進程空間的資源,沒法操做其它進程的資源(共享資源除外).
4.進程間有多種通信方式,liteipc是進程間基於文件的通信方式.
5.高優先級的進程可搶佔低優先級進程,低優先級進程必須在高優先級進程阻塞或結束後才能獲得調度。
第三大塊:進程的五種狀態
初始化(Init):該進程正在被建立。
就緒(Ready):該進程在就緒列表中,等待CPU調度。
運行(Running):該進程正在運行。
阻塞(Pend):該進程被阻塞掛起。本進程內全部的線程均被阻塞時,進程被阻塞掛起。
殭屍態(Zombies):該進程運行結束,等待父進程回收其控制塊資源。
第四大塊:和內存的關係
LosVmSpace *vmSpace; /**< VMM space for processes */ //虛擬空間,描述進程虛擬內存的數據結構,linux稱爲內存描述符
進程與內存有關的就只有LosVmSpace一個,是進程空間,每個用戶態進程均擁有本身獨立的進程空間,相互之間不可見,實現進程間隔離,獨立進程空間意味着每一個進程都要將本身的虛擬內存和物理內存進行映射.並將映射區保存在本身的進程空間.代碼區,數據區,堆棧區,映射區都存放在進程空間中,但內核態進程的空間是共用的,只需一次映射.具體的進入系列篇中
鴻蒙內核源碼分析(總目錄) | 精讀內核源碼 深挖地基工程 < CSDN | 開源中國 | WeHarmony >
查看內存篇.詳細介紹了虛擬內存,物理內存,線性地址,映射關係,共享內存,分配回收,頁面置換的概念和實現.
第五大塊:和文件的關係
#ifdef LOSCFG_FS_VFS struct files_struct *files; /**< Files held by the process */ //進程所持有的全部文件,注者稱之爲進程的文件管理器 #endif //每一個進程都有屬於本身的文件管理器,記錄對文件的操做. 注意:一個文件能夠被多個進程操做
進程與文件系統有關的就只有files_struct,可理解爲進程的文件管理器,文件也是很複雜的一大塊, 後續有系列篇來說解文件系統的實現. 理解文件系統的主脈絡是:
1.一個真實的物理文件(inode),能夠同時被多個進程打開,並有進程獨立的文件描述符, 進程文件描述符(ProcessFD)後邊映射的是系統文件描述符(SystemFD).
2.系統文件描述符(0-stdin,1-stdout,2-stderr)默認被內核佔用,任何進程的文件描述符前三個都是(stdin,stdout,stderr),默認已經打開,能夠直接往裏面讀寫數據.
3.文件映射跟內存映射同樣,每一個進程都須要單獨對同一個文件進行映射,page_mapping記錄了映射關係,而頁高速緩存(page cache)提供了文件實際的存放在內存位置.
4.內存<->文件的置換以頁爲單位(4K),進程並不能對硬盤文件直接操做,必須經過頁高速緩存(page cache)完成.其中會涉及到一些經典的概念好比COW(寫時拷貝)技術.後續會詳細說明.
第六大塊:輔助工具
#if (LOSCFG_KERNEL_SMP == YES) UINT32 timerCpu; /**< CPU core number of this task is delayed or pended *///統計各線程被延期或阻塞的時間 #endif #ifdef LOSCFG_SECURITY_CAPABILITY //安全能力 User *user; //進程的擁有者 UINT32 capability; //安全能力範圍 對應 CAP_SETGID #endif #ifdef LOSCFG_SECURITY_VID TimerIdMap timerIdMap; #endif #ifdef LOSCFG_DRIVERS_TZDRIVER struct file *execFile; /**< Exec bin of the process */ #endif
其他是一些安全性,統計性的能力.
以上就是進程的五臟六腑,看清楚它鴻蒙內核的影像會清晰不少!
喜歡就請注入源動力吧
各大站點搜 "鴻蒙內核源碼分析",快速找到組織.或者更簡單的,如圖:
鴻蒙內核源碼註釋倉庫 >> 精讀內核源碼,中文註解分析, 深挖地基工程,大腦永久記憶, 四大源碼倉每日同步更新 < Gitee | Github | CSDN | Coding >
鴻蒙內核源碼分析博客 >> 故事說內核,問答式導讀,生活式比喻,表格化說明,圖形化展現,主流站點每日同步更新 < CSDN | 開源中國 | WeHarmony >