pro*_*cci 5 linux x86 scheduler linux-kernel
我编写了一个简单的内核模块,它循环遍历所有进程并提取它们在被取消安排时保存的寄存器(特别是EIP).
如果我没错,我需要的是保存在每个进程的thread_struct中sp0指向的内核堆栈上.这就是我做的:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/sched.h>
int init_module(void){
struct task_struct *t;
struct pt_regs regs;
for_each_process(t){
memcpy(®s, (unsigned long*)(t->thread.sp0-sizeof(struct pt_regs)), sizeof(struct pt_regs));
printk(KERN_INFO "%s eip: %lx\n", t->comm, regs.ip);
}
return 0;
}
void cleanup_module(void){
}
MODULE_LICENSE("GPL");
Run Code Online (Sandbox Code Playgroud)
现在,关于用户级进程的输出似乎是合法的:
[ 3558.322088] bash eip: b770b430
Run Code Online (Sandbox Code Playgroud)
但是我从内核线程得到的所有东西总是0.
[ 3558.322095] kworker/0:0 eip: 0
Run Code Online (Sandbox Code Playgroud)
我不明白.在内核线程方面,内核是否将寄存器保存在其他地方?
它是否与内核抢占有关?
我在3.14-1-486内核上.
先感谢您.
thread.sp0是用户态SP。内核SP是thread.sp(内核 ip 只是thread.ip;这似乎存在于 x86-32 上,但不存在于 x86-64 上)。
上下文切换总是发生在内核中的switch_to(定义之一)宏中,调用 fromcontext_switch调用 from schedule。所以那里使用的IP和SP指向内核空间。
返回用户态时,需要另外一个SP和IP。这就是你正在读的内容。
kworker是在内核内部创建的线程,用于调度不应在中断中完成的事情,并且在它们运行的上下文中没有任何特定进程。因此它没有任何用户层代码,因此它的用户层 SP 和 IP 都为零。你可以查看内核SP和IP,它们应该是非零的(IP应该几乎总是相同的,指向中的相同位置context_switch)