内核模块编程练习

 
设计两个内核模块,它们分别完成以下工作:  
1)  设计一个模块,该模块的功能是列出系统中所有内核进程的程序名、PID号和进程的状态。  
2)  设计一个带有参数的内核模块,其参数为某个进程的PID号;该模块的功能是列出该进程的家族信息,包括父进程、兄弟进程和子进程的程序名、PID号。
 
 作业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函数在卸载模块时调用
 
作业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
  
  
  
 
 

转载于:https://www.cnblogs.com/huangjiandong2012/archive/2010/12/21/1913048.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值