在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,如需轉載請自行聯系原作者