您的位置:首页 > 编程语言

刚写的一个unix作业,关于内核编程的--2010-1-8 18:13

2010-05-21 13:50 246 查看
转自我另一个的博客,书写日期

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: