<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
在内核内存分配时需要注意内存分配睡眠问题,这两天的项目开发过程中遇到了一个死锁问题。该死锁问题实际上也是比较简单的,问题可以参考下图所示。
Context-A是一个IO转发路径,也就是一个IO的过滤层,通过一定的算法规则将IO进行转发处理。在IO转发路径上需要持有一系列的锁资源,保证对临界区的正确访问。在context-A持有锁资源之后,由于内存分配可能会导致上下文睡眠。在内存分配时,由于没有采用GFP_ATOMIC的方法,所以内存资源不够时,会导致内存分配睡眠,同时会触发pdflush线程释放page cache所占用的内存,由于pdflush线程的io同样需要经过context-A,所以,在context-A睡眠时,必然导致pdflush D住。如果没有其它地方能够释放内存,那么,将会导致整个系统发生死锁。对于这个问题,需要对内存分配进行改进,例如可以采用mempool技术可以缓解这个问题(不能从根本上解决)。mempool技术可以预留一些内存空间,当context-A上下文分配内存失败时,可以等待前面的io完成,并且释放内存资源到mempool中。但是,这样的操作必须满足io操作过程中持有的锁与context-A没有冲突。在上图中,Context-B上下文就是用于完成具体io的内核线程,在该内核线程中,需要持有mutext A,由于该信号量已经被context-A持有,所以会导致整个系统发生死锁。针对上述问题,context-A上下文在睡眠时,需要释放mutex A,让context-B能够完成io操作,释放内存,从而可以唤醒context-A继续运行。因此,在context-A中需要采用GFP_ATOMIC的方式进行内存分配,如果内存分配失败,释放持有的锁资源,然后调度睡眠;context-B上下文完成具体的io操作,在该路径上不能再申请内存资源,否则将极易导致系统死锁。
该问题实际上是IO栈上内存分配问题,在io路径上分配内存失败,io无法正常进行,并且会导致page cache所占据的内存空间无法释放,此时会发生io死锁。采用mempool技术可以缓解这个问题,内存资源不仅可以从page cache中获取,而且可以从io完成之后的mempool中获取。但是,如果io栈比较深,一旦io栈中的某个模块将io路径堵住(没有采用mempool或其它原因),那么mempool中的内存将无法回收,直接导致系统死锁。
综上,个人认为在IO栈上分配内存时,一定要小心io死锁问题。
文章评论(0条评论)
登录后参与讨论