本文共 1295 字,大约阅读时间需要 4 分钟。
challenge: 编写一个KO,传入一个PID模块参数,打印进程得父PID, 以及所有线程PID
好久没有碰内核驱动,突然要写一个KO文件,并实现PID的打印功能,还是内心慌得一批。话不多说,直接开撸~
首先题目是要实现一个KO文件,那么首先要做的就是先具备一个linux调试环境(我这边测试在VM-ware虚拟机上面), 源码部分先上链接https://gitee.com/badbadguys
内核驱动模块初始化离不开module_init,module_exit这两个宏,关于module_init/exit这两个宏的解释这里不再多说。
为了能够在应用程序中,动态的传入PID参数,这里内核模块注册为一个字符驱动,关于字符驱动的学习,bilibili也是一个不错的学习途径linux的字符驱动
按照传统字符驱动的框架,搭建好我们的内核驱动模块,现在要对传入参数进行处理,也就是我们打印PID的核心代码。static int print_pid_operation(int input_pid)
{
struct pid *current_pid = find_get_pid(input_pid);
struct task_struct *current_task = pid_task(current_pid, PIDTYPE_PID);//获取进程任务描述符
struct pid* parent = get_task_pid(current_task->parent, PIDTYPE_PID);//获取进程pid描述符
pr_info("parent pid: %d\n", pid_nr(parent));
struct task_struct *t = current_task;
while((t=next_thread(t)) != current_task) {
struct pid* pid = get_task_pid(t, PIDTYPE_PID);//获取线程pid描述符
pr_info("thread pid: %d\n", pid_nr(pid));
}
return 0;
}
其中比较关键的几个内核函数:
input_pid是从应用程序侧获取到的PID参数;
find_get_pid函数用来根据PID值,获取struct *pid结构体;
pid_task获取已知pid,获取对应的task结构体;
next_thread获取进程的线程task结构体;
pid_nr返回入参为struct pid*,对应的pid值;
最后进行测试环节:
1. 编译内核模块,并安装内核模块(insmod, rmmod)。
2. 编译client测试程序:gcc test.c生成可执行文件a.out
3. ps -ef寻找一个系统正在运行的程序,这里以chrome为例,chrome的进程号为34063
4. sudo ./a.out 34063
5. 使用dmesg输出内核模块打印信息,并使用ps -T -p 34063对比线程打印信息是否一致
上图:
转载地址:http://tqvqa.baihongyu.com/