歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux綜合 >> Linux內核 >> Linux內核——進程管理與調度

Linux內核——進程管理與調度

日期:2017/3/1 9:40:58   编辑:Linux內核

進程的管理與調度

進程管理

進程描述符及任務結構

進程存放在叫做任務隊列(tasklist)的雙向循環鏈表中。鏈表中的每一項包含一個具體進程的所有信息,類型為task_struct,稱為進程描述符(process descriptor),該結構定義在<linux/sched.h>文件中。

Linux通過slab分配器分配task_struct結構,這樣能達到對象復用和緩存著色(cache coloring)的目的。另一方面,為了避免使用額外的寄存器存儲專門記錄,讓像x86這樣寄存器較少的硬件體系結構只要通過棧指針就能計算出task_struct的位置,該結構為thread_info,在文件<asm/thread_info.h>中定義。

Linux中可以用ps命令查看所有進程的信息。

Linux基礎篇之內存管理機制 http://www.linuxidc.com/Linux/2014-03/98293.htm

Linux內存管理之高端內存 http://www.linuxidc.com/Linux/2013-06/85693.htm

Linux內存管理之分段機制 http://www.linuxidc.com/Linux/2012-11/74480.htm

Linux內存管理伙伴算法 http://www.linuxidc.com/Linux/2012-09/70711.htm

進程狀態

task_struct中的state描述進程的當前狀態。進程的狀態一共有5種,而進程必然處於其中一種狀態:

1)TASK_RUNNING(運行)——進程是可執行的,它或者正在執行,或者在運行隊列中等待執行。這是進程在用戶空間中執行唯一可能的狀態;也可以應用到內核空間中正在執行的進程。

2)TASK_INTERRUPTIBLE(可中斷)——進程正在睡眠(也就是說它被阻塞)等待某些條件的達成。一旦這些條件達成,內核就會把進程狀態設置為運行,處於此狀態的進程也會因為接收到信號而提前被喚醒並投入運行。

3)TASK_UNINTERRUPTIBLE(不可中斷)——除了不會因為接收到信號而被喚醒從而投入運行外,這個狀態與可打斷狀態相同。這個狀態通常在進程必須在等待時不受干擾或等待事件很快就會發生時出現。由於處於此狀態的任務對信號不作響應,所以較之可中斷狀態,使用得較少。

4)TASK_ZOMBIE(僵死)——該進程已經結束了,但是其父進程還沒有調用wait4()系統調用。為了父進程能夠獲知它的消息,子進程的進程描述符仍然被保留著。一旦父進程調用了wait4(),進程描述符就會被釋放。

5)TASK_STOPPED(停止)——進程停止執行,進程沒有投入運行也不能投入運行。通常這種狀態發生在接收到SIGSTOP,SIGTSTP,SIGTTIN,SIGTTOU等信號的時候。此外,在調試期間接收到任何信號,都會使進程進入這種狀態。

需要調整進程的狀態,最好使用set_task_state(task, state)函數,在必要的時候,它會設置內存屏障來強制其他處理器作重新排序(SMP)。

進程的各個狀態之間的轉化構成了進程的整個生命周期,

進程的創建

在Linux系統中,所有的進程都是PID為1的init進程的後代。內核在系統啟動的最後階段啟動init進程。該進程讀取系統的初始化腳本(initscript)並執行其他的相關程序,最終完成系統啟動的整個進程。

Linux提供兩個函數去處理進程的創建和執行:fork()和exec()。首先,fork()通過拷貝當前進程創建一個子進程。子進程與父進程的區別僅僅在於PID(每個進程唯一),PPID(父進程的PID)和某些資源和統計量(例如掛起的信號)。exec()函數負責讀取可執行文件並將其載入地址空間開始運行。

fork()使用寫時拷貝(copy-on-write)頁實現。內核在fork進程時不復制整個進程地址空間,讓父進程和子進程共享同一個拷貝,當需要寫入時,數據才會被復制,使各進程擁有自己的拷貝。在頁根本不會被寫入的情況下(fork()後立即exec()),fork的實際開銷只有復制父進程的頁表以及給子進程創建唯一的task_struct。

創建進程的fork()函數實際上最終是調用clone()函數。創建線程和進程的步驟一樣,只是最終傳給clone()函數的參數不同。比如,通過一個普通的fork來創建進程,相當於:clone(SIGCHLD, 0);創建一個和父進程共享地址空間,文件系統資源,文件描述符和信號處理程序的進程,即一個線程:clone(CLONE_VM | CLONE_FS | CLONE_FILES |CLONE_SIGHAND, 0)。

在內核中創建的內核線程與普通的進程之間還有個主要區別在於:內核線程沒有獨立的地址空間,它們只能在內核空間運行。

fork和vfork的區別

fork()與vfock()都是創建一個進程,那他們有什麼區別呢?總結有以下三點區別:
1. fork ():子進程拷貝父進程的數據段,代碼段
vfork ( ):子進程與父進程共享數據段
2. fork ()父子進程的執行次序不確定
vfork 保證子進程先運行,在調用exec 或exit 之前與父進程數據是共享的,在它調用exec
或exit 之後父進程才可能被調度運行。
3. vfork ()保證子進程先運行,在她調用exec 或exit 之後父進程才可能被調度運行。如果在
調用這兩個函數之前子進程依賴於父進程的進一步動作,則會導致死鎖。

更多詳情見請繼續閱讀下一頁的精彩內容: http://www.linuxidc.com/Linux/2014-08/105366p2.htm

Copyright © Linux教程網 All Rights Reserved