剛寫的一個unix作業,關於內核編程的--2010-1-8 18:13

轉自我另一個的博客,書寫日期

2010-1-8 18:13

作業題目:

內核模塊編程練習

設計兩個內核模塊,它們分別完成以下工作:

1) 設計一個模塊,該模塊的功能是列出系統中所有內核進程的程序名、PID號和進程的狀態。

2) 設計一個帶有參數的內核模塊,其參數爲某個進程的PID號;該模塊的功能是列出該進程的家族信息,包括父進程、兄弟進程和子進程的程序名、PID號。

 

作業1的答案:

 1 #include <linux/init.h>   //定義在init.h
 2 #include <linux/module.h>
 3 #include <linux/sched.h>
 4 #include <linux/list.h>
 5 
 6 MODULE_LICENSE("GPL");
 7 
 8 static int name_init(void//初始化函數,註冊和申請資源。返回0表示初始化成功;其他值表示失敗
 9 {
10     printk("My name is Liu Xu/n");
11     struct task_struct *p,*task1;
12     struct list_head *ptr;
13     for_each_process(p)
14     {    
15         printk("/nProcess info:/n");
16         printk("comm=%s,pid=%d,state=%ld/n",p->comm,p->pid,p->state);
17         task1=list_entry(&p->children,struct task_struct,children);
18         printk("/nChildren info:/n");
19         list_for_each(ptr,&(p->children)){
20             task1=list_entry(ptr,struct task_struct,sibling);
21             printk("child:comm=%s,pid=%d,state=%ld/n",task1->comm,task1->pid,task1->state);
22         
23         }
24         printk("/n");
25     }
26 
27     return 0;    
28 }
29 static void name_exit(void)  // 退出的函數,註銷和釋放資源
30 {
31     printk("Goodbye!/n");
32 }
33 
34 module_init(name_init); //標記的name_init函數在模塊加載時調用
35 module_exit(name_exit); //標記的name_exit函數在卸載模塊時調用
36 


作業2的答案:

 1 #include <linux/init.h>   //定義在init.h
 2 #include <linux/module.h>
 3 #include <linux/sched.h>
 4 #include <linux/list.h>
 5 
 6 MODULE_LICENSE("GPL");
 7 static int pid=1;
 8 module_param(pid,int,S_IRUGO);//給模塊傳遞參數
 9 
10 static int name_init(void//初始化函數,註冊和申請資源。返回0表示初始化成功;其他值表示失敗
11 {
12     struct task_struct *task1,*task2;
13     struct list_head *ptr;
14 
15     printk("My name is Liu Xu/n");
16     //find_task_by_pid 和 find_task_by_vpid在2.6.30版後內核都沒有被聲明爲extern
17     //find_get_pid是獲得pid_t對應的pid結構指針,以給pid_task調用,在內核版本號爲2.6.31-17-generic下測試通過
18     task1=pid_task(find_get_pid(pid),PIDTYPE_PID);    
19     if(task1){
20         printk("The wanted process info:/n");
21         printk("##Wanted:comm=%s,pid=%d,state=%ld/n",task1->comm,task1->pid,task1->state);
22         task2=task1->parent;
23         printk("##His Parent:comm=%s,pid=%d,state=%ld/n",task2->comm,task2->pid,task2->state);
24         /*list_for_each(ptr,&task1->children){
25             task2=list_entry(ptr,struct task_struct,tasks);//ptr是task1的child,是task2的sibiling,雙鏈表
26             printk("##His child:comm=%s,pid=%d,state=%ld/n",task2->comm,task2->pid,task2->state);
27         }*/
28         //searching the children
29            list_for_each_entry(task2, &task1->children, sibling) {
30             printk("##His child:comm=%s,pid=%d,state=%ld/n",task2->comm,task2->pid,task2->state);
31         }
32         //searching the siblings
33         list_for_each_entry(task2, &task1->real_parent->children, sibling) {
34             printk("##His siblings:comm=%s,pid=%d,state=%ld/n",task2->comm,task2->pid,task2->state);
35         }
36         
37     }else{
38         printk("process %d does not exist!/n",pid);
39     }    
40     return 0;    
41 }
42 static void name_exit(void)  // 退出的函數,註銷和釋放資源
43 {
44     printk("Goodbye!/n");
45 }
46 
47 module_init(name_init); //標記的name_init函數在模塊加載時調用
48 module_exit(name_exit); //標記的name_exit函數在卸載模塊時調用
49 

作業2因爲在linux內核版本2.6.30以後,沒有把find_task_by_vpid聲明爲extern,所以不能當作API函數調用,我在網上搜了好多方法才最終找到解決方案的。。
第18行的那句話,在2.6.24版本以前的內核,應該寫成
task1=find_task_by_pid(pid);

在2.6.30版本以前內核應該寫成

task1=find_task_by_vpid(pid);

最後把那個超級通用的內核編譯的Makefile發出來吧。。

ifneq ($(KERNELRELEASE),)
    obj
-m:=name.o
else
    KDIR:
=/lib/modules/$(shell uname -r)/build
    PWD:
=$(shell pwd)

default:
    $(MAKE) 
-C $(KDIR) M=$(PWD) modules
clean:
    $(MAKE) 
-C $(KDIR) M=$(PWD) clean

endif

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章