linux内核线程的上下文

时间:2014-08-11 22:09:40

标签: linux linux-kernel x86 scheduler

我编写了一个简单的内核模块,它循环遍历所有进程并提取它们在被取消安排时保存的寄存器(尤其是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: %lx\n", 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内核。

提前谢谢。

1 个答案:

答案 0 :(得分:2)

thread.sp0 userland SP。 内核SP thread.sp(内核ip只是thread.ip;这似乎存在于x86-32上,但不存在于x86-64)。

上下文切换始终发生在switch_to (one of definitions)宏的内核中,从context_switch调用的schedule调用。因此,那里使用的IP和SP指向内核空间。

返回用户空间时,需要另一个SP和IP。这就是你正在阅读的内容。

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

相关问题