進程概念介紹
進程是操作系統(tǒng)對運行程序的一種抽象。
? 一個正在執(zhí)行的程序;
? 一個正在計算機上執(zhí)行的程序?qū)嵗?/span>
? 能分配給處理器并由處理器執(zhí)行的實體;
? 一個具有普以下特征的活動單元:一組指令序列的執(zhí)行、一個當前狀態(tài)和相關(guān)的系統(tǒng)資源集。
內(nèi)核觀點:擔當分配系統(tǒng)資源(CPU時間,內(nèi)存)的實體。進程的兩個基本元素:程序代碼(可能被執(zhí)行的其他進程共享)、數(shù)據(jù)集。進程是一種動態(tài)描述,但是并不代表所有的進程都在運行。(進程在內(nèi)存中因策略或調(diào)度需求,會處于各種狀態(tài)) 進程是處于執(zhí)行期的程序以及它所管理的資源(如打開的文件、掛起的信號、進程狀態(tài)、地址空間等等)的總稱。注意,程序并不是進程,實際上兩個或多個進程不僅有可能執(zhí)行同一程序,而且還有可能共享地址空間等資源。
進程描述
?義上,所有的進程信息被放在?個叫做進程控制塊的數(shù)據(jù)結(jié)構(gòu)中,可以理解為進程屬性的集合,該控制塊由操作系統(tǒng)創(chuàng)建和管理。
進程控制塊
進程控制塊是操作系統(tǒng)能夠支持多線程和提供多重處理技術(shù)的關(guān)鍵工具。每個進程在內(nèi)核中都有?個進程控制塊(PCB)來維護進程相關(guān)的信息,Linux內(nèi)核的 進程控制塊是task_struct結(jié)構(gòu)體?,F(xiàn)在我們?nèi)?了解?下其中都有哪些信息。 在Linux中,這個結(jié)構(gòu)叫做task_struct。task_struct是Linux內(nèi)核的?種數(shù)據(jù)結(jié)構(gòu),它會被裝載到RAM?并且包含著進程的信息。每個進程都把它的信息放在 task_struct 這個數(shù)據(jù)結(jié)構(gòu)?,并且可以在 include/linux/sched.h ?找到它。所有運?在系統(tǒng)?的進程都以 task_struct 鏈表的形式存在內(nèi)核?。task_struct 包含了這些內(nèi)容
1、進程標?符(PID):描述本進程的唯?標?符,?來區(qū)別其他進程。?進程id(PPID)
1 pid_t pid; //這個是進程號2 pid_t tgid; //這個是進程組號3 pid_t Uid; //用戶標識符4 pid_t Euid; //有效用戶標識符5 pid_t egid; //有效組標識符6 pid_t Suid; //備份用戶標識符7 pid_t sgid; //備份組標識符8 pid_t Fsuid; //文件系統(tǒng)用戶標識符9 pid_t fsgid; //文件系統(tǒng)組標識符
在CONFIG_BASE_SMALL配置為0的情況下,PID的取值范圍是0到32767,即系統(tǒng)中的進程數(shù)最大為32768個。
1 /* linux-2.6.38.8/include/linux/threads.h */ 2 #define PID_MAX_DEFAULT (CONFIG_BASE_SMALL ? 0x1000 :0x8000)
在Linux系統(tǒng)中,一個線程組中的所有線程使用和該線程組的領(lǐng)頭線程(該組中的第一個輕量級進程)相同的PID,并被存放在tgid成員中。只有線程組的領(lǐng)頭線程的pid成員才會被設置為與tgid相同的值。注意,getpid()系統(tǒng)調(diào)用返回的是當前進程的tgid值而不是pid值。
2、進程狀態(tài) : 任務狀態(tài),退出代碼,退出信號等。
1 volatile long state; 2 int exit_state; 4 /*state成員的可能取值如下:*/ 5 #define TASK_RUNNING 0 //TASK_RUNNING表示進程要么正在執(zhí)行,要么正要準備執(zhí)行。 6 #define TASK_INTERRUPTIBLE 1 //TASK_INTERRUPTIBLE表示進程被阻塞(睡眠),直到某個條件變?yōu)檎?。條件一旦達成,進程的狀態(tài)就被設置為TASK_RUNNING。 7 #define TASK_UNINTERRUPTIBLE 2 //TASK_UNINTERRUPTIBLE的意義與TASK_INTERRUPTIBLE類似,除了不能通過接受一個信號來喚醒以外。 8 #define __TASK_STOPPED 4 // __TASK_STOPPED表示進程被停止執(zhí)行。 9 #define __TASK_TRACED 8 //__TASK_TRACED表示進程被debugger等進程監(jiān)視。10 /* in tsk->exit_state */ 11 #define EXIT_ZOMBIE 16 //EXIT_ZOMBIE表示進程的執(zhí)行被終止,但是其父進程還沒有使用wait()等系統(tǒng)調(diào)用來獲知它的終止信息。12 #define EXIT_DEAD 32 EXIT_DEAD表示進程的最終狀態(tài)。13 /* in tsk->state again */ 14 #define TASK_DEAD 64 15 #define TASK_WAKEKILL 128 16 #define TASK_WAKING 256 17 /*EXIT_ZOMBIE和EXIT_DEAD也可以存放在exit_state成員中。*/
volatile這個關(guān)鍵詞是告訴編譯器不要對其優(yōu)化,編譯器有一個緩存優(yōu)化的習慣,比如說,第一次在內(nèi)存取數(shù),編譯器發(fā)現(xiàn)后面還要用這個變量,于是把這個變量的值就放在寄存器中。這個關(guān)鍵詞就是要求編譯器不要優(yōu)化,每次都讓CPU去內(nèi)存取數(shù)。以確保狀態(tài)的變化能及時地反映上來。
3、進程調(diào)度(優(yōu)先級 : 相對于其他進程的優(yōu)先級。)
unsigned rt_priority; sched_class *sched_class; unsigned policy; cpumask_t cpus_allowed; SCHED_NORMAL 0 SCHED_FIFO 1 SCHED_RR 2 SCHED_BATCH 3 SCHED_IDLE 5 sched_class stop_sched_class;
實時優(yōu)先級范圍是0到MAX_RT_PRIO-1(即99),而普通進程的靜態(tài)優(yōu)先級范圍是從MAX_RT_PRIO到MAX_PRIO-1(即100到139)。值越大靜態(tài)優(yōu)先級越低。
4、表示進程親屬關(guān)系的成員
在Linux系統(tǒng)中,所有進程之間都有著直接或間接地聯(lián)系,每個進程都有其父進程,也可能有零個或多個子進程。擁有同一父進程的所有進程具有兄弟關(guān)系。
1 struct task_struct *real_parent; /* real parent process ,real_parent指向其父進程,如果創(chuàng)建它的父進程不再存在,則指向PID為1的init進程。 */ 2 struct task_struct *parent; /* recipient of SIGCHLD, wait4() reports, parent指向其父進程,當它終止時,必須向它的父進程發(fā)送信號。它的值通常與real_parent相同。 */ 3 struct list_head children; /* list of my children, children表示鏈表的頭部,鏈表中的所有元素都是它的子進程。 */ 4 struct list_head sibling; /* linkage in my parent's children list, sibling用于把當前進程插入到兄弟鏈表中。 */ 5 struct task_struct *group_leader; /* threadgroup leader ,group_leader指向其所在進程組的領(lǐng)頭進程。*/
可以用下面這些通俗的關(guān)系來理解它們:real_parent是該進程的”親生父親“,不管其是否被“寄養(yǎng)”;parent是該進程現(xiàn)在的父進程,有可能是”繼父“;這里children指的是該進程孩子的鏈表,可以得到所有孩子的進程描述符,但是需使用list_for_each和list_entry,list_entry其實直接使用了container_of,同理,sibling該進程兄弟的鏈表,也就是其父親的所有孩子的鏈表。用法與children相似;struct task_struct *group_leader這個是主線程的進程描述符,也許你會奇怪,為什么線程用進程描述符表示,因為linux并沒有單獨實現(xiàn)線程的相關(guān)結(jié)構(gòu)體,只是用一個進程來代替線程,然后對其做一些特殊的處理;struct list_head thread_group;這個是該進程所有線程的鏈表。
5、進程標記
反應進程狀態(tài)的信息,但不是運行狀態(tài),用于內(nèi)核識別進程當前的狀態(tài),以備下一步操作
1 unsigned int flags; /* per process flags, defined below */ 2 // flags成員的可能取值如下: 3 #define PF_KSOFTIRQD 0x00000001 /* I am ksoftirqd */ 4 #define PF_STARTING 0x00000002 /* being created */ 5 #define PF_EXITING 0x00000004 /* getting shut down */ 6 #define PF_EXITPIDONE 0x00000008 /* pi exit done on shut down */ 7 #define PF_VCPU 0x00000010 /* I'm a virtual CPU */ 8 #define PF_WQ_WORKER 0x00000020 /* I'm a workqueue worker */ 9 #define PF_FORKNOEXEC 0x00000040 /* forked but didn't exec */ 10 #define PF_MCE_PROCESS 0x00000080 /* process policy on mce errors */ 11 #define PF_SUPERPRIV 0x00000100 /* used super-user privileges */ 12 #define PF_DUMPCORE 0x00000200 /* dumped core */ 13 #define PF_SIGNALED 0x00000400 /* killed by a signal */ 14 #define PF_MEMALLOC 0x00000800 /* Allocating memory */ 15 #define PF_USED_MATH 0x00002000 /* if unset the fpu must be initialized before use */ 16 #define PF_FREEZING 0x00004000 /* freeze in progress. do not account to load */ 17 #define PF_NOFREEZE 0x00008000 /* this thread should not be frozen */ 18 #define PF_FROZEN 0x00010000 /* frozen for system suspend */ 19 #define PF_FSTRANS 0x00020000 /* inside a filesystem transaction */ 20 #define PF_KSWAPD 0x00040000 /* I am kswapd */ 21 #define PF_OOM_ORIGIN 0x00080000 /* Allocating much memory to others */ 22 #define PF_LESS_THROTTLE 0x00100000 /* Throttle me less: I clean memory */ 23 #define PF_KTHREAD 0x00200000 /* I am a kernel thread */ 24 #define PF_RANDOMIZE 0x00400000 /* randomize virtual address space */ 25 #define PF_SWAPWRITE 0x00800000 /* Allowed to write to swap */ 26 #define PF_SPREAD_PAGE 0x01000000 /* Spread page cache over cpuset */ 27 #define PF_SPREAD_SLAB 0x02000000 /* Spread some slab caches over cpuset */ 28 #define PF_THREAD_BOUND 0x04000000 /* Thread bound to specific cpu */ 29 #define PF_MCE_EARLY 0x08000000 /* Early kill for mce process policy */ 30 #define PF_MEMPOLICY 0x10000000 /* Non-default NUMA mempolicy */ 31 #define PF_MUTEX_TESTER 0x20000000 /* Thread belongs to the rt mutex tester */ 32 #define PF_FREEZER_SKIP 0x40000000 /* Freezer should not count it as freezable */ 33 #define PF_FREEZER_NOSIG 0x80000000 /* Freezer won't send signals to it */
6、進程內(nèi)核棧
進程通過alloc_thread_info函數(shù)分配它的內(nèi)核棧,通過free_thread_info函數(shù)釋放所分配的內(nèi)核棧。
1 void *stack; 2 // 3 /* linux-2.6.38.8/kernel/fork.c */ 4 static inline struct thread_info *alloc_thread_info(struct task_struct *tsk) 5 { 6 #ifdef CONFIG_DEBUG_STACK_USAGE 7 gfp_t mask = GFP_KERNEL | __GFP_ZERO; 8 #else 9 gfp_t mask = GFP_KERNEL; 10 #endif 11 return (struct thread_info *)__get_free_pages(mask, THREAD_SIZE_ORDER); 12 } 13 static inline void free_thread_info(struct thread_info *ti) 14 { 15 free_pages((unsigned long)ti, THREAD_SIZE_ORDER); 16 } 17 /*其中,THREAD_SIZE_ORDER宏在linux-2.6.38.8/arch/arm/include/asm/thread_info.h文件中被定義為1,也就是說alloc_thread_info函數(shù)通過調(diào)用__get_free_pages函數(shù)分配2個頁的內(nèi)存(它的首地址是8192字節(jié)對齊的)。18 19 Linux內(nèi)核通過thread_union聯(lián)合體來表示進程的內(nèi)核棧,其中THREAD_SIZE宏的大小為8192。 */20 union thread_union { 21 struct thread_info thread_info; 22 unsigned long stack[THREAD_SIZE/sizeof(long)]; 23 }; 24 /*當進程從用戶態(tài)切換到內(nèi)核態(tài)時,進程的內(nèi)核棧總是空的,所以ARM的sp寄存器指向這個棧的頂端。因此,內(nèi)核能夠輕易地通過sp寄存器獲得當前正在CPU上運行的進程。*/25 /* linux-2.6.38.8/arch/arm/include/asm/current.h */ 26 static inline struct task_struct *get_current(void) 27 { 28 return current_thread_info()->task; 29 } 30 31 #define current (get_current()) 32 33 /* linux-2.6.38.8/arch/arm/include/asm/thread_info.h */ 34 static inline struct thread_info *current_thread_info(void) 35 { 36 register unsigned long sp asm ("sp"); 37 return (struct thread_info *)(sp & ~(THREAD_SIZE - 1)); 38 }
下圖中顯示了在物理內(nèi)存中存放兩種數(shù)據(jù)結(jié)構(gòu)的方式。線程描述符駐留與這個內(nèi)存區(qū)的開始,而棧頂末端向下增長。在這個圖中,esp寄存器是CPU棧指針,用來存放棧頂單元的地址。在80x86系統(tǒng)中,棧起始于頂端,并朝著這個內(nèi)存區(qū)開始的方向增長。從用戶態(tài)剛切換到內(nèi)核態(tài)以后,進程的內(nèi)核??偸强盏?。因此,esp寄存器指向這個棧的頂端。一旦數(shù)據(jù)寫入堆棧,esp的值就遞減。
7、ptrace系統(tǒng)調(diào)用
1 unsigned int ptrace; 2 struct list_head ptraced; 3 struct list_head ptrace_entry; 4 unsigned long ptrace_message; 5 siginfo_t *last_siginfo; /* For ptrace use. */ 6 ifdef CONFIG_HAVE_HW_BREAKPOINT 7 atomic_t ptrace_bp_refcnt; 8 endif 9 /*成員ptrace被設置為0時表示不需要被跟蹤,它的可能取值如下:*/10 /* linux-2.6.38.8/include/linux/ptrace.h */ 11 #define PT_PTRACED 0x00000001 12 #define PT_DTRACE 0x00000002 /* delayed trace (used on m68k, i386) */ 13 #define PT_TRACESYSGOOD 0x00000004 14 #define PT_PTRACE_CAP 0x00000008 /* ptracer can follow suid-exec */ 15 #define PT_TRACE_FORK 0x00000010 16 #define PT_TRACE_VFORK 0x00000020 17 #define PT_TRACE_CLONE 0x00000040 18 #define PT_TRACE_EXEC 0x00000080 19 #define PT_TRACE_VFORK_DONE 0x00000100 20 #define PT_TRACE_EXIT 0x00000200
8、Performance Event
http://www.cnblogs.com/33debug/p/6705391.html