歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux綜合 >> Linux內核

進程在Linux內核中的角色扮演

在Linux內核中,內核將進程、線程和內核線程一視同仁,即內核使用唯一的數據結構task_struct來分別表示他們;內核使用相同的調度算法對這三者進行調度;並且內核也使用同一個函數do_fork()來分別創建這三種執行線程(thread of execution)。執行線程通常是指任何正在執行的代碼實例,比如一個內核線程,一個中斷處理程序或一個進入內核的進程。

這樣處理無疑是簡潔方便的,並且內核在統一處理這三者之余並沒有失去他們本身所具有的特性。本文將結合進程、線程和內核線程的特性淺談進程在內核中的角色扮演問題。

1.進程描述符task_struct的多角色扮演

上述三種執行線程在內核中都使用統一的數據結構task_struct來表示。task_struct結構即所謂的進程描述符,它包含了與一個進程相關的所有信息。進程描述符中不僅包含了許多描述進程屬性的字段,而且還有一系列指向其他數據結構的指針。下面將簡單介紹進程描述符中幾個比較特殊的字段,它們分別指向代表進程所擁有的資源的數據結構。

mm字段:指向mm_struct結構的指針,該類型用來描述進程整個的虛擬地址空間。

fs字段:指向fs_struct結構的指針,該類型用來描述進程所在文件系統的根目錄和當前進程所在的目錄信息。

files字段:指向files_struct結構的指針,該類型用來描述當前進程所打開文件的信息。

signal字段:指向signal_struct結構(信號描述符)的指針,該類型用來描述進程所能處理的信號。

對於普通進程來說,上述字段分別指向具體的數據結構以表示該進程所擁有的資源。

對應每個線程而言,內核通過輕量級進程與其進行關聯。輕量級進程之所輕量,是因為它與其他進程共享上述所提及的進程資源。比如進程A創建了線程B,則B線程會在內核中對應一個輕量級進程。這個輕量級進程很自然的對應一個進程描述符,只不過B線程的進程描述符中的某些代表資源指針會和A進程中對應的字段指向同一個數據結構,這樣就實現了多線程之間的資源共享。

由於內核線程只運行在內核態,並且只能由其他內核線程創建,所以內核線程並不需要和普通進程那樣的獨立地址空間。因此內核線程的進程描述符中的mm指針即為NULL。內核線程是否共享父內核線程的某些資源,則通過向內核線程創建函數kernel_thread()傳遞參數來決定。

通過上面的分析可以發現,內核中使用統一的進程描述符來表示進程、線程和內核線程,根據他們不同的特性,其進程描述符中某些代表資源的字段的指向會有所不同,以實現扮演不同角色。

2. do_fork()的多角色扮演

進程、線程以及內核線程都有對應的創建函數,不過這三者所對應的創建函數最終在內核都是由do_fork()進行創建的。do_fork()函數的原型如下:

long do_fork(unsigned long clone_flags,
               unsigned long stack_start,
               struct pt_regs *regs,
               unsigned long stack_size,
               int __user *parent_tidptr,
               int __user *child_tidptr)

該函數的參數個數是固定的,每個參數的功能如下:

clone_flags:代表進程各種特性的標志。低字節指定子進程結束時發送給父進程的信號代碼,一般為SIGCHLD信號,剩余三個字節是若干個標志或運算的結果。

stack_start:子進程用戶態堆棧的指針,該參數會被賦值給子進程的esp寄存器。

regs:指向通用寄存器值的指針,當進程從用戶態切換到內核態時通用寄存器中的值會被保存到內核態堆棧中。

stack_size:未被使用,默認值為0。

parent_tidptr:該子進程的父進程用戶態變量的地址,僅當CLONE_PARENT_SETTID被設置時有效。

child_tidptr:該子進程用戶態變量的地址,僅當CLONE_CHILD_SETTID被設置時有效。

既然進程、線程和內核線程在內核中都是通過do_fork()完成創建的,那麼do_fork()是如何體現其功能的多樣性?其實,clone_flags參數在這裡起到了關鍵作用,通過選取不同的標志,從而保證了do_fork()函數實現多角色——創建進程、線程和內核線程——功能的實現。clone_flags參數可取的標志很多,下面只介紹幾個與本文相關的標志。

CLONE_VIM:子進程共享父進程內存描述符和所有的頁表。

CLONE_FS:子進程共享父進程所在文件系統的根目錄和當前工作目錄。

CLONE_FILES:子進程共享父進程打開的文件。

CLONE_SIGHAND:子進程共享父進程的信號處理程序、阻塞信號和掛起的信號。使用該標志必須同時設置CLONE_VM標志。

如果創建子進程時設置了上述標志,那麼子進程會共享這些標志所代表的父進程資源。

Copyright © Linux教程網 All Rights Reserved