# linux讀書筆記(3章)

linux讀書筆記(3章)

標籤(空格分隔): 20135328陳都

第三章 進程管理

3.1 進程

  • 進程就是處於執行期的程序(目標碼存放在某種存儲介質上)。但進程並不只僅侷限於一段可執行程序代碼( Unix稱其爲代碼段,text section)。一般進程還要包含其餘資源,像打開的文件,掛起的信號,內核內部數據,處理器狀態,一個或多個具備內存映射的內存地址空間及一個或多個執行線程(threa do fexecution),固然還包括用來存放全局變量的數據段等。linux

  • 程序自己並非進程,進程是處於執行期的程序以及相關的資源的總稱。實際上,徹底可能存在兩個或多個不一樣的進程執行的是同一個程序。而且兩個或兩個以上並存的進程還能夠共享許多諸如打開的文件、地址空間之類的資源。編程

  • 一般,建立新的進程都是爲了當即執行新的、不一樣的程序,而接着調用exec。這組函數就能夠建立新的地址空間,並把新的程序載入其中。數組

  • 最終,程序經過exi的系統調用退出執行。這個函數會終結進程並將其佔用的資源釋放掉。父進程能夠經過wait4()9系統調用查詢子進程是否終結,這其實使得進程擁有了等待特定進程執行完畢的能力。進程退出執行後被設置爲僵死狀態,直到它的父進程調用wait()或waitpid()爲止。併發

3.2進程描述符及任務結構

進程描述符中包含的數據能完整地描述一個正在執行的程序:它打開的文件,進程的地址空間,掛起的信號,進程的狀態,還有其餘更多信息(見下圖)
函數

3.2.1 分配避程描述符

  • 在x86 上, structtbre叫~info在文件<asm/也read_info.h>中定義以下:

每一個任務的thread_info 結構在色的內核栓的尾端分配。結構中task 域中存放的是指向該任務實際task_struct 的指針。spa

3.3進程建立

Unix 的進程建立很特別。許多其餘的操做系統都提供了產生(spawn)進程的機制,首先在新的地址空間裏建立進程,讀入可執行文件,最後開始執行。Unix 採用了不同凡響的實現方式,它把上述步驟分解到兩個單獨的函數中去執行: forkO 和exec()首先,fork()經過拷貝當前進程建立一個子進程。子進程與父進程的區別僅僅在於PID(每一個進程惟一)、PPID(父進程的進程號,子進程將其設置爲被拷貝進程的PID)和某些資源和統計量(例如,掛起的信號,它沒有必要被繼承〉。exec()函數負責讀取可執行文件並將其載入地址空間開始運行。把這兩個函數組合起來使用的效果跟其餘系統使用的單一函數的效果類似。操作系統

3.3.1 寫時拷貝

Linux 的fork()使用寫時拷貝(copy-on-write)頁實現。寫時拷貝是一種能夠推遲甚至免除拷貝數據的技術。內核此時並不複製整個進程地址空間, 而是讓父進程和子進程共享同-個拷貝.只有在須要寫入的時候,數據纔會被複制,從而使各個進程擁有各自的拷貝。也就是說,資源的複製只有在須要寫入的時候才進行,在此以前,只是以只讀方式共享。線程

3.3.2 fork()

Linux 經過clone()系統調用實現fork()。這個調用經過一系列的參數標誌來指明父、子進程須要共享的資源。
do_fork 完成了建立中的大部分工做,它的定義在kemeVfork.c 文件中。該函數調用copy_
process()函數,而後讓進程開始運行。copy_process()函數完成的工做頗有意思:設計

  1. 調用dup_task_ struct()爲新進程建立一個內核枝、也read_info結構和task_struct,這些值與當前進程的值相同。此時,子進程和父進程的描述符是徹底相同的。
  2. 檢查並確保新建立這個子進程後,當前用戶所擁有的進程數目沒有超出繪色分配的資源的限制。
  3. 子進程着手使本身與父進程區別開來。進程描述符內的許多成員都要被清0 或設爲初始值.那些不是繼承而來的進程描述符成員,主要是統計信息。task_struct 中的大多數數據都依然未被修改。
  4. 子進程的狀態被設置爲TASK_UNJNTERRUPTIBLE,以保證它不會投入運行。
  5. copy _process()調用copy_flags()以更新task_struct 的組ags 成員.代表進程是否擁有超級用戶權限的PF_SUPE盯RIV標誌被清0。代表進程尚未調用exec()函數的PF_FOR.KNOEXEC標誌被設置。
  6. 調用alloc _pid()爲新進程分配一個有效的PID。
  7. 根據傳遞給clone()的參數標誌,copy_process()拷貝或共享打開的文件、文件系統信息、信號處理函數、進程地址空間和命名空間等。在通常狀況下,這些資源會被給定進程的全部線程共享:不然,這些資源對每一個進程是不一樣的,所以被拷貝到這裏。
  8. 最後, copy_process()傲掃尾工做並返回一個指向子進程的指針。
    再回到do_fork()函數,若是copy_process()函數成功返回,新建立的子進程被喚醒並讓其投入運行。內核有意選擇子進程首先執行。.由於通常子進程都會立刻調用exec()函數,這樣能夠避免寫時拷貝的額外開銷,若是父進程首先執行的話,有可能會開始向地址空間寫入。

3.3.3 vfork()

除了不拷貝父進程的頁表項外,vfork()系統調用和fork()的功能相同。3d

3.4 線程在linux中的實現

錢程機制是現代編程技術中經常使用的一種抽象概念. 該機制提供了在同一程序內共享內存地址
空間運行的一組線程。這些線程還能夠共享打開的文件和其餘資源.線程機制支持併發程序設計技術(concurrentprogramming),在多處理器系統上,它也能保證真正的井行處理( parallelism )。Linux實現線程的機制很是獨特。從內核的角度來講,它並無線程這個概念。Linux 把所
有的錢程都當作進程來實現。

  • 傳遞給clone()的參數標誌決定了新建立進程的行爲方式和父子進程之間共辜的資源種類。下表列舉了這些clone()周到的參數標誌以及它們的做用,這些是在<linux/scbed.h>中定義的。
    -

3.4.2 內核編程

內核常常須要在後臺執行一些操做。這種任務能夠經過內核線程( kernel thread)完成————獨立運行在內核空間的標準進程。內核線程和普通的進程闊的區別在於內核線程沒有獨立的地址空間(實際上指向地址空間的mm指針被設置爲NULL ).它們只在內核空間運行,歷來不切換到用戶空間去.內核進程和普通進程同樣,能夠被調度,也能夠被搶佔.

3.5 進程終結

雖然讓人傷感,但進程終歸是要終結的(說得好像真的很傷感同樣)。當一個進程終結時,內核必須釋放它所佔有的資掠並把這一不幸告知其父進程。

3.5.2 孤兒進程形成的進退維谷

若是父進程在子進程以前退出,必須有機制來保證子進程能找到一個新的父親,不然這些成爲孤兒的進程就會在退出時永遠處於僵死狀態,白白地豔費內存。

3.6 小結

  • 在本章中,咱們考察了操做系統中的核心概念一一進程。
  • 進程是一個很是基礎、很是關鍵的抽象概念,位於每一種現代操做系統核心位置,也是咱們擁有操做系統的最終緣由。
相關文章
相關標籤/搜索