01.31 內核鏈表遍歷系統進程與模塊編程


初窺內核 | 內核鏈表遍歷系統進程與模塊編程


模塊

在開篇處還是先為你放上這次模塊的全部代碼:

<code>// traverse.c
#include <linux>
#include <linux>
#include <linux>
#include <linux>
#include <linux>
#include <linux>

static int traverse_init(void)
{
struct task_struct *task;

printk(KERN_INFO "Hello, world. \\n");

for_each_process(task)
printk(KERN_INFO "%s[%d]\\n", task->comm, task->pid);

return 0;
}

static void traverse_exit(void)
{
printk(KERN_INFO "Finish.\\n");
}

module_init(traverse_init);
module_exit(traverse_exit);/<linux>/<linux>/<linux>/<linux>/<linux>/<linux>/<code>

嘿,就只有這麼點。這裡既保留了先寫 Hello, world 的傳統,又對我們的內核進程進行了遍歷。

在閱讀完上面的代碼之後,你會發現這與你之前所學的 C 語言有那麼幾處不同。

  • 頭文件不同,連之前最常用的 stdio.h 都沒有。
  • 輸出不是 printf 而是 printk。
  • 沒有 main 函數,取而代之的卻是 __init, __exit 這種東西。

再加上一個 Makefile 文件:

<code>obj-m:=traverse.o

all:
\tmake -C /usr/src/linux-headers-$(shell uname -r) M=$(shell pwd) modules
clean:
\tmake -C /usr/src/linux-headers-$(shell uname -r) M=$(shell pwd) clean
/<code>

此時你就可以開心地為你的內核編譯模塊了。

<code>make/<code>

如果你編譯成功了的話,在當前目錄下進行 ls 操作,會發現多了很多新文件,其中對我們最重要的就是 traverse.ko 文件了。

<code>sudo insmod traverse.ko/<code>

這裡並沒有任何輸出信息,就代表著你已成功地將模塊插入到了內核中。

是時候看看輸出結果了,但是 prink 並不會將內容輸出至屏幕,它是對內核信息的一種記錄。就跟你傳給它的參數 KERN_INFO 的意思一樣,是你在告訴內核,這有警告信息,請你記錄下來。

接下來從內核中將剛剛的模塊刪除了吧:

<code>sudo rmmod traverse/<code>

同樣執行這一步時,你在終端上並不能看到提示信息。

<code>dmesg/<code>

操作後,你就能一覽你剛剛編寫的模塊的結果了。

初窺內核 | 內核鏈表遍歷系統進程與模塊編程

省略部分

初窺內核 | 內核鏈表遍歷系統進程與模塊編程

從開頭的 Hello, world 到各個進程的相關信息,以及最後你執行刪除操作時所留下的自定義 Finish 信息,你期待的全部都在這裡了。

進程

至於模塊就先說那麼多,畢竟這一片還是以說內核鏈表在內核中的應用為主,那當然就需要告訴你,進程描述符的作用了。

task_struct 類型的進程描述符中包含著一個進程的所有信息:

<code>struct task_struct {
\t// ...
\tpid_t pid;
\tchar comm[TASK_COMM_LEN];

\tstruct list_head tasks;
\t// ...
};/<code>

內核源碼文件為 include/linux/sched.h,你可以在其中找到 task_struct 的完整超長定義。其中此次你將要用到的字段有 pid,進程號;comm,進程名;還有內嵌其中的 task,鏈表結構。

再加上一個,進行便利操作,又是對 list_entry 進行了封裝的宏:

<code>#define for_each_process(p) \\
\tfor (p = &init_task ; (p = list_entry_rcu((p)->tasks.next, \\

struct task_struct, tasks) \\

\t) != &init_task ; )/<code>

本文只是一次對內核鏈表,在內核中應用的簡單體驗,希望對你理解內核鏈表有幫助。

參考

[1]Peter Jay Salzman; Michael Burian; Ori Pomerantz.The Linux Kernel Module Programming Guide[EB/OL].https://blog.csdn.net/yeshennet/article/details/82315604,2007-05-18

[2]Bovet, D. P.; Cesati, M…深入理解Linux內核[M].中國電力出版社:北京,2007:85.

[3]Love, R…Linux內核設計與實現[M].機械工業出版社:北京,2011.6:21.


分享到:


相關文章: