实验目的
学习 Linux 模块的实现机理,理解 Linux 提出内核模块这个机制的意义。
掌握如何编写 Linux 模块,运用 Linux 提供的工具和命令,掌握操作内核模块的方
法。
通过对 Linux 系统中进程的遍历,进一步理解操作系统进程概念和进程结构。
实验内容
1. 编写一个Linux的内核模块,其功能是遍历进程,输出系统中:每个进程的名字、
进程pid、进程的状态、父进程的名字;统计系统中进程个数,统计系统中
TASK_RUNNING、TASK_INTERRUPTIBLE、TASK_UNINTERRUPTIBLE、
TASK_ZOMBIE、TASK_STOPPED等(还有其他状态)状态进程的个数。
操作方法与实验步骤
(一) 编写c文件
首先我们要编写一个c文件(模块程序)。这个c文件要包括几个部分,头文件部分、初始化函数、清理函数、绑定函数入出口函数、模块许可申明。
首先是头文件部分
然后是初始化函数
函数里定义了一个num,用于计算进程数。定义struct task_struct 类型的指针*p,*task。定义struct list_head类型的指针*p1。
*task用于指向init_task(0号进程),*p用于输出遍历到的进程信息。*p1用于遍历进程。使用printk()函数输出相应信息。这里使用了list_for_each()函数遍历进程,该函数的定义在#include
然后是清理函数
最后是绑定函数入出口函数、模块许可申明。
(二) 编写Makefile
(三) 实施操作
1、首先我们要获得超级用户权限
使用命令su root
2、我们要对c文件进行编译
使用命令make
3、我们要执行内核模块的装入命令
使用命令insmod happy.ko
4、我们可以看结果输出
使用命令dmesg
5、然后我们将模块卸载
使用命令rmmod happy.ko
6、最后我们可以看结果输出
使用命令dmesg
实验结果与分析
执行内核模块的装入命令后,输入dmesg命令
可见进程的名字,pid, state,可见多数进程的state都是1,即TASK_INTERRUPTIBLE状态。
在卸载模块后,输入dmesg命令,结果输出为下图
可见进程总数为155
实验源代码
(一)happy.c
#include
#include
#include
#include
#include
#include
//初始化函数
static int hello_init(void)
{
int num=0;
struct task_struct *p,*task;
struct list_head *p1;
task = &init_task;
printk("\t\t\tHello!\n");
printk(KERN_ALERT"name\t\tpid\t\tstate\t\tfather_name\t\t");
list_for_each(p1,&task->tasks)
{
p=list_entry(p1,struct task_struct,tasks);
num=num+1;
printk(KERN_ALERT"%s\t\t%d\t\t%ld\t\t%s\n",p->comm,p->pid,p->state,p->parent->comm);
}
printk("the number of process is:%d\n",num);
return 0;
}
//清理函数
static void hello_exit(void)
{
printk(KERN_ALERT"Bye!\n");
}
//函数注册
module_init(hello_init);
module_exit(hello_exit);
//模块许可申明
MODULE_LICENSE("GPL");
(二)Makefile
TARGET=happy
KDIR=/lib/modules/$(shell uname -r)/build
PWD=$(shell pwd)
obj-m+=$(TARGET).o
default:
make -C $(KDIR) M=$(PWD) modules
clean:
make -C $(KDIR) M=$(PWD) clean