進程基本概念理解

1、進程和程序
linux

1.進程的基本概念緩存

  所謂進程是由正文段用戶數據段以及系統數據段共同組成的一個執行環境,是一個動態實體。網絡

2.程序的基本概念數據結構

  程序只是一個普通文件,是一個機器代碼指令和數據的集合,這些指令和數據存儲在磁盤上的一個可執行映像中,因此,程序是一個靜態的實體。ide

wKiom1na8_WAsle4AAAnwz3_ZWo119.png

3.進程的組成部分函數

(1)正文段:存放被執行的機器指令。這個段是隻讀的(因此,在這裏不能寫本身能修改的代碼),它容許系統中正在運行的兩個或多個進程之間可以共享這一代碼。spa

(2)用戶數據段:存放進程在執行時直接進行操做的全部數據,包括進程使用的所有變量在內。顯然,這裏包含的信息能夠被改變。雖然進程之間能夠共享正文段,可是每一個進程須要有它本身的專用用戶數據段。操作系統

(3)系統數據段:該段有效地存放程序運行的環境。事實上,這正是程序和進程的區別所在。做爲動態事物,進程是正文段、用戶數據段和系統數據段的信息的交叉綜合體,其中系統數據段是進程實體最重要的一部分,之因此說它有效地存放程序運行的環境,是由於這一部分存放有進程的控制信息。Linux爲每一個進程創建了task_struct數據結構來容納這些控制信息。.net

4.進程和程序總結線程

  程序裝入內存後就能夠運行了:在指令指針寄存器的控制下,不斷地將指令取至CPU運行。這些指令控制的對象不外乎各類存儲器(內存、外存和各類CPU寄存器等),這些存儲器中保存有待運行的指令和待處理的數據,固然,指令只有到CPU才能發揮其做用。

  Linux是一個多任務操做系統,也就是說,能夠有多個程序同時裝入內存並運行,操做系統爲每一個程序創建一個運行環境即建立進程,每一個進程擁有本身的虛擬地址空間,它們之間互不干擾,即便要相互做用(例如多個進程合做完成某個工做),也要經過內核提供的進程間通訊機制(IPC)

2、task_struct結構描述

1.Linux中的每一個進程由一個task_struct數據結構來描述,task_struct其實就是一般所說的「進程控制塊」即PCB。task_struct容納了一個進程的全部信息,是系統對進程進行控制的惟一手段,也是最有效的手段。

2.task_struct數據結構全部域以下:

*進程狀態(State);

wKioL1nbES7DwaJOAABabyaaZfc304.png

  僵死狀態:進程雖然已經終止,但因爲某種緣由,父進程尚未執行wait()系統調用,終止進程的
信息也尚未回收。

*進程調度信息(Scheduling Information);


wKiom1nbEvPhmHuKAAA9hO7T7DI798.png

wKiom1nbEvPQVkBZAABE300oFQM152.png

調度策略

只有root用戶能經過sched_setscheduler()系統調用來改變調度策略。

*各類標識符(Identifiers);

wKioL1nbE2XBBQ1oAABRJjD_MnU439.png

*進程通訊有關信息(IPC,Inter_Process Communication);

  Linux 支持多種不一樣形式的通訊機制。它支持典型的UNIX通訊機制(IPC Mechanisms):信號、管道,也支持System V通訊機制:共享內存、信號量和消息隊列。

wKioL1nbFT_CiW2lAABw2l4C30A197.png

*時間和定時器信息(Times and Timers);

  一個進程從建立到終止叫作該進程的生存期(lifetime)。進程在其生存期內使用 CPU的時間,內核都要進行記錄,以便進行統計、計費等有關操做。進程耗費CPU的時間由兩部分組成:一是在用戶模式(或稱爲用戶態)下耗費的時間、一是在系統模式(或稱爲系統態)下耗費的時間。每一個時鐘滴答,也就是每一個時鐘中斷,內核都要更新當前進程耗費CPU的時間信息。

wKiom1nbF6LhiPRBAABhIvQu0sY077.png

 創建了「時間」的概念,「定時」就是垂手可得的了,無非是判斷系統時間是否到達某個時刻,而後執行相關的操做而已。Linux提供了許多種定時方式,用戶能夠靈活使用這些方式來爲本身的程序定時。

wKioL1nbF2aidamQAACdN24aPus521.png

*進程連接信息(Links);

  程序建立的進程具備父/子關係。由於一個進程能建立幾個子進程,而子進程之間有兄弟關係,在 task_struct結構中有幾個域來表示這種關係。

  在Linux系統中,除了初始化進程init,其餘進程都有一個父進程或稱爲雙親進程。 能夠經過 fork()或 clone()系統調用來建立子進程, 除了進程標識符(PID)等要的信息外,子進程的task_struct結構中的絕大部分的信息都是從父進程中拷貝,或說「克隆」過來的。系統有必要記錄這種「親屬」關係,使進程之間的協做更加方便,例如父進程給子進程發送殺死(kill)信號、父子進程通訊等,就能夠用這種關係很方便地實現。

wKioL1nbFQChCoaeAACSUEmFqeo609.png

*文件系統信息(File System);

  進程能夠打開或關閉文件,文件屬於系統資源,Linux內核要對進程使用文件的狀況進行記錄。task_struct結構中有兩個數據結構用於描述進程與文件相關的信息。其中,fs_struct中描述了兩個 VFS索引節點,這兩個索引節點叫作root和pwd,分別指向進程的可執行映像所對應的根目錄和當前目錄或工做目錄。file_struct結構用來記錄了進程打開的文件的描述符。

  在文件系統中,每一個VFS索引節點惟一描述一個文件或目錄,同時該節點也是向更低層的文件系統提供的統一的接口。 

