進程結構 linux
進程在內核的源代碼中以結構體表示,篇幅很長,在此列舉一小段關鍵代碼,能夠發現是個雙向鏈表,具體的能夠在內核目錄下找一個叫「sched.h」的頭文件。緩存
struct task_struct { struct task_struct *real_parent; /* real parent process */ struct task_struct *parent; /* recipient of SIGCHLD, wait4() reports */ /* * children/sibling forms the list of my natural children */ struct list_head children; /* list of my children */ struct list_head sibling; /* linkage in my parent's children list */ struct task_struct *group_leader; /* threadgroup leader */ …… };
進程被存放在叫作任務鏈表(tasklist)的雙向循環鏈表中,linux經過slab分配器分配task_struct結構,這樣能達到對象複用和緩存着色(cache coloring)的目的。函數
結構體中主要由四部分組成spa
1.進程控制塊:進程標誌線程
2.進程程序塊:可與其餘程序共享code
3.進程數據塊:進程專屬空間,用於存放各類私有數據以及堆棧空間orm
4.獨立的空間:線程對象
進程狀態blog
#define TASK_RUNNING 0 #define TASK_INTERRUPTIBLE 1 #define TASK_UNINTERRUPTIBLE 2 #define __TASK_STOPPED 4 #define __TASK_TRACED 8 /* in tsk->exit_state */ #define EXIT_ZOMBIE 16 #define EXIT_DEAD 32 /* in tsk->state again */ #define TASK_DEAD 64 #define TASK_WAKEKILL 128 #define TASK_WAKING 256
進程的狀態一共有五種。隊列
進程的建立
在linux系統中,全部進程都是PID爲1的init進程的後代。內核在系統啓動的最後階段啓動init進程。該進程讀取系統的初始化腳本,並執行其餘的相關程序,最終完成系統啓動的整個進程。
進程是系統中基本的執行單位(線程是最小的調度單位),能夠利用fork函數建立一個新的進程;
pid_t fork( void )
fork() 函數不須要參數,但返回兩次,返回值有三種狀況:
(1)對於父進程,fork函數返回新的子進程的ID。
(2)對於子進程,fork函數返回0。
(3)若是出錯,fork函數返回-1。
fork函數建立一個新的進程,並從內核中爲此進程獲得一個新的可用進程ID,以後爲這個新進程分配進程空間,並將父進程的進程空間中的內容複製到子進程的進程空間中,包括父進程的數據段+堆棧段,並與父進程共享代碼段。
fork函數以後,子進程從等待fork返回開始執行,而不是從頭開始。
注意:子進程徹底複製了父進程的地址空間的內容,包括堆棧段+數據段的內容。可是,子進程並無複製代碼段,而是和父進程共享代碼段。代碼段是隻讀的,不存在修改的問題,所以能夠共用。在建立一個子進程後,子進程的地址空間徹底和父進程分開,父子進程是兩個獨立的進程。
linux環境下提供一個和fork函數相似的函數,能夠用來建立一個共用父進程地址空間的子進程。
pid_t vfork();
vfork()與fork()的區別:
(1)vfork產生的子進程和父進程徹底共享地址空間,包括代碼段+數據段+堆棧段。子進程對共享資源進行的修改,也會影響到父進程。
(2)vfork函數產生的子進程必定比父進程先運行。即父進程調用了vfork函數後會等待子進程運行後再運行。