在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(),然后通过此函数运行线程。
- 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。
- static struct task_struct *kt = NULL;
- 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
注:
我原先编译的,内容是打印SIGSEGV sent和Segment Fault!
seg_fault代码
- int main()
- {
- *(int*)0 = 1;
- return 0;
- }