1、進程的定義html
進程是操做系統的概念,每當咱們執行一個程序時,對於操做系統來說就建立了一個進程,在這個過程當中,伴隨着資源的分配和釋放。能夠認爲進程是一個程序的一次執行過程。
2、進程與程序的區別
程序時靜態的,它是一些保存 在磁盤上得指令的有序集合,沒有任何執行的概念。
進程是一個動態的概念,它是程序執行的過程,包括建立、調度和消亡。
3、linux系統中進程的表示
在linux系統中,進程由一個叫task_struct的結構體描述,也就是說linux中的每一個進程對應一個task_struct結構體。該結構體記錄了進程的一切。下面咱們來看看它的核心字段。
struct task_struct
{
//這個是進程的運行狀態,-1表明不可運行,0表明可運行,>0表明已經中止。
volatile long state;
/*
flags是進程當前的狀態標誌,具體以下:
0x0000 0002表示進程正在被建立
0x0000 0004表示進程正準備退出
0x0000 0040表示此進程被fork出,可是並無執行exec
0x0000 0400表示此進程因爲其餘進程發送相關信號而被殺死
*/
unsigned int flags;
//表示此進程的運行優先級
unsigned int rt_priority;
//該結構體記錄了進程內存使用的相關狀況
struct mm_struct *mm;
//進程號,是進程的惟一標識
pid_t pid;
//進程組號
pid_t tgid;
//real_parent是該進程的"親生父親",無論其是否被"寄養"
struct task_struct *real_parent;
//parent是該進程如今的父進程,有多是"繼父"
struct task_struct *parent;
//這裏children指的是該進程孩子的鏈表,能夠獲得全部孩子的進程描述符
struct list_head children;
//同理,sibling該進程兄弟的鏈表,也就是其父進程的全部孩子的鏈表
struct list_head sibling;
//這個是主線程的進程描述符,也許你會奇怪,爲何線程用進程描敘符表示,由於linux並無單獨實現線程的相關結構體,只用一 個進程來代替線程,而後對其作一些特殊的處理。
struct task_struct *group_leader;
//這個是該進程全部線程的鏈表
struct list_head thread_group;
//這個是該進程使用cpu時間的信息,utime是在用戶態下執行的時間,stime 是在內核態下執行的時間
cputime_t utime,stime;
//comm是保存該進程名字的字符數組,長度最長爲15,由於TASK_COMM_LEN爲16
char comm[TASK_COMM_LEN];
//打開的文件相關信息結構體
struct files_struct *files;
//信號相關信息的句柄
struct signal_struct *signal;
struct sigband_struct *sighand;
};
task_struct結構體很是龐大,咱們不必去了解它的全部字段,只須要對其中比較重要的字段加以關注就能夠了。從上面的分析能夠看出,一個進程至少有一下東東
1. 進程號(pid),就像咱們的身份證ID同樣,每一個人的都不同。進程ID也是,是其惟一標示。
2.進程的狀態,標識進程是處於運行態,等待態,中止態,仍是死亡態
A.運行態:此時進程 或者正在運行,或者準備運行
B.等待態:此時進程在等待一個事件發生或某種系統資源
C.中止態:此時進程被終止
D.死亡態:這是一個已終止的進程,但還在進程向量數組中,佔有一個task_struct結構。
3.進程的優先級和時間片。不一樣有優先的進程,被調度運行的次序不同,通常是高優先級的進程先運行。時間片標識一個進程將被處理器運行的時間
4.虛擬內存 大多數進程有一些虛擬內存(內核線程和守護進程沒有) ,而且Linux必須跟蹤內存如何映射到系統物理內存。
5.處理器相關上下文 一個進程能夠被認爲是系統當前狀態的總和。每當一個進程運行時,它要使用處理器的寄存器、棧等,這是進程的上下文(context)。而且,每當一個進程被暫停時,全部的CPU相關上下文必須保存在該進程的task_struct中。當進程被調度器從新啓動時其上下文將從這裏恢復。
4、linux進程中的文件
linux操做系統中每一個進程有兩個數據結構描敘文件相關信息。
第一個:fs_struct,它包含此進程當前工做目錄和根目錄、umask。umask是新文件被 建立的缺省模式,它能夠經過系統調用來改變。
第二個:files_struct,包含此進程正在使用的全部文件的信息。f_mode字段描述該文件是以什麼模式建立的:只讀、讀寫、仍是隻寫。f_pos保存文件中下一個讀或寫將發生的位置。f_inode描敘文件的VFS索引節點,而f_ops是一個例程向量的指針,每一個表明一個想施加於文件的操做的函數。
每次一個文件被打開時,files_struct中的空閒file指針之一就被用來指向新的file結構。Linux進程在啓動時有三個文件描敘符被打開了,他們是標準輸入設備、標準輸出設備和標準錯誤設備,而且一般是從建立此進程的父進程繼承得來的。全部對文件的訪問時經過傳遞或返回文件描敘符的標準系統調用進行的。這些描述符是進程fd向量的索引,因此標準輸入設備、標準輸出設備和標準錯誤設備分別對應文件描述符0、1和2。
5、進程中的虛擬內存
在Linux操做系統中,當咱們運行一個二級制可執行文件時,操做系統將建立一個進程。此時若是將這個可執行二進制文件的所有代碼和數據裝入物理內存將是浪費的。由於他們不可能同時使用。隨着系統中進程數的增多,這種浪費將被成倍的擴大,系統將很是低效地運行。事實上,linux使用一種稱爲請求調頁(demand-paging)的技術:只有當進程要使用時其虛擬內存時,其對應的數據才裝入物理內存。因此,不是直接把代碼和數據裝入物理內存。linux內核只修改進程的頁表,標識虛擬內存頁存在但其對應的數據不在內存中。當進程想要訪問代碼或數據時,系統硬件將產生頁故障並把控制交給Linux內核來解決。所以,對於進程地址空間中的每個內存區,Linux都須要知道該虛擬內存來自何處,以及如何把它裝入內存以解決故障。
當一個進程分配虛擬內存時,Linux並不真正爲它保留物理內存。它只是建立一個新vm_area_struct數據結構來描敘虛擬內存,這個結構被鏈入進程的虛擬內存列表。當進程試圖寫一個位於新分配虛擬內存區域的虛擬地址時,系統將產生頁故障。處理器試圖轉換該虛擬地址,可是由於沒有此內存的頁表項,它將放棄併產生一個頁故障異常,留給Linux內核來解決。Linux查看被引用的虛擬地址是不是位於當前進程的虛擬內存地址空間。若是是Linux建立適當的PTE併爲此進程分配一頁物理內存。代碼或數據可能須要從文件系統或交換硬盤上讀入物理內存。而後進程能夠從引發頁故障的那條指令處重啓,而且由於此次內存物理地址存在,因此它能夠繼續執行。若是不是,就是你們經常見到的"段錯誤"。
呵呵,更纖細的介紹請看linux 進程地址空間的一步步探究。
from:http://blog.chinaunix.net/uid-26833883-id-3193588.html