樓主,可能有點(diǎn)把kernel處理和kernel thread處理以及中斷處理弄混了。
記?。寒敵绦蚺茉趦群藨B(tài)的時(shí)候,只可能處于兩種環(huán)境:中斷上下文或者進(jìn)程上下文
前者是中斷驅動(dòng)的,后者是用戶(hù)進(jìn)程/內核線(xiàn)程驅動(dòng)的
當內核處于中斷驅動(dòng)部分時(shí),沒(méi)有上下文,是不能阻塞,睡眠的。這種情況適用于中斷處理程序,以及你提到的packet handler,這是網(wǎng)站中斷驅動(dòng)的
當內核處于進(jìn)程上下文時(shí),是可以阻塞的,包括內核線(xiàn)程,也有自己的上下文。
關(guān)于你的問(wèn)題:
1) a)是主要原因。
2)kernel中是看哪一部分,
有中斷上下文的是不允許阻塞的。系統調用部分是可以的,內核線(xiàn)程也是可以的。
*)關(guān)于內核模塊:以一個(gè)驅動(dòng)程序舉例,驅動(dòng)程序中某部分是中斷處理程序,那么處于中斷上下文中,就不能睡眠。
如果通過(guò)系統調用從用戶(hù)態(tài)到內核態(tài)(比如你的設備是字符設備,驅動(dòng)程序中掛了open/read函數),此時(shí)就處于進(jìn)程上下文,就可以睡眠。
*)關(guān)于內核線(xiàn)程:內核線(xiàn)程與普通的進(jìn)程的區別是,內核線(xiàn)程沒(méi)有獨立的地址空間,它的mm指針被設置為NULL(p->mm = NULL),能訪(fǎng)問(wèn)內核地址空間,一般用于內核后臺執行一些操作,從不切換到用戶(hù)空間去。內核線(xiàn)程只能由其他內核線(xiàn)程創(chuàng )建??梢员徽{度,也可以被搶占。因為它有自己的task_struct,current宏就指向自己的task_struct,x86里在內核棧的尾端創(chuàng )建thread_info結構,通過(guò)計算偏移間接的查找task_struct結構。內核是在創(chuàng )建線(xiàn)程時(shí)分配內核棧的。
From
http://www.linuxquestions.org/li ... Linux_Kernel_ThreadThe implementation of kernel_thread() function is available in arch/i386/kernel/process.c. The new task is created via do_fork() system call. A kernel_thread() system call is invoked with a special flag CLONE_KERNEL as an argument. This is defined in include/linux/sched.h as below in
define CLONE_KERNEL (CLONE_FS | CLONE_FILES | CLONE_SIGHAND)
Internally, kernel_thread() passes another two flags CLONE_VM and CLONE_UNTRACED to
do_fork() system call. It means a newly created process will share following resources with its parent process.
File System Information.
File Descriptor Table.
Signal Handlers.
Memory space.
A do_fork() is responsible to create a new task structure on the basis of the
flags passed to it, to set a state of newly created task to TASK_RUNNING and put
this task structure on a runqueue list. It depends upon scheduler when this task
is being picked up for execution.
*)關(guān)于系統調用:內核在執行系統調用的時(shí)候是處于進(jìn)程上下文中,current指針指向當前任務(wù),即引發(fā)系統調用的那個(gè)進(jìn)程。所以,系統調用是可以睡眠的。
若有問(wèn)題,歡迎討論。