进程和底半部(softirq tasklet)间的数据共享的问题,持有锁,为何还要禁止底半部
本文是原「蜗窝讨论区」的历史存档(2017-02-06),来自版块「Linux kernel技术问答」,共 5 帖。讨论区已停止服务,此处仅供查阅。
最近在看LKD,有些疑问来请教一下
当一个进程持有一把自旋锁的时候,内核此时preempt_count非0,也就是禁止抢占,同样书中说,preempt_count非0时,底半部也是禁止的 那么,疑问来了,当进程中持有一把自旋锁时,preempt_count非0,底半部是否自动禁止了? 如果按照上面的推理,底半部被禁止了,那么为何书中说:一般单纯禁止下半部处理是不够的,一般做法是先得到一个锁,再禁止下半部 书中的说法有问题吗?
对于 硬中断——底半部——进程的理解, 我觉得只有硬中断是异步的,随时可能到来打断别人,对于底半部和进程抢占都是同步的,能否把底半部当成一个优先级非常高的进程来理解 触发底半部软中断或者tasklet,它们也是需要等待调度执行,我觉得它们和进程抢占非常像。 软中断执行的时机,相比进程抢占是否是一样的(进程抢占多一个软中断返回时?)
初学linux,上述都是个人简单的理解,有很多不对的地方,请大家帮忙指点一下,谢谢
那么,疑问来了,当进程中持有一把自旋锁时,preempt_count非0,底半部是否自动禁止了? ------------------ 不会,持有自旋锁的时候仅仅是disable了preempt而已,不会disable bottom half。
在QQ群中,你给出了一段LKD中的话,如下: 如果一个进程上下文和一个下半部共享数据,在访问这些数据之前,你需要禁止下半部的处理并得到锁的使用权,一般单纯禁止下半部处理是不够的,一般做法是先得到一个锁,再禁止下半部 -------------------------- 其实你的问题可以归结为在进程上下文和bottom half中共享数据,如何使用锁。 我手边有一本LKD 3rd edition,没有中文版,我猜测这段话对应的英文是157页的Locking between the bottom halves小节,英文原文是: -------------------------- If process context code and a bottom half share data, you need to disable bottom-half processing and obtain a lock before accessing the data. Doing both ensures local and SMP protection and prevents a deadlock.
在UP的场景下,process context不用抢占bottom half的执行,因此,这时候如何保护临界区非常简单:在process context中disable bottom half的处理就OK了。 在SMP场景下,事情就有点复杂了。既然你的问题说道了spin lock,那么就假设本场景中使用的锁就是spin lock了,哈哈。这时候,保护临界区可能采用的方法包括: 1、spin lock only 2、disable bottom half only 3、both 当然,这里只有第三种方法是对的。对于第一种方法,为何是错误的呢?让我们从CPUa上的进程上下文来看,这时候,spinlock仅仅能够保护来自其他cpu上的process context和bottom half的并发访问,对于CPUa的bottom half的抢占却会造成灾难性的后果:dead lock 为何第二种方法是错误的呢?因为这时候无法保护来自其他CPU上bottom half的并发,也无法保护来自其他cpu的process context的并发。 正确的方法是:进程上下文的时候,在进入临界区之前,先disable bottom half,然后获取spinlock。在bottom half中,在进入临界区之前,获取spinlock。
我觉得只有硬中断是异步的,随时可能到来打断别人,对于底半部和进程抢占都是同步的,能否把底半部当成一个优先级非常高的进程来理解 触发底半部软中断或者tasklet,它们也是需要等待调度执行,我觉得它们和进程抢占非常像。 软中断执行的时机,相比进程抢占是否是一样的(进程抢占多一个软中断返回时?) ------------------------------ 我的看法是这样的,对于process context(包括内核线程),interrupt context(包括hard irq 、soft irq)总是异步的,bottom half永远都是优先于process context执行。虽然bottom half(例如tasklet)也是需要等待调度执行,但是它的主人是中断处理而不是调度器。
linuxer 写道: 我觉得只有硬中断是异步的,随时可能到来打断别人,对于底半部和进程抢占都是同步的,能否把底半部当成一个优先级非常高的进程来理解 触发底半部软中断或者tasklet,它们也是需要等待调度执行,我觉得它们和进程抢占非常像。 软中断执行的时机,相比进程抢占是否是一样的(进程抢占多一个软中断返回时?) ------------------------------ 我的看法是这样的,对于process context(包括内核线程),interrupt context(包括hard irq 、soft irq)总是异步的,bottom half永远都是优先于process context执行。虽然bottom half(例如tasklet)也是需要等待调度执行,但是它的主人是中断处理而不是调度器。
收获颇丰,谢谢
