在Linux中,有一些进程完全运行在内核空间,比如ksoftirqd等等,这些进程称为内核线程。今天,我们就动手创建一个内核线程。
引言:
如果用户层的进程违规访问内存,内核会发送一个SIGSEGV信号给进程。我们的目标就是,创建一个内核线程,如果发生了段错误,就在控制台打印
"myKthread: Segmentation Fault!!!"
系统环境:
CentOS 5.5 i386 + 2.6.18 源码
设计原理:
(1)使用kthread_create创建线程:
struct task_struct *kthread_create(int (*threadfn)(void *data),
void *data,
const char *namefmt, ...);
这个函数可以像printk一样传入某种格式的线程名
线程创建后,不会马上运行,而是需要将kthread_create() 返回的task_struct指针传给wake_up_process(),然后通过此函数运行线程。
在arch/i386/mm/fault.c最前边添加函数
static int mykthread(void *data)
{
for(;;)
{
printk(KERN_ALERT "myKthread: Segmentation Fault!!!\n");
set_current_state(TASK_INTERRUPTIBLE);
schedule();
}
}
(2)不管是谁访问内存,都会调用到函数do_page_fault,如果是用户层程序,地址合法,就会允许访存,如果违法,就发送SIGSEGV。我们在发送发动信号前唤醒mykthread。
mykthread在第一次段错误时被创建。
在arch/i386/mm/fault.c的do_page_fault函数内添加一个静态变量
static struct task_struct *kt = NULL;
在force_sig_info_fault(SIGSEGV, si_code, address, tsk);这个语句之前,添加下面的内容
if(!kt) //first time
kt = kthread_create(mythread,NULL,"mykthread");
if(!kt)
printk(KERN_ALERT "create mykthread failed!\n");
else
wake_up_process(kt);
else
wake_up_process(kt);
OK.重新编译内核
程序运行结果:
没发生段错误之前
运行程序seg_fault
<a href="http://blog.51cto.com/attachment/201111/100451575.png" target="_blank"></a>
<a href="http://blog.51cto.com/attachment/201111/100511920.png" target="_blank"></a>
注:
我原先编译的,内容是打印SIGSEGV sent和Segment Fault!
seg_fault代码
int main()
*(int*)0 = 1;
return 0;
}
本文转自nxlhero 51CTO博客,原文链接:http://blog.51cto.com/nxlhero/708885,如需转载请自行联系原作者