《Linux及安全》实践2
一、Linux基本内核模块
1.1什么是内核模块
- linux模块是一些可以作为独立程序来编译的函数和数据类型的集合。之所以提供模块机制,是因为Linux本身是一个单内核。单内核由于所有内容都集成在一起,效率很高,但可扩展性和可维护性相对较差,模块机制可弥补这一缺陷。
- Linux模块可以通过静态或动态的方法加载到内核空间,静态加载是指在内核启动过程中加载;动态加载是指在内核运行的过程中随时加载。(我们要做的实践内容就是动态加载内核模块)
- 一个模块被加载到内核中时,就成为内核代码的一部分。模块加载入系统时,系统修改内核中的符号表,将新加载的模块提供的资源和符号添加到内核符号表中,以便进行模块间的通信。
1.2.c程序编写
-
具体代码如下(打印学号):
-
解释:
(1)关于 #include <linux/init.h>以及#include <linux/module.h>是编写内核模块程序所必须的2个头文件。
(2)编写内核模块时必须要有的两个函数 :
- 加载函数:static int init_fun(void) { // 初始化代码 } 函数实例: static int hello_init(void)// 不加void在调试时会出现报警 { printk("hello world!/n"); return 0; } - 卸载函数(出口函数) 无返回值 static void cleaup_fun(void) { // 释放代码 }
(3)printk是内核态信息打印函数,功能和比标准C库的printf类似
(5)module_init(fun):告诉内核模块程序从何处开始执行。module_exit(fun):告诉内核编写模块程序从何处离开。
(6)模块许可声明:函数原型是MODULE_LICENSE(),告诉内核该程序使用的许可证,一般是GPL。
1.3Makefile编写
-
代码如下:
-
解释:
- 其中make -C $(LINUX_KERNEL_PATH) 指明跳转到内核源码目录下读取Makefile
M=$(CURRENT_PATH) 表明返回到当前目录继续执行当前的Makefile(M= 后指定的是 lwr.c 和 Makefile 所在的目录) - 关于个人虚拟机的内核版本号,输入指令“uname - a”可查看,在usr/src中可找到
- 其中make -C $(LINUX_KERNEL_PATH) 指明跳转到内核源码目录下读取Makefile
1.4操作
-
输入make进行自动编译;编译之后,生成需要的文件
-
输入sudo insmod lwr.ko,加载模块(root权限)
-
输入dmesg,测试模块输出
-
卸载模块:“sudo rmmod 模块名” 之后,就将内核中之前加载的模块删除,此时再输入dmesg测试,可以看到显示了exit信息
二、Linux内核模块的功能实现
1.实现输出当前进程信息的功能
-
代码如下:
-
结果如下:
-
温馨提示需要改一下makefile哦,代码里使用了printk函数打印了进程的pid、state等信息
2.实现读取进程链表的功能
-
代码如下:
-
结果如下:
-
这个与上述不同的地方在于要打印进程链表的,所以需要一个循环,连续打印
-
for_each_process()的函数本质即for循环,从第一个PCB(init_task)开始,顺着pcurrent链表进行遍历,输出所有当前进程的信息(pid,tgid等)。