mmap_sem信号量死锁故障分析

1 故障现象

     该故障出现时,系统提供的调试shell,命令行都不能执行,只有busybox shell (bshell)和魔键(sysrq)可以用。在串口下启动进程就被挂住,进程都处于D状态。

2 故障定位分析

        该故障出现时,只有bshell跟魔键信息可以用,自然而然的就敲了魔键,把内核的调用链打印出来,可是,魔键打印的内核调用链信息很多,很难从调用链的信息中找到出问题的任务。面对收集到的信息,却没有定位的思路,那只能从魔键的函数调用链开始分析,业务进程(app)中的子线程,很多都有类似的函数调用关系,调用关系如下所示:

schedule

__down_read

do_page_fault 

       根据 内核调用链提示的信息,走查代码,发现缺页异常时,获取mmap_sem信号量的时候,没有获取成功,然后主动调用schedule放弃cpu。也就是说app中的多数任务在缺页异常时,获取mmap_sem信号量失败,导致大多数任务都被阻塞在mmap_sem信号量上。从代码上看是请求mmap_sem信号量失败,但是什么情景下会出现这种现象,为什么会出现这种现象暂时不清楚。跟同事讨论,觉得应该是个信号量死锁问题。

      如果是信号量死锁问题,那么当前系统必须满足三个条件:

        1)高优先级任务抢占中优先级任务,并申请mmap_semp信号量

         2)存在中优先级的死循环任务,将低优先级级任务压制,导致低优先级任务得不到调度

        3)存在低优先级级任务占用mmap_semp信号量

        首先,从魔键信息看,大多数任务都处于D状态,并且都是获取mmap_sem信号量失败,也就是说存在许多任务申请mmap_sem信号量,第一个条件成立。

        (确认了第一个条件成立之后,bshell也被阻塞在mmap_sem信号量上,导致不能通过bsell查看必要的信息啦。系统在出问题之后,只要有任务请求获取mmap_sem信号量,就会被挂在获取该信号量上,并且任务状态处于D状态,这也从侧面验证了我们初步定为到信号量死锁的问题,只要一请求该信号量,任务就处于D状态,这也正是魔键信息中大部分app子线程处于D状态的原因。只有请测试部同事帮忙重新复现该问题)

        其次, 第二次出现这个故障的时候,就相对有经验一些,首先起了多个调试shell(kshell),在kshell下执行bshell的命令,防止bshell被阻塞住。然后在kshell下输入shell top命令,查看当前占有cpu的任务。从top执行的结果上看,bcmCNTR.0任务占用了64%左右的cpu,也就是说,大部分时间都是bcmCNTR.0任务在执行。那这个任务就就很值得怀疑,查看该任务的状态:

cat/proc/1198/task/1275/status

我们主要关注任务的调度情况,status结果中voluntary_ctxt_switches表示主动放弃cpu,而nonvoluntary_ctxt_switches表示被动放弃cpu,只有被高优先级任务抢占cpu时该值才会增加。从status结果看,voluntary_ctxt_switches的数值一直都没有变化,说明该任务没有主动放弃过cpu,一直在死循环。nonvoluntary_ctxt_switches的数值有变化,说明只有高优先级的任务可以抢占,低优先级任务不能得到调度。根据以上分析,系统中确实存在死循环任务,也存在比该任务优先级高的任务可以抢占该任务。第二个条件成立。

第三,既然是低优先级级任务被压制,得不到调度,那只要提高低优先级任务的优先级,使其得到调度,释放占用的mmap_sem信号量,那系统应该可以恢复。为了确认这一点,需要关注获取该信号量并且处于R状态的任务,提高该任务的优先级,看环境能否恢复。 从魔键信息上看,跟mmap_sem信号量相关并且处于R状态的任务有三个,MsperfTask、tLowSoftChk和BackRunProc任务。也就是说这三个任务比较可疑。提高MsperfTask任务的实时优先级为80,然后查看任务的状态,发现任务的优先级已经被提高到80,然后查看任务的调用链信息,函数调用链已经不在__down_read中,并且任务状态也处于S状态,而不是之前的R状态。分别提高另外两个任务的优先级之后,整个系统恢复了,说明第三个条件也成立。

      到此为止,这个故障已经定位。该故障主要是bcmCNTR.0任务一直在死循环,导致优先级比bcmCNTR.0任务优先级低的任务得不到调度,从而被饿死。而这些低优先级的任务又占用了mmap_sem信号量,由于得不到及时的调度,该信号量一直得不到释放,最终,导致只要任务获取mmap_sem信号量,就被阻塞到该信号量上,导致信号量死锁。定位了这个问题之后,可以回过头来看看魔键信息中那些我们关注的任务的优先级,确实这些任务的优先级都比bcmCNTR.0任务的优先级低。

总结

    这个故障一出现的时候,面对魔键信息,起初找不到分析问题的切入点,在同事的帮助下,才逐步从魔键信息中找到定位问题的有效信息。对这种只有bshell可以敲的情形,只能从内核的proc文件中查看任务的一些信息,从这些信息中分析故障现象,而proc中有什么信息,可以帮助我们定位问题,对这些我们还是知之甚少,导致出问题时,不能快速定位。

 

 


你可能感兴趣的:(嵌入式故障分析)