Chinaunix首页 | 论坛 | 博客
  • 博客访问: 410070
  • 博文数量: 33
  • 博客积分: 3050
  • 博客等级: 中校
  • 技术积分: 551
  • 用 户 组: 普通用户
  • 注册时间: 2006-12-22 08:57
文章分类

全部博文(33)

文章存档

2011年(4)

2010年(3)

2009年(5)

2008年(21)

我的朋友

分类: LINUX

2009-09-22 09:31:07

    前一段时间在研发、调试一个virtual scsi host时,遇到了一个锁的问题,这个问题也就是在spinlock的环境中调用了可能睡眠的函数,导致系统崩溃。在此,对这个问题进行一下总结。

       从理论上讲spinlock环境是不能睡眠的,这需要分两种情况进行讨论。

1、  spinlock_irq(关中断)的环境下,如果上下文(context)睡眠,那么极有可能导致Linux系统无法正常调度,并且Linux的心跳中断服务例程都无法调度,所以,很容易导致系统进入崩溃状态。

2、  spinlock(不关中断)的环境下,如果上下文睡眠,那么被调度的上下文极有可能再次访问被锁保护的临界资源,从而导致系统死锁而崩溃。

 

从上面的分析来看,在spinlock保护的范围内是不能睡眠的。如果睡眠,将会导致系统的崩溃。

 

       在编写virtual scsi host代码时,没有注意scsi middle levelqueuecommand函数接口是在spinlock环境下调用的,而在virtual scsi hostqueuecommand函数实现时,引入了generic_make_request函数,该函数是块设备层的转发处理函数,极有可能导致睡眠。

 

generic_make_request函数中,会调用被转发设备的私有make_request函数,如果私有make_request函数调用了kmalloc等内存分配的函数,那么在有些情况下,调用generic_make_request将会进入睡眠状态。所以在测试过程中,如果对virtual scsi host写的数据流较多,那么系统崩溃,如果写的数据流较少,那么系统工作正常,因此,十分不稳定。系统崩溃的信息参考如下:

   

     发现问题之后,对queuecommand函数进行了修改。在scsi host driverqueuecommand函数中只能处理简单的事物,例如将scsi command挂入需要处理的队列,然后唤醒处理队列中的daemon,在daemon的上下文对scsi middle level传下来的scsi command进行处理,例如调用generic_make_request等函数。经过上述方法修改之后,virtual scsi host系统能够稳定运行了~~

阅读(2112) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~