【正文】
es the current condition of the process. Each process on the system is in exactly one of five different states. This value is represented by one of five flags:(1) TASK_RUNNING The process is runnable。 it can also apply to a process in kernelspace that is actively running.(2) TASK_INTERRUPTIBLE. The process is sleeping (that is, it is blocked), waiting for some condition to exist. When this condition exists, the kernel sets the process39。s process descriptor must remain in case the parent wants to access it. If the parent calls wait4(), the process descriptor is deallocated.(5) TASK_STOPPED Process execution has stopped。s state. The preferred mechanism is using set_task_state(task, state)。 The method set_current_state(state) is synonymous to set_task_state(current, state).6 Process ContextOne of the most important parts of a process is the executing program code. This code is read in from an executable file and executed within the program39。一個進程就是處于執(zhí)行期間的程序(目標代碼放在某種存儲介質上)。通常進程還要包含其他資源,像打開的文件、掛起的信號、內核內部數據、處理器狀態(tài)、地址空間及一個或多個執(zhí)行線程、當然還包括用來存放全局變量的數據段等。 執(zhí)行線程,簡稱線程(thread),是在進程中活動的對象。內核調度的對象是線程,而不是進程。Linux系統的線程實現非常特別—他對線程和進程并不特別區(qū)分。 在現代操作系統中,進程提供兩種虛擬機制:虛擬處理器和虛擬內存。而虛擬內存讓進程在獲取和使用內存是覺得自己擁有整個操作系統的所有內存資源。 程序本身并不是進程:進程是處于執(zhí)行期間的程序以及它所包含的資源的總稱。并且兩個或兩個以上并存的進程還可以共享許多諸如打開的文件、地址空間之類的資源。在Linux系統中,這通常是調用fork()系統調用的結果,該系統調用通過復制一個現有進程來創(chuàng)建一個全新的進程。在調用結束的時,在返回這個相同位置上,父進程恢復執(zhí)行,子進程開始執(zhí)行。 通常,創(chuàng)建新的進程都是為了立即執(zhí)行新的、不同的程序,而接著調用exec()這族函數就可以創(chuàng)建新的地址空間,并把新的程序載入。 最終,程序通過exit()系統調用退出。父進程可以通過wait()系統調用查詢子進程是否終結,這其實使得進程擁有了等待指定進程執(zhí)行完畢的能力。 進程的另一個名字是任務(task)。在這里所說的任務是指從內核觀點看到的進程。鏈表的每一項都是類型為task_struct、稱為進程描述符的結構,改結構定義在linux/文件中。task_struct相對較大,在32位機器上。進程描述符中包含的數據能完整的描述一個正在執(zhí)行的程序:它打開的文件,進程的地址空間,掛起的信號,進程的狀態(tài),還有其他更多的信息。各個進程的task_struct存放在他們的內核棧的尾端。由于現在用slab分配器動態(tài)生成task_struct,所以只需在棧底或棧頂創(chuàng)建一個新的結構struct thread)info。在x86上,thread_info { Struct task_struct *任務。 Unsigned long flags。 __u32 cpu。 Mm_segment addr_limit。 Unsigned long previous_esp。}每個任務的thread_info 結構在它的內核棧的尾端分配。3 進程描述符的存放內核通過一個唯一的進程標識值或PID來表示每個進程。為了老版本的Unix和Linux兼容,PID 的最大值默認設置為32768,盡管這個值也可以增加到類型所允許的范圍。 這個值很重要,因為它實際上就是系統中允許同時存在的進程的最大數目。這個值越小,轉一圈就越快,本類數值大的進程比數值小的進程遲運行,但這樣一來就破壞了這一原則。 在內核中,訪問任務通常需要獲得指向其task_struct指針。因此,通過current宏查找到當前正在運行進程的進程描述符的速度就顯得尤為重要。有的硬件體系結構可以拿出一個專門寄存器來存放指向當前進程task_strcut的指針,用于加快訪問速度。在x86體系上,current把棧指針的后13個有效位屏蔽掉,用來計算出thread_info的偏移。匯編代碼如下: Mov $81925, %eax Andl %esp, %eax 這里假定棧的大小為8KB。 最后,current_thread_info()task。也就是說,在PPC上,current宏只需要把r2寄存器中的值返回就行了。而訪問進程描述符是一個重要的頻繁的操作,所以PPC的內核開發(fā)者會覺得完全有必要為此使用一個專門的寄存器。系統的每個進程都必然處于五種進程狀態(tài)的一種。這是進程在用戶空間中執(zhí)行唯一可能的狀態(tài),也可以應用到內核空間中正在執(zhí)行的進程。一檔這些條件達成,內核就會把進程狀態(tài)設置為運行。(3) TASK_UNINTERRUPTIBLE(不可中斷)——除了不會因為接受到信號而被喚醒從而投入運行外,這個狀態(tài)與可打斷的狀態(tài)相同。由于處于此狀態(tài)的任務對信號不做響應,所以較之可中斷狀態(tài),使用的較少。一旦父進程調用了wait進程描述符就會被釋放掉。通常這種狀態(tài)發(fā)生在接受到SIGSTOP、SIGTTIN、SIGTTOU等信號的時候。5 設置當前進程狀態(tài)內核經常需要調整某個進程的狀態(tài)。 函數。必要的時候,它會設置內存屏障來強制其他處理器作重新排序(一般只有在SMP系統中有此必要),否則,它等價于:Taskstate = state。6 進程上下文可執(zhí)行程序代碼是進程的重要組成部分。一般程序在用戶空間執(zhí)行。此時,我們稱內核“代表進程執(zhí)行”并處于進程上下文中。除非在此間隙有更高優(yōu)先級的進程需要執(zhí)行并由調度器做出了相應的調整,否則在內核退出的時候,程序恢復在用戶空間繼續(xù)執(zhí)行。進程只有通過這些接口才能陷入內核執(zhí)行——對內核的所有的訪問都必須通過這些