詳細(xì)解剖Linux進(jìn)程管理
學(xué)習(xí)進(jìn)程時(shí),你可能會(huì)遇到linux進(jìn)程管理的問題,這里將介linux進(jìn)程管理問題的解決方法,在這里拿出來和大家分享一下。
***進(jìn)程數(shù):在 Linux 內(nèi)雖然進(jìn)程都是動(dòng)態(tài)分配的,但還是需要考慮***進(jìn)程數(shù)。在內(nèi)核內(nèi)***進(jìn)程數(shù)是由一個(gè)稱為 max_threads 的符號(hào)表示的,它可以在 ./linux/kernel/fork.c 內(nèi)找到??梢酝ㄟ^ /proc/sys/kernel/threads-max 的 proc 文件系統(tǒng)從用戶空間更改此值。
現(xiàn)在,讓我們來看看如何在 Linux進(jìn)程管理。在很多情況下,進(jìn)程都是動(dòng)態(tài)創(chuàng)建并由一個(gè)動(dòng)態(tài)分配的 task_struct 表示。一個(gè)例外是 init 進(jìn)程本身,它總是存在并由一個(gè)靜態(tài)分配的 task_struct 表示。在 ./linux/arch/i386/kernel/init_task.c 內(nèi)可以找到這樣的一個(gè)例子。
Linux 內(nèi)所有l(wèi)inux進(jìn)程管理的分配有兩種方式。***種方式是通過一個(gè)哈希表,由 PID 值進(jìn)行哈希計(jì)算得到;第二種方式是通過雙鏈循環(huán)表。循環(huán)表非常適合于對(duì)任務(wù)列表進(jìn)行迭代。由于列表是循環(huán)的,沒有頭或尾;但是由于 init_task 總是存在,所以可以將其用作繼續(xù)向前迭代的一個(gè)錨點(diǎn)。讓我們來看一個(gè)遍歷當(dāng)前任務(wù)集的例子。
任務(wù)列表無法從用戶空間訪問,但該問題很容易解決,方法是以模塊形式向內(nèi)核內(nèi)插入代碼。下面清單所示的是一個(gè)很簡單的程序,它會(huì)迭代任務(wù)列表并會(huì)提供有關(guān)每個(gè)任務(wù)的少量信息(name、pid 和 parent 名)。注意,在這里,此模塊使用 printk 來發(fā)出結(jié)果。要查看具體的結(jié)果,可以通過 cat 實(shí)用工具(或?qū)崟r(shí)的 tail -f /var/log/messages)查看 /var/log/messages 文件。next_task 函數(shù)是 sched.h 內(nèi)的一個(gè)宏,它簡化了任務(wù)列表的迭代(返回下一個(gè)任務(wù)的 task_struct 引用)。
清單:發(fā)出任務(wù)信息的簡單內(nèi)核模塊(procsview.c)
#include
#include
#include
int init_module( void ){
/* Set up the anchor point */
struct task_struct *task = &init_task;
/* Walk through the task list, until we hit the init_task again */do {
printk( KERN_INFO "*** %s [%d] parent %s\n",
task->comm, task->pid, task->parent->comm );
} while ( (task = next_task(task)) != &init_task );
return 0;
}
void cleanup_module( void ){
return;}
可以用清單所示的 Makefile 編譯此模塊。在編譯時(shí),可以用 insmod procsview.ko 插入模塊對(duì)象,也可以用 rmmod procsview 刪除它。
清單:用來構(gòu)建內(nèi)核模塊的 Makefile
obj-m += procsview.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
插入后,/var/log/messages 可顯示輸出,如下所示。從中可以看到,這里有一個(gè)空閑任務(wù)(稱為 swapper)和 init 任務(wù)(pid 1)。
Nov 12 22:19:51 mtj-desktop kernel: [8503.873310] *** swapper [0] parent swapper
Nov 12 22:19:51 mtj-desktop kernel: [8503.904182] *** init [1] parent swapper
Nov 12 22:19:51 mtj-desktop kernel: [8503.904215] *** kthreadd [2] parent swapper
Nov 12 22:19:51 mtj-desktop kernel: [8503.904233] *** migration/0 [3] parent kthreadd
...
注意,還可以標(biāo)識(shí)當(dāng)前正在運(yùn)行的任務(wù)。Linux 維護(hù)一個(gè)稱為 current 的符號(hào),代表的是當(dāng)前運(yùn)行的進(jìn)程(類型是 task_struct)。如果在 init_module 的尾部插入如下這行代碼:
printk( KERN_INFO, "Current task is %s [%d], current->comm, current->pid );
會(huì)看到:
Nov 12 22:48:45 mtj-desktop kernel: [10233.323662] Current task is insmod [6538]
注意到,當(dāng)前的任務(wù)是 insmod,這是因?yàn)?init_module 函數(shù)是在 insmod 命令執(zhí)行的上下文運(yùn)行的。current 符號(hào)實(shí)際指的是一個(gè)函數(shù)(get_current)并可在一個(gè)與 arch 有關(guān)的頭部中找到(比如 ./linux/include/asm-i386/current.h 內(nèi)找到)。
【編輯推薦】