刚刚看spinlock和semaphores的使用,有几个问题,想请教一下:
1)中断处理程序(top half)中不能睡眠,是因为哪个原因:
a)没有进程上下文,睡眠之后不能重新调度?
b)中断程序可能关闭了所有中断(使用SA_INTERRUPT),那么再睡眠,就没有抢占点了(中断都进不来,哪里可以schedule()?)
2)kernel thread (ps 中名称类似"[xxx]"),可以睡眠,是因为kernel thread是有上下文,可以调度的,
那么kernel module作为kernel的一部分是否能够睡眠?为什么?如果能,它有上下文么?
3)除了内核线程,内核什么地方可以用semaphores? 即可以睡眠?
呵呵,有点混了,哪位朋友帮我分析一下,非常感谢!
楼主,可能有点把kernel处理和kernel thread处理以及中断处理弄混了。
记住:当程序跑在内核态的时候,只可能处于两种环境:中断上下文或者进程上下文
前者是中断驱动的,后者是用户进程/内核线程驱动的
当内核处于中断驱动部分时,没有上下文,是不能阻塞,睡眠的。这种情况适用于中断处理程序,以及你提到的packet handler,这是网站中断驱动的
当内核处于进程上下文时,是可以阻塞的,包括内核线程,也有自己的上下文。
关于你的问题:
1) a)是主要原因。
2)kernel中是看哪一部分,
有中断上下文的是不允许阻塞的。系统调用部分是可以的,内核线程也是可以的。
*)关于内核模块:以一个驱动程序举例,驱动程序中某部分是中断处理程序,那么处于中断上下文中,就不能睡眠。
如果通过系统调用从用户态到内核态(比如你的设备是字符设备,驱动程序中挂了open/read函数),此时就处于进程上下文,就可以睡眠。
*)关于内核线程:内核线程与普通的进程的区别是,内核线程没有独立的地址空间,它的mm指针被设置为NULL(p->mm = NULL),能访问内核地址空间,一般用于内核后台执行一些操作,从不切换到用户空间去。内核线程只能由其他内核线程创建。可以被调度,也可以被抢占。因为它有自己的task_struct,current宏就指向自己的task_struct,x86里在内核栈的尾端创建thread_info结构,通过计算偏移间接的查找task_struct结构。内核是在创建线程时分配内核栈的。
From http://www.linuxquestions.org/li ... Linux_Kernel_Thread
The 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.
*)关于系统调用:内核在执行系统调用的时候是处于进程上下文中,current指针指向当前任务,即引发系统调用的那个进程。所以,系统调用是可以睡眠的。
若有问题,欢迎讨论。
1) 是因为a), 没有进程上下文是最关键因素。
kernel module, 从module_init指定的函数起, 是运行于insmod这个进程的进程上下文的。 当然,如果你注册了中断、softirq等, 你写的那些处理函数就是运行在中断上下文。
除了irq和softirq,哪里都可以用semaphore
1)ISR中不能睡眠,没别的原因,就是因为中断什么时候来是不可预测的。
本来当前进程运行的好好的,突然来了个中断把当前进程睡眠掉了,而这个中断和当前进程什么关系都没有,有点象走大街上突然被天上掉石头砸一下的感觉。
被中断打断的进程或者线程技术上属于运行态,不是睡眠态。
在Solaris里是TS_ONPROC,在linux相信类似
2)kernel module是什么?是module吗?module无所谓睡眠不睡眠,因为一个module并不是一个进程或者线程。
有的module中,启动了一个内核线程,如usb总线驱动模块中启动了usb_hub_thread线程,那么这个线程倒是可以睡眠,唤醒.......
大部分内核模块和驱动程序都支持多线程,支持锁来同步互斥访问,这些都是可以引起睡眠的,当然睡眠的实体还是所服务的用户线程对应的内核线程。
中断等特殊的上下文在不同的系统上实现有差异,所有的系统上都存在不允许睡眠的特殊上下文,这时,是不允许睡眠的。
3)内核什么地方都可以用semaphores,只要down和up之间不睡眠。
锁的使用取决于上下文的约束条件,在不同系统上是有差异的。特殊的内核上下文里不允许睡眠。[]