版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、<p><b> ?。?lt;/b></p><p> Process Management</p><p> The process is one of the fundamental abstractions in Unix operating systems. A process is a program(object code stored on so
2、me media) in execution. Processes are, however, more than just the executingprogram code (often called the text section in Unix). They also include a set of resources such as open files and pending signals, internal kern
3、el data, processor state, an address space, one or more threads ofexecution, and a data section containing global variables. Processes, in effect, are the </p><p> Threads of execution, often shortened to t
4、hreads, are the objects of activity within the process. Each thread includes a unique program counter, process stack, and set of processor registers. The kernel schedules individual threads, not processes. In traditional
5、 Unix systems, each process consists of one thread. In modern systems, however, multithreaded programsthose that consist of more than one threadare common. Linux has a unique implementation of threads: It does not differ
6、entiate between th</p><p> On modern operating systems, processes provide two virtualizations: a virtualized processor and virtual memory. The virtual processor gives the process the illusion that it alone
7、monopolizes the system, despite possibly sharing the processor among dozens of other processes. discusses this virtualization. Virtual memory lets the process allocate and manage memory as if it alone owned all the memor
8、y in the system. Interestingly, note that threads share the virtual memory abstraction while each rec</p><p> A program itself is not a process; a process is an active program and related resources. Indeed,
9、 two or more processes can exist that are executing the same program. In fact, two or more processes can exist that share various resources, such as open files or an address space.</p><p> A process begins
10、its life when, not surprisingly, it is created. In Linux, this occurs by means of the fork()system call, which creates a new process by duplicating an existing one. The process that calls fork() is the parent, whereas th
11、e new process is the child. The parent resumes execution and the child starts execution at the same place, where the call returns. The fork() system call returns from the kernel twice:once in the parent process and again
12、 in the newborn child.</p><p> Often, immediately after a fork it is desirable to execute a new, different, program. The exec*() family of function calls is used to create a new address space and load a new
13、 program into it. In modern Linux kernels, fork() is actually implemented via the clone() system call, which is discussed in a followingsection.</p><p> Finally, a program exits via the exit() system call.
14、This function terminates the process and frees all its resources. A parent process can inquire about the status of a terminated child via the wait4() system call, which enables a process to wait for the termination of a
15、 specific process. When a process exits, it is placed into a special zombie state that is used to represent terminated processes until the parent calls wait() or waitpid().</p><p> Another name for a proces
16、s is a task. The Linux kernel internally refers to processes as tasks. although when I say task I am generally referring to a process from the kernel's point of view.</p><p> 1 Process Descriptor and t
17、he Task Structure</p><p> The kernel stores the list of processes in a circular doubly linked list called the task list. Each element in the task list is a process descriptor of the type struct task_struct,
18、 which is defined in <linux/sched.h>.The process descriptor contains all the information about a specific process.</p><p> The task_struct is a relatively large data structure, at around 1.7 kilobyte
19、s on a 32-bit machine. This size,however, is quite small considering that the structure contains all the information that the kernel has and needs about a process. The process descriptor contains the data that describes
20、the executing programopen files, the process's address space, pending signals, the process's state, and much more</p><p> 2 Allocating the Process Descriptor</p><p> The task_struct s
21、tructure is allocated via the slab allocator to provide object reuse and cache coloring Prior to the 2.6 kernel series, struct task_struct was stored at the end of the kernel stack of each process. This allowed architec
22、tures with few registers, such as x86, to calculate the location of the process descriptor via the stack pointer without using an extra register to store the location. With the process descriptor now dynamically created
23、via the slab allocator, a new structure, st</p><p> The thread_info structure is defined on x86 in <asm/thread_info.h> as</p><p> struct thread_info {</p><p> struct task_s
24、truct *task;</p><p> struct exec_domain *exec_domain;</p><p> unsigned long flags;</p><p> unsigned long status;</p><p> __u32 cpu;</p><p> __s32 pree
25、mpt_count;</p><p> mm_segment_t addr_limit;</p><p> struct restart_block restart_block;</p><p> unsigned long previous_esp;</p><p> __u8 supervisor_stack[0];</p&
26、gt;<p><b> };</b></p><p> Each task's tHRead_info structure is allocated at the end of its stack. The task element of the structure is a pointer to the task's actual task_struct.
27、</p><p> 3 Storing the Process Descriptor</p><p> The system identifies processes by a unique process identification value or PID. The PID is a numerical value that is represented by the opa
28、que type pid_t, which is typically an int. Because of backward compatibility with earlier Unix and Linux versions, however, the default maximum value is only 32,768 although the value can optionally be increased to the f
29、ull range afforded the type. The kernel stores this value as pid inside each process descriptor.</p><p> This maximum value is important because it is essentially the maximum number of processes that may ex
30、ist concurrently on the system. Although 32,768 might be sufficient for a desktop system, large servers may require many more processes. The lower the value, the sooner the values will wrap around, destroying the useful
31、notion that higher values indicate later run processes than lower values. If the system is willing to break compatibility with old applications, the administrator may increase the</p><p> Inside the kernel,
32、 tasks are typically referenced directly by a pointer to their task_struct structure. In fact, most kernel code that deals with processes works directly with struct task_struct. Consequently, it is very useful to be able
33、 to quickly look up the process descriptor of the currently executing task, which is done via the current macro. This macro must be separately implemented by each architecture. Some architectures save a pointer to the ta
34、sk_struct structure of the currently runni</p><p> On x86, current is calculated by masking out the 13 least significant bits of the stack pointer to obtain the thread_info structure. This is done by the cu
35、rrent_thread_info() function. The assembly is shown here:</p><p> movl $-8192, %eax</p><p> andl %esp, %eax</p><p> This assumes that the stack size is 8KB. When 4KB stacks are e
36、nabled, 4096 is used in lieu of 8192.</p><p> Finally, current dereferences the task member of thread_info to return the task_struct:current_thread_info()->task; Contrast this approach with that taken by
37、 PowerPC (IBM's modern RISC-based microprocessor), which stores the current task_struct in a register. Thus, current on PPC merely returns the value stored in the register r2. PPC can take this approach because, unli
38、ke x86, it has plenty of registers. Because accessing the process descriptor is a common and important job, the PPC kernel deve</p><p> 4 Process State</p><p> The state field of the process
39、descriptor describes 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:</p><p> (1) TASK_RUNNING The
40、 process is runnable; it is either currently running or on a runqueue waiting to run. This is the only possible state for a process executing in user-space; it can also apply to a process in kernel-space that is actively
41、 running.</p><p> (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 process's state to TASK_R
42、UNNING. The process also awakes prematurely and becomes runnable if it receives a signal.</p><p> (3) TASK_UNINTERRUPTIBLE This state is identical to TASK_INTERRUPTIBLE except that it does not wake up and
43、become runnable if it receives a signal. This is used in situations where the process must wait without interruption or when the event is expected to occur quite quickly. Because the task does not respond to signals in t
44、his state, this state is less often used than TASK_INTERRUPTIBLE</p><p> (4)TASK_ZOMBIE The task has terminated, but its parent has not yet issued a wait4() system call. The task's process descriptor mu
45、st remain in case the parent wants to access it. If the parent calls wait4(), the process descriptor is deallocated.</p><p> (5) TASK_STOPPED Process execution has stopped; the task is not running nor is it
46、 eligible to run. This occurs if the task receives the SIGSTOP, SIGTSTP, SIGTTIN, or SIGTTOU signal or if it receives any signal while it is being debugged.</p><p> 5 Manipulating the Current Process State
47、</p><p> Kernel code often needs to change a process's state. The preferred mechanism is using set_task_state(task, state); This function sets the given task to the given state. If applicable, it also p
48、rovides a memory barrier to force ordering on other processors (this is only needed on SMP systems). Otherwise, it is equivalent to task->state = state; The method set_current_state(state) is synonymous to set_task_st
49、ate(current, state).</p><p> 6 Process Context</p><p> One of the most important parts of a process is the executing program code. This code is read in from an executable file and executed wi
50、thin the program's address space. Normal program execution occurs in userspace. When a program executes a system call or triggers an exception, it enters kernel-space. At this point, the kernel is said to be "ex
51、ecuting on behalf of the process" and is in process context. When in process context, the current macro is valid. Upon exiting the kernel, the process re</p><p> System calls and exception handlers are
52、 well-defined interfaces into the kernel. A process can begin executing in kernel.</p><p><b> 進程管理</b></p><p> 進程是Uinx操作系統(tǒng)最基本的抽象之一。一個進程就是處于執(zhí)行期間的程序(目標代碼放在某種存儲介質上)。但進程并不僅僅局限于一段可執(zhí)行程序(
53、Unix稱其為代碼段(text section))。通常進程還要包含其他資源,像打開的文件、掛起的信號、內核內部數據、處理器狀態(tài)、地址空間及一個或多個執(zhí)行線程、當然還包括用來存放全局變量的數據段等。實際上,進程就是正在執(zhí)行的程序代碼的活標本。</p><p> 執(zhí)行線程,簡稱線程(thread),是在進程中活動的對象。每個線程用由一個獨立的程序計數器、進程棧和一組進程寄存器。內核調度的對象是線程,而不是進程。在
54、傳統(tǒng)的Unix系統(tǒng)中,一個進程只包含一個線程,但現在的系統(tǒng)中,包含多個線程的多線程程序司空見慣。Linux系統(tǒng)的線程實現非常特別—他對線程和進程并不特別區(qū)分。對Linux而言,線程只不過是一種特殊的進程罷了。</p><p> 在現代操作系統(tǒng)中,進程提供兩種虛擬機制:虛擬處理器和虛擬內存。雖然實際上可能是許多進程正在分享一個處理器,但虛擬處理器給進程一種假象,讓這些進程覺得自己在獨享處理器。而虛擬內存讓進程在獲
55、取和使用內存是覺得自己擁有整個操作系統(tǒng)的所有內存資源。有趣的是,注意在線程之間(這里是指包含在同一個進程中的進程)可以共享虛擬內存,但擁有各自的虛擬處理器。</p><p> 程序本身并不是進程:進程是處于執(zhí)行期間的程序以及它所包含的資源的總稱。實際上完全可以存在兩個或者多個不同的進程執(zhí)行的是同一個程序。并且兩個或兩個以上并存的進程還可以共享許多諸如打開的文件、地址空間之類的資源。無疑,進程在它被創(chuàng)建的時刻開始
56、存活。在Linux系統(tǒng)中,這通常是調用fork()系統(tǒng)調用的結果,該系統(tǒng)調用通過復制一個現有進程來創(chuàng)建一個全新的進程。調用fork()的進程被稱為父子進程,新產生的進程被稱為子進程。在調用結束的時,在返回這個相同位置上,父進程恢復執(zhí)行,子進程開始執(zhí)行。Fork()系統(tǒng)調用從內核返回兩次:一次回到父進程,另一個回到新誕生的子進程。</p><p> 通常,創(chuàng)建新的進程都是為了立即執(zhí)行新的、不同的程序,而接著調用e
57、xec()這族函數就可以創(chuàng)建新的地址空間,并把新的程序載入。在現代Linux內核中,fork()實際上是由clone()系統(tǒng)調用實現的,后者將在后面討論。</p><p> 最終,程序通過exit()系統(tǒng)調用退出。這個函數會終結進程并將其占有的資源釋放掉。父進程可以通過wait()系統(tǒng)調用查詢子進程是否終結,這其實使得進程擁有了等待指定進程執(zhí)行完畢的能力。進程退出執(zhí)行后被置為僵死狀態(tài),直到它的父進程調用wait
58、()或waitpid()為止。</p><p> 進程的另一個名字是任務(task)。Linux內核通常把進程也叫做任務。在這里所說的任務是指從內核觀點看到的進程。</p><p> 1 進程描述符及任務結構</p><p> 內核把進程存放在叫做任務隊列(task list)的雙向循環(huán)鏈表中。鏈表的每一項都是類型為task_struct、稱為進程描述符的結構
59、,改結構定義在<linux/sched.h>文件中。進程描述符中包含一個具體進程的所有信息。</p><p> task_struct相對較大,在32位機器上,它大約有1.7k字節(jié)。但如果考慮到該結構內包含了內核管理一個進程所需要的所有信息,那么它的大小也相當小了。進程描述符中包含的數據能完整的描述一個正在執(zhí)行的程序:它打開的文件,進程的地址空間,掛起的信號,進程的狀態(tài),還有其他更多的信息。<
60、/p><p><b> 2 進程描述符</b></p><p> Linux通過slab非配器分配task_struct結構,這樣能達到對象復用和緩存著色的目的。在2.6以前的內核中,各個進程的task_struct存放在他們的內核棧的尾端。這樣做的目的是為了讓那些像x86這樣寄存器較的硬件體系結構只要通過棧指針就能算出它的位置,從而避免使用額外的寄存器專門記錄。由
61、于現在用slab分配器動態(tài)生成task_struct,所以只需在棧底或棧頂創(chuàng)建一個新的結構struct thread)info。這個新的結構能使在匯編代碼中計算器偏移變得相當的容易。</p><p> 在x86上,thread_info {</p><p> Struct task_struct *任務;</p><p> Struct exec_d
62、omain *exec_domain;</p><p> Unsigned long flags;</p><p> Unsigned long status;</p><p> __u32cpu;</p><p> __s32preempt_count;</p>&
63、lt;p> Mm_segment addr_limit;</p><p> Struct restart_blockrestart_block;</p><p> Unsigned longprevious_esp;</p><p> __u8supervisor_stack[0];</p>
64、<p><b> }</b></p><p> 每個任務的thread_info 結構在它的內核棧的尾端分配。結構中task域中存放的是指向該任務實際task_struct的指針。</p><p> 3 進程描述符的存放</p><p> 內核通過一個唯一的進程標識值或PID來表示每個進程。PID 是一個數,表示為pid
65、_t隱含類型,實際上就是一個int類型。為了老版本的Unix和Linux兼容,PID 的最大值默認設置為32768,盡管這個值也可以增加到類型所允許的范圍。內核把每個進程PID存放在他們各自的進策劃那個描述符中。</p><p> 這個值很重要,因為它實際上就是系統(tǒng)中允許同時存在的進程的最大數目。盡管32768對一般的桌面系統(tǒng)足夠用了,但是大型服務器可能需要更新進程。這個值越小,轉一圈就越快,本類數值大的進程比
66、數值小的進程遲運行,但這樣一來就破壞了這一原則。如果確實需要的話,可以不考慮與老式系統(tǒng)的兼容,由系統(tǒng)管理員通過修改/proc/sys/kernel/pid_max來提高上限。</p><p> 在內核中,訪問任務通常需要獲得指向其task_struct指針。實際上,內核中大部分處理進程的代碼都是直接通過task_struct進行的。因此,通過current宏查找到當前正在運行進程的進程描述符的速度就顯得尤為重要
67、。硬件體系結構不同,該宏的實現也就不同,它必須針對專門的硬件體系結構作處理。有的硬件體系結構可以拿出一個專門寄存器來存放指向當前進程task_strcut的指針,用于加快訪問速度。而有些像x86這樣的體系結構,就只能在內核棧的尾端創(chuàng)建thread_info結構,通過計算偏移間接地查找task_struct結構。</p><p> 在x86體系上,current把棧指針的后13個有效位屏蔽掉,用來計算出threa
68、d_info的偏移。該操作通過current_thread_info()函數完成的。匯編代碼如下:</p><p> Mov $-81925, %eax</p><p> Andl %esp, %eax</p><p> 這里假定棧的大小為8KB。當4KB的棧啟用時,就用4096,而不是8192。</p><p> 最后,cur
69、rent_thread_info()->task;</p><p> 對比一下這部分在PowerPC上的實現(IBM基于RISC的現代微處理器),我們可以發(fā)現當前task_struct的地址是保存在一個寄存器中的。也就是說,在PPC上,current宏只需要把r2寄存器中的值返回就行了。與x86不一樣,PPC有足夠多的寄存器,所以它的實現有這樣的余地。而訪問進程描述符是一個重要的頻繁的操作,所以PPC的內
70、核開發(fā)者會覺得完全有必要為此使用一個專門的寄存器。</p><p><b> 進程狀態(tài)</b></p><p> 進程描述符中的state域描述了進程的當前狀態(tài)。系統(tǒng)的每個進程都必然處于五種進程狀態(tài)的一種。該域的值也必為下列五種狀態(tài)標志之一:</p><p> TASK_RUNNING(運行)——進程是可執(zhí)行的,它或者正在執(zhí)行,或者在運行
71、隊列中等待執(zhí)行。這是進程在用戶空間中執(zhí)行唯一可能的狀態(tài),也可以應用到內核空間中正在執(zhí)行的進程。</p><p> TASK_INTERRUPTIBLE(可中斷)——進程正在睡眠(也就是說它被阻塞),等待某些條件的達成。一檔這些條件達成,內核就會把進程狀態(tài)設置為運行。處于此狀態(tài)的進程也會因為接受到信號而提前被喚醒并投入到運行。</p><p> TASK_UNINTERRUPTIBLE(
72、不可中斷)——除了不會因為接受到信號而被喚醒從而投入運行外,這個狀態(tài)與可打斷的狀態(tài)相同。這個狀態(tài)通常在進程必須在等待時不受干擾或等待時間很快就會發(fā)生時出現。由于處于此狀態(tài)的任務對信號不做響應,所以較之可中斷狀態(tài),使用的較少。</p><p> TASK_ZOMBIE(僵死)——該進程已經結束了,但是其父進程還沒有調用wait()系統(tǒng)調用,為了父進程能夠獲知它的消息,子進程的進程描述符仍然被保留著。一旦父進程調用
73、了wait進程描述符就會被釋放掉。</p><p> TASK_STOPPED(停止)——進程停止執(zhí)行,進程沒有投入運行也不能投入欲行。通常這種狀態(tài)發(fā)生在接受到SIGSTOP、SIGTTIN、SIGTTOU等信號的時候。此外,在調試期間受到任何信號,都會使進程進入這種狀態(tài)。</p><p> 5 設置當前進程狀態(tài)</p><p> 內核經常需要調整某個進程的狀
74、態(tài)。這時最好使用set_task_state(task, state); 函數。該函數將制定的進程設置為給定的狀態(tài)。必要的時候,它會設置內存屏障來強制其他處理器作重新排序(一般只有在SMP系統(tǒng)中有此必要),否則,它等價于:Task->state = state;方法set_current_state(state),和set_task_state(current, state)含義是等同的。</p><p>
75、<b> 進程上下文</b></p><p> 可執(zhí)行程序代碼是進程的重要組成部分。這些代碼從可執(zhí)行文件載入到進程的地址空間執(zhí)行。一般程序在用戶空間執(zhí)行。當一個程序調用執(zhí)行了系統(tǒng)調用或者觸發(fā)了某個異常,它就陷入了內核空間。此時,我們稱內核“代表進程執(zhí)行”并處于進程上下文中。在此上下文中current宏是有效的。除非在此間隙有更高優(yōu)先級的進程需要執(zhí)行并由調度器做出了相應的調整,否則在內核退
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 眾賞文庫僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- [雙語翻譯]--物流管理外文翻譯--全球化進程中的物流管理未來
- 外文翻譯--- 燃煤鍋爐的燃燒進程控制
- 2015年--物流管理外文翻譯--全球化進程中物流管理的未來
- 2015年--物流管理外文翻譯--全球化進程中的物流管理未來
- 關于景觀都市主義發(fā)展進程的探討 外文翻譯
- 城市化進程和經濟增長外文文獻翻譯
- 外文翻譯---解析oracle數據庫后臺進程的功能
- 外文翻譯--制造分析進程數據使用快速標記技術
- vb課題項目進程管理系統(tǒng)設計(論文+源代碼+開題報告+外文翻譯+答辯ppt)
- 存貨管理【外文翻譯】
- 預算管理【外文翻譯】
- 2015年--物流管理外文翻譯--全球化進程中的物流管理未來(譯文).docx
- 2015年--物流管理外文翻譯--全球化進程中的物流管理未來(原文).pdf
- 外文翻譯--制造分析進程數據使用快速標記技術
- 績效管理 外文翻譯
- 績效管理外文翻譯
- 薪酬管理 外文翻譯
- 設計管理外文翻譯
- 營銷管理-外文翻譯
- 倉儲管理【外文翻譯】
評論
0/150
提交評論