在设计Linux内核程序时,有些小的任务可以直接交给系统的default-workqueue,这样的处理简单方便,受到了很多内核开发者的喜爱。但是,在使用default-workqueue时需要注意内核死锁问题,一不小心就会导致系统死锁。
实际上我是知道上述设计原则的,并且在使用default-workqueue时也考虑了死锁问题,但是最近的设计还是发生了上述问题,真是防不甚防啊!最近遇到的问题可以描述如下图所示:
系统中存在两个work:第一个work(可以称之为IO-work)实现数据的I/O通路,在IO通路中可能会睡眠,当系统资源不够的时候IO通路的work就会睡眠;另一个work(可以称之为timer-work)实现IO通路的控制、处理,该work不会睡眠。考虑到这两个work发生的概率不是很高,所以都采用了Linux系统提供的default-workqueue,在wrok调度时采用schedule_work直接将work派遣到default-workqueue中,让default-workqueue的内核线程进行work的具体处理。通过实际测试发现,上述处理在单核平台上导致了系统死锁问题,当IO-work的处理的IO过多时会导致IO-work的睡眠,由于timer-work无法得到执行,所以IO通路无法打通,IO-work所需要的资源无法得到释放,因此系统死锁。
解决上述死锁的方法比较简单,IO-work和timer-work不能在同一个workqueue中运行,可以为其中的一个work单独创建一个运行上下文(workqueue)。由于多核平台上的default-workqueue会存在多个(与CPU的个数相同),所以上述问题才不会出现。不管怎么样,在设计内核程序时一定要慎用default-workqueue了,该问题的本质是共享上下文问题。
文章评论(0条评论)
登录后参与讨论