Linux内核线程背景



我编写了一个简单的内核模块,它循环遍历所有进程并提取它们在取消调度时保存的寄存器(特别是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(&regs, (unsigned long*)(t->thread.sp0-sizeof(struct pt_regs)), sizeof(struct pt_regs));
       printk(KERN_INFO "%s eip: %lxn", t->comm, regs.ip);
    }
    return 0;
}
void cleanup_module(void){
}
MODULE_LICENSE("GPL");

现在,关于用户级进程的输出似乎是合法的:

[ 3558.322088] bash eip: b770b430

但是我从内核线程得到的总是0。

[ 3558.322095] kworker/0:0 eip: 0

我不明白。当涉及到内核线程时,内核是否在其他地方保存寄存器?
是否碰巧与内核抢占有关?

我使用的是3.14-1-486内核。

提前感谢。

thread.sp0userland SP.内核SPthread.sp(内核ip仅为thread.ip);这似乎在x86-32上存在,但在x86-64上不存在)。

上下文切换总是发生在内核中的switch_to(其中一个定义)宏中,从context_switch调用,从schedule调用。所以这里使用的IP和SP指向内核空间。

返回用户地时,需要另一个SP和IP。这就是你正在读的。

kworker是一个内核内部创建的线程,用于调度不应该在中断中完成的事情,并且在它们运行的上下文中没有任何特定的进程。因此,它没有任何用户地代码,因此它的用户地SP和IP都是零。您可以查看内核SP和IP,它们应该是非零的(IP应该几乎总是相同的,指向context_switch中的相同位置)

最新更新