wKioL1nbGlmwUThNAAA0Rqw-1Mw994.png

*虛擬內存信息(Virtual Memory);
*頁面管理信息(page);
*對稱多處理器(SMP)信息;
*和處理器相關的環境(上下文)信息(Processor Specific Context);

*其餘信息。

3、task_struct 結構在內存中的存放

內核棧:每一個進程都有本身的內核棧。當進程從用戶態進入內核態時,CPU就自動地設置該進程的內核棧。

wKiom1nbH8_CJaedAAAroLYyKeQ094.png

 從這個結構能夠看出,內核棧佔8KB 的內存區。實際上,進程的task_struct結構所佔的內存是由內核動態分配的,更確切地說,內核根本不給task_struct分配內存,而僅僅給內核棧分配8KB的內存,並把其中的一部分給task_struct使用。

  task_struct結構大約佔1K字節左右,其具體數字與內核版本有關,由於不一樣的版本其域稍有不一樣。所以,內核棧的大小不能超過7KB,不然,內核棧會覆蓋task_struct結構,從而致使內核崩潰。不過,7KB大小對內核棧已足夠。

  把task_struct結構與內核棧放在一塊兒具備如下好處:
*內核能夠方便而快速地找到這個結構,用僞代碼描述以下:
  task_struct = (struct task_struct *) STACK_POINTER & 0xffffe000(8K)
*避免在建立進程時動態分配額外的內存。
*task_struct 結構的起始地址老是開始於頁大小(PAGE_SIZE)的邊界。

4、進程的組織方式

1.哈希表

 哈希表是進行快速查找的一種有效的組織方式。Linux在進程中引入的哈希表叫作pidhash,在include/linux/sched.h 中定義。

2.雙向循環鏈表

  哈希表的主要做用是根據進程的pid能夠快速地找到對應的進程,但它沒有反映進程建立的順序,也沒法反映進程之間的親屬關係,所以引入雙向循環鏈表。每一個進程task_struct結構中的prev_task和next_task域用來實現這種鏈表。

3.運行隊列

  當內核要尋找一個新的進程在CPU上運行時,必須只考慮處於可運行狀態的進程(即在TASK_RUNNING 狀態的進程) ,由於掃描整個進程鏈表是至關低效的,因此引入了可運行狀態進程的雙向循環鏈表,也叫運行隊列(runqueue)。

4.進程的運行隊列鏈表

 該隊列經過task_struct結構中的兩個指針run_list鏈表來維持。隊列的標誌有兩個:一個是「空進程」idle_task,一個是隊列的長度。

  空進程是個比較特殊的進程,只有系統中沒有進程可運行時它纔會被執行,Linux將它看做運行隊列的頭,當調度程序遍歷運行隊列,是從idle_task開始、至idle_task結束的,在調度程序運行過程當中,容許隊列中加入新出現的可運行進程,新出現的可運行進程插入到隊尾,這樣的好處是不會影響到調度程序所要遍歷的隊列成員,可見,idle_task是運行隊列很重要的標誌。另外一個重要標誌是隊列長度,也就是系統中處於可運行狀態(TASK_RUNNING)的進程數目,用全局整型變量nr_running表示,在/kernel/fork.c 中定義。

5.等待隊列

  顧名思義,就是等待執行的進程所組成的隊列。等待隊列在內核中有不少用途,尤爲對中斷處理、進程同步及定時用處更大。

5、內核線程

  內核線程或叫守護進程,在操做系統中佔據至關大的比例,你能夠用「ps」命令查看系統中的進程,這時會發現不少以「d」結尾的進程名,這些進程就是內核線程。內核線程是由kernel_thread ( )函數在內核態下建立。

  內核線程也能夠叫內核任務,它們週期性地執行,例如,磁盤高速緩存的刷新,網絡鏈接的維護,頁面的換入換出等。在Linux中,內核線程與普通進程有一些本質的區別,從如下幾個方面能夠看出兩者之間的差別。
*內核線程執行的是內核中的函數,而普通進程只有經過系統調用才能執行內核中的函數。
*內核線程只運行在內核態,而普通進程既能夠運行在用戶態,也能夠運行在內核態。
*由於內核線程指只運行在內核態,所以,它只能使用大於PAGE_OFFSET(3G)的地址空間。另外一方面,無論在用戶態仍是內核態,普通進程可使用4GB的地址空間。

  因爲kernel_thread包含大部分彙編代碼,大體和下面代碼等價:

int kernel_thread(int(*fn)(void *),void * arg,unsigned long flags)
{
    pid_t p ;
    p = clone(0, flags | CLONE_VM);
    if(p) /* parent */
    return p;
    else{ /* child */
    fn(arg) ;
    exit( ) ;
    }
}

6、進程的權能

  Linux 用「權能(capability)」表示一進程所具備的權力。一種權能僅僅是一個標誌,它代表是否容許進程執行一個特定的操做或一組特定的操做。這個模型不一樣於傳統的「超級用戶對普通戶」模型,在後一種模型中,一個進程要麼能作任何事情,要麼什麼也不能作,這取決於它的有效 UID。

  任什麼時候候,每一個進程只須要有限種權能,這是其主要優點。所以,即便一位有惡意的用戶使用有潛在錯誤程序,他也只能非法地執行有限個操做類型。

  具體權能列表在博客:http://blog.csdn.net/tq08g2z/article/details/77311787?locationNum=3&fps=1

相關文章
相關標籤/搜索