内核死锁解除的难点是什么会导致什么

kernel内核锁 完全解析_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
kernel内核锁 完全解析
上传于||文档简介
&&关​于​内​核​锁​得​文​章
阅读已结束,如果下载本文需要使用0下载券
想免费下载更多文档?
定制HR最喜欢的简历
下载文档到电脑,查找使用更方便
还剩21页未读,继续阅读
定制HR最喜欢的简历
你可能喜欢新手园地& & & 硬件问题Linux系统管理Linux网络问题Linux环境编程Linux桌面系统国产LinuxBSD& & & BSD文档中心AIX& & & 新手入门& & & AIX文档中心& & & 资源下载& & & Power高级应用& & & IBM存储AS400Solaris& & & Solaris文档中心HP-UX& & & HP文档中心SCO UNIX& & & SCO文档中心互操作专区IRIXTru64 UNIXMac OS X门户网站运维集群和高可用服务器应用监控和防护虚拟化技术架构设计行业应用和管理服务器及硬件技术& & & 服务器资源下载云计算& & & 云计算文档中心& & & 云计算业界& & & 云计算资源下载存储备份& & & 存储文档中心& & & 存储业界& & & 存储资源下载& & & Symantec技术交流区安全技术网络技术& & & 网络技术文档中心C/C++& & & GUI编程& & & Functional编程内核源码& & & 内核问题移动开发& & & 移动开发技术资料ShellPerlJava& & & Java文档中心PHP& & & php文档中心Python& & & Python文档中心RubyCPU与编译器嵌入式开发驱动开发Web开发VoIP开发技术MySQL& & & MySQL文档中心SybaseOraclePostgreSQLDB2Informix数据仓库与数据挖掘NoSQL技术IT业界新闻与评论IT职业生涯& & & 猎头招聘IT图书与评论& & & CU技术图书大系& & & Linux书友会二手交易下载共享Linux文档专区IT培训与认证& & & 培训交流& & & 认证培训清茶斋投资理财运动地带快乐数码摄影& & & 摄影器材& & & 摄影比赛专区IT爱车族旅游天下站务交流版主会议室博客SNS站务交流区CU活动专区& & & Power活动专区& & & 拍卖交流区频道交流区
白手起家, 积分 66, 距离下一级还需 134 积分
论坛徽章:0
humjb_1983
看了一些资料,觉得在netif_receive_skb前禁止所有中断确实不太合适。但是,不直接调用netif_receive_skb还有什么办法?调用netif_rx可以吗?希望能多多指点
白手起家, 积分 8, 距离下一级还需 192 积分
论坛徽章:0
[ ]&&[&c14f00d8&] ? tcp_connect+0x318/0x490
[ ]&&[&c14e6841&] ? tcp_validate_incoming+0x71/0x340
[ ]&&[&c14f8010&] ? tcp_check_req+0x260/0x4b0
[ ]&&[&c14ecaf7&] ? tcp_rcv_state_process+0x47/0xb80
[ ]&&[&c14f8093&] ? tcp_check_req+0x2e3/0x4b0
[ ]&&[&c14f7ced&] ? tcp_child_process+0x8d/0x150
[ ]&&[&c14f5d8a&] ? tcp_v4_do_rcv+0x2aa/0x3c0
[ ]&&[&c12c149b&] ? do_raw_spin_lock+0x3b/0xf0
[ ]&&[&c159eefd&] ? _raw_spin_lock_nested+0x3d/0x50
[ ]&&[&c14f6f4a&] ? tcp_v4_rcv+0x78a/0xaa0
[ ]&&[&c14d4b8f&] ? ip_local_deliver_finish+0xdf/0x380
[ ]&&[&c14d4aec&] ? ip_local_deliver_finish+0x3c/0x380
[ ]&&[&c14d4fbf&] ? ip_local_deliver+0x7f/0x90
[ ]&&[&c14d46be&] ? ip_rcv_finish+0x16e/0x560
[ ]&&[&c14d522a&] ? ip_rcv+0x25a/0x320
[ ]&&[&c14d4550&] ? inet_del_protocol+0x30/0x30
[ ]&&[&c14a63d2&] ? __netif_receive_skb+0x4c2/0x570
[ ]&&[&c14a5fec&] ? __netif_receive_skb+0xdc/0x570
[ ]&&[&c14a707b&] ? netif_receive_skb+0xcb/0xe0
[ ]&&[&c14a6fcf&] ? netif_receive_skb+0x1f/0xe0
[ ]&&[&f848e33e&] ? SendSkb2Middle+0x162/0x176 [kksfilter]
[ ]&&[&f848f867&] ? KksNatHandler+0x6cd/0x86d [kksfilter]
[ ]&&[&c1095000&] ? futex_wait_requeue_pi+0x1c0/0x380
[ ]&&[&f848fa67&] ? kks_tx+0x60/0x81 [kksfilter]
[ ]&&[&f848fa07&] ? KksNatHandler+0x86d/0x86d [kksfilter]
[ ]&&[&c1079df8&] ? kthread+0x78/0x80
[ ]&&[&c1079d80&] ? __init_kthread_worker+0x60/0x60
[ ]&&[&c15a6d82&] ? kernel_thread_helper+0x6/0x10
这个调用栈是异常的,netif_receive_skb是运行在软中断上下文了,而你这里在kks_tx线程上下文去调用了,在tcp_v4_rcv的时候会去lock_sock获取spinlock,而该线程被硬
中断中断后,会执行软中中断,在软中断上下文最后正常执行到tcp_v4_rcv时去lock_sock获取spinlock获取不到,出现AA锁了。
稍有积蓄, 积分 205, 距离下一级还需 295 积分
论坛徽章:1
netif_receive_skb是运行在软中断上下文了
这句话对么? ksoftirqd不是也会处理软中断么? ksoftirqd应该是内核线程吧? 求解
巨富豪门, 积分 22811, 距离下一级还需 17189 积分
论坛徽章:15
FlankerSky 发表于
回复 10# humjb_1983
看了一些资料,觉得在netif_receive_skb前禁止所有中断确实不太合适。但是,不直接 ...
直接调netif_rx应该也是不合适的,效果不比netif_receive_skb好,不确认你具体要实现怎样的功能~~,如果一定要直接调用netif_receive_skb,可以尝试模仿do_softirq中的处理,在调用前先调用local_bh_disable(),增加软中断计数,防止软中断重入,这样比直接关中断副作用稍小,但关闭时间也不能太长,需要保证~
巨富豪门, 积分 22811, 距离下一级还需 17189 积分
论坛徽章:15
kmindg 发表于
回复 12# jinsdb
确实不对~~,netif_receive_skb的确可以运行于ksoftirq内核线程中。
对于目前讨论的问题,ksoftirq也是调用do_softirq入口,netif_receive_skb不可重入同样是由do_softirq保证的~~
白手起家, 积分 66, 距离下一级还需 134 积分
论坛徽章:0
humjb_1983
目前用的netif_rx还可以,暂时没发现问题,当然还需长时间测试。然后,我再着手实现下你说的那种方法,多谢兄台指点了,帮了我很大忙!感激不尽!
巨富豪门, 积分 22811, 距离下一级还需 17189 积分
论坛徽章:15
FlankerSky
呵呵,不用客气的,多交流学习~~
白手起家, 积分 75, 距离下一级还需 125 积分
论坛徽章:1
在系统原有的do_softirq中,netif_receive_skb 不可重入,不管是在ksoftirqd中运行还是中断里,都不可重入,所以如果你的netif_receive_skb前关闭了中断,应该不是AA死锁
humjb_1983
白手起家, 积分 8, 距离下一级还需 192 积分
论坛徽章:0
to kmindg & humjb_1983
看来大家比较纠结&netif_receive_skb是运行在软中断上下文& 这句话,仔细看一下netif_receive_skb的代码注释吧,linux内核多个内核版本都是清晰了标注了
“This function may only be called from softirq context ”
2270 *& && &netif_receive_skb - process receive buffer from network
2271 *& && &@skb: buffer to process
2273 *& && &netif_receive_skb() is the main receive data processing function.
2274 *& && &It always succeeds. The buffer may be dropped during processing
2275 *& && &for congestion control or by the protocol layers.
2277 *& &&& This function may only be called from softirq context and interrupts
2278 *& && &should be enabled.
2280 *& && &Return values (usually ignored):
2281 *& && &NET_RX_SUCCESS: no congestion
2282 *& && &NET_RX_DROP: packet was dropped
2284int netif_receive_skb(struct sk_buff *skb)
2286& && &&&struct packet_type *ptype, *pt_
2287& && &&&struct net_device *orig_
2288& && &&&struct net_device *null_or_
2289& && &&&int ret = NET_RX_DROP;
2290& && &&&__be16
2292& && &&&if (!skb-&tstamp.tv64)
2293& && && && && & net_timestamp(skb);
2295& && &&&if (skb-&vlan_tci && vlan_hwaccel_do_receive(skb))
2296& && && && && & return NET_RX_SUCCESS;
2298& && &&&/* if we've gotten here through NAPI, check netpoll */
2299& && &&&if (netpoll_receive_skb(skb))
2300& && && && && & return NET_RX_DROP;
netif_receive_skb是在网卡驱动接收到数据包,将skb投递协议栈处理的时候调用的,所以netif_receive_skb是是在网卡软中断上下文调用的,包括后续
的投递的协议栈(如果是TCP包)的ip_rcv,tcp_v4_rcv,tcp_v4_do_rcv,协议栈的处理过程都是在软中断上下文完成,第一眼看到这个调用堆栈居然有人这么调用,
感到蛮诧异的,更没有想到还有的人会认为netif_receive_skb不应该运行在软中断上下文。
ksoftirqd是软中断的辅助处理线程,理论上所有的软中断,都有机会(可能)被ksoftirqd调用执行,是否这样就否认软中断上下文的存在?如果有人不相信netif_receive_skb
是在软中断上下文调用的,在netif_receive_skb函数中加个sleep编个内核试试看。内核提供宏in_softirq()&&可以方便确认当前函数运行在哪一种上下文,为什么函数要明确调用上下文,这和资源的互斥访问相关,资源的互斥访问就得用锁,分不清调用上下文的,也必然不会用锁。
巨富豪门, 积分 22811, 距离下一级还需 17189 积分
论坛徽章:15
jinsdb 发表于
to kmindg & humjb_1983
看来大家比较纠结&netif_receive_skb是运行在软中断上下文& 这句话,仔细看一下 ...
呵呵,误会了吧,我没有否认netif_receive_skb运行在软中断上下文,之前的一处纠结在于:ksoftirq最终也可能调用netif_receive_skb,所以该函数不能完全说“只能运行在软中断上下文”。Linux内核调试技术——进程D状态死锁检测 - 推酷
Linux内核调试技术——进程D状态死锁检测
Linux的进程存在多种状态,如TASK_RUNNING的运行态、EXIT_DEAD的停止态和TASK_INTERRUPTIBLE的接收信号的等待状态等等(可在include/linux/sched.h中查看)。其中有一种状态等待为TASK_UNINTERRUPTIBLE,称为D状态,该种状态下进程不接收信号,只能通过wake_up唤醒。处于这种状态的情况有很多,例如mutex锁就可能会设置进程于该状态,有时候进程在等待某种IO资源就绪时(wait_event机制)会设置进程进入该状态。一般情况下,进程处于该状态的时间不会太久,但若IO设备出现故障或者出现进程死锁等情况,进程就可能长期处于该状态而无法再返回到TASK_RUNNING态。因此,内核为了便于发现这类情况设计出了hung task机制专门用于检测长期处于D状态的进程并发出告警。本文分析内核hung task机制的源码并给出一个示例演示。
一、hung task机制分析
内核在很早的版本中就已经引入了hung task机制,本文以较新的Linux 4.1.15版本源码为例进行分析,代码量并不多,源代码文件为kernel/hung_task.c。
首先给出整体流程框图和设计思想:
图 D状态死锁流程图
其核心思想为创建一个内核监测进程循环监测处于D状态的每一个进程(任务),统计它们在两次检测之间的调度次数,如果发现有任务在两次监测之间没有发生任何的调度则可判断该进程一直处于D状态,很有可能已经死锁,因此触发报警日志打印,输出进程的基本信息,栈回溯以及寄存器保存信息以供内核开发人员定位。
下面详细分析实现方式:
static&int&__init&hung_task_init(void)&&
&&&&atomic_notifier_chain_register(&panic_notifier_list,&&panic_block);&&
&&&&watchdog_task&=&kthread_run(watchdog,&NULL,&&khungtaskd&);&&
&&&&return&0;&&
subsys_initcall(hung_task_init);&&
首先,若在内核配置中启用了该机制,在内核的subsys初始化阶段就会调用hung_task_init()函数启用功能,首先向内核的panic_notifier_list通知链注册回调:
static&struct&notifier_block&panic_block&=&{&&
&&&&.notifier_call&=&hung_task_panic,&&
在内核触发panic时就会调用该hung_task_panic()函数,这个函数的作用稍后再看。继续往下初始化,调用kthread_run()函数创建了一个名为khungtaskd的线程,执行watchdog()函数,立即尝试调度执行。该线程就是专用于检测D状态死锁进程的后台内核线程。
&*&kthread&which&checks&for&tasks&stuck&in&D&state&
static&int&watchdog(void&*dummy)&&
&&&&set_user_nice(current,&0);&&
&&&&for&(&;&;&)&{&&
&&&&&&&&unsigned&long&timeout&=&sysctl_hung_task_timeout_&&
&&&&&&&&while&(schedule_timeout_interruptible(timeout_jiffies(timeout)))&&
&&&&&&&&&&&&timeout&=&sysctl_hung_task_timeout_&&
&&&&&&&&if&(atomic_xchg(&reset_hung_task,&0))&&
&&&&&&&&&&&&&&
&&&&&&&&check_hung_uninterruptible_tasks(timeout);&&
&&&&return&0;&&
本进程首先设置优先级为0,即一般优先级,不影响其他进程。然后进入主循环(每隔timeout时间执行一次),首先让进程睡眠,设置的睡眠时间为
CONFIG_DEFAULT_HUNG_TASK_TIMEOUT,可以通过内核配置选项修改,默认值为120s,睡眠结束被唤醒后判断原子变量标识reset_hung_task,若被置位则跳过本轮监测,同时会清除该标识。该标识通过reset_hung_task_detector()函数设置(目前内核中尚无其他程序使用该接口):
void&reset_hung_task_detector(void)&&
&&&&atomic_set(&reset_hung_task,&1);&&
EXPORT_SYMBOL_GPL(reset_hung_task_detector);&&
接下来循环的最后即为监测函数check_hung_uninterruptible_tasks(),函数入参为监测超时时间。
&*&Check&whether&a&TASK_UNINTERRUPTIBLE&does&not&get&woken&up&for&
&*&a&really&long&time&(120&seconds).&If&that&happens,&print&out&
&*&a&warning.&
static&void&check_hung_uninterruptible_tasks(unsigned&long&timeout)&&
&&&&int&max_count&=&sysctl_hung_task_check_&&
&&&&int&batch_count&=&HUNG_TASK_BATCHING;&&
&&&&struct&task_struct&*g,&*t;&&
&&&&&*&If&the&system&crashed&already&then&all&bets&are&off,&
&&&&&*&do&not&report&extra&hung&tasks:&
&&&&if&(test_taint(TAINT_DIE)&||&did_panic)&&
&&&&&&&&&&
&&&&rcu_read_lock();&&
&&&&for_each_process_thread(g,&t)&{&&
&&&&&&&&if&(!max_count--)&&
&&&&&&&&&&&&goto&&&
&&&&&&&&if&(!--batch_count)&{&&
&&&&&&&&&&&&batch_count&=&HUNG_TASK_BATCHING;&&
&&&&&&&&&&&&if&(!rcu_lock_break(g,&t))&&
&&&&&&&&&&&&&&&&goto&&&
&&&&&&&&}&&
&&&&&&&&/*&use&&==&&to&skip&the&TASK_KILLABLE&tasks&waiting&on&NFS&*/&&
&&&&&&&&if&(t-&state&==&TASK_UNINTERRUPTIBLE)&&
&&&&&&&&&&&&check_hung_task(t,&timeout);&&
&unlock:&&
&&&&rcu_read_unlock();&&
首先检测内核是否已经DIE了或者已经panic了,如果是则表明内核已经crash了,无需再进行监测了,直接返回即可。注意这里的did_panic标识在前文中的panic通知链回调函数中hung_task_panic()置位:
static&int&&
hung_task_panic(struct&notifier_block&*this,&unsigned&long&event,&void&*ptr)&&
&&&&did_panic&=&1;&&
&&&&return&NOTIFY_DONE;&&
接下去若尚无触发内核crash,则进入监测流程并逐一检测内核中的所有进程(任务task),该过程在RCU加锁的状态下进行,因此为了避免在进程较多的情况下加锁时间过长,这里设置了一个batch_count,一次最多检测HUNG_TASK_BATCHING个进程。于此同时用户也可以设定最大的检测个数max_count=sysctl_hung_task_check_count,默认值为最大PID个数PID_MAX_LIMIT(通过sysctl命令设置)。
函数调用for_each_process_thread()函数轮询内核中的所有进程(任务task),仅对状态处于TASK_UNINTERRUPTIBLE状态的进程进行超时判断,调用check_hung_task()函数,入参为task_struct结构和超时时间(120s):
static&void&check_hung_task(struct&task_struct&*t,&unsigned&long&timeout)&&
&&&&unsigned&long&switch_count&=&t-&nvcsw&+&t-&&&
&&&&&*&Ensure&the&task&is&not&frozen.&
&&&&&*&Also,&skip&vfork&and&any&other&user&process&that&freezer&should&skip.&
&&&&if&(unlikely(t-&flags&&&(PF_FROZEN&|&PF_FREEZER_SKIP)))&&
&&&&&&&&&&
&&&&&*&When&a&freshly&created&task&is&scheduled&once,&changes&its&state&to&
&&&&&*&TASK_UNINTERRUPTIBLE&without&having&ever&been&switched&out&once,&it&
&&&&&*&musn't&be&checked.&
&&&&if&(unlikely(!switch_count))&&
&&&&&&&&&&
&&&&if&(switch_count&!=&t-&last_switch_count)&{&&
&&&&&&&&t-&last_switch_count&=&switch_&&
&&&&&&&&&&
&&&&trace_sched_process_hang(t);&&
&&&&if&(!sysctl_hung_task_warnings)&&
&&&&&&&&&&
&&&&if&(sysctl_hung_task_warnings&&&0)&&
&&&&&&&&sysctl_hung_task_warnings--;&&
首先通过t-&nvcsw和t-&nivcsw的计数累加表示进程从创建开始至今的调度次数总和,其中t-&nvcsw表示进程主动放弃CPU的次数,t-&nivcsw表示被强制抢占的次数。随后函数判断几个标识:(1)如果进程被frozen了那就跳过检测;(2)调度次数为0的不检测。
接下来判断从上一次检测时保存的进程调度次数和本次是否相同,若不相同则表明这轮timeout(120s)时间内进程发生了调度,则更新该调度值返回,否则则表明该进程已经有timeout(120s)时间没有得到调度了,一直处于D状态。接下来的trace_sched_process_hang()暂不清楚作用,然后判断sysctl_hung_task_warnings标识,它表示需要触发报警的次数,用户也可以通过sysctl命令配置,默认值为10,即若当前检测的进程一直处于D状态,默认情况下此处每2分钟发出一次告警,一共发出10次,之后不再发出告警。下面来看告警代码:
&*&Ok,&the&task&did&not&get&scheduled&for&more&than&2&minutes,&
&*&complain:&
pr_err(&INFO:&task&%s:%d&blocked&for&more&than&%ld&seconds.\n&,&&
&&&&t-&comm,&t-&pid,&timeout);&&
pr_err(&&&&&&&%s&%s&%.*s\n&,&&
&&&&print_tainted(),&init_utsname()-&release,&&
&&&&(int)strcspn(init_utsname()-&version,&&&&),&&
&&&&init_utsname()-&version);&&
pr_err(&\&echo&0&&&/proc/sys/kernel/hung_task_timeout_secs\&&&&
&&&&&&disables&this&message.\n&);&&
sched_show_task(t);&&
debug_show_held_locks(t);&&
touch_nmi_watchdog();&&
这里会在控制台和日志中打印死锁任务的名称、PID号、超时时间、内核tainted信息、sysinfo、内核栈barktrace以及寄存器信息等。如果开启了debug lock则打印锁占用的情况,并touch nmi_watchdog以防止nmi_watchdog超时(对于我的ARM环境无需考虑nmi_watchdog)。
if&(sysctl_hung_task_panic)&{&&
&&&&trigger_all_cpu_backtrace();&&
&&&&panic(&hung_task:&blocked&tasks&);&&
最后如果设置了sysctl_hung_task_panic标识则直接触发panic(该值可通过内核配置文件配置也可以通过sysctl设置)。
二、示例演示
演示环境:树莓派b(Linux 4.1.15)
1、首先确认内核配置选项以确认开启hung stak机制
Kernel hacking &---&
Debug Lockups and Hangs &---&
[*] Detect Hung Tasks
(120) Default timeout for hung task detection (in seconds)
2、编写测试程序
#include&&&&&
#include&&&&&
#include&&&&&
#include&&&
DEFINE_MUTEX(dlock);&&
static&int&__init&dlock_init(void)&&
&&&&mutex_lock(&dlock);&&
&&&&mutex_lock(&dlock);&&&
&&&&return&0;&&
static&void&__exit&dlock_exit(void)&&&
module_init(dlock_init);&&&&
module_exit(dlock_exit);&&&&
MODULE_LICENSE(&GPL&);&&&&
本示例程序定义了一个mutex锁,然后在模块的init函数中重复加锁,人为造成死锁现象(mutex_lock()函数会调用__mutex_lock_slowpath()将进程设置为TASK_UNINTERRUPTIBLE状态),进程进入D状态后是无法退出的。可以通过ps命令来查看:
root@apple:~# busybox ps
PID & USER & & TIME & COMMAND
521 root & & & 0:00 insmod dlock.ko
然后查看该进程的状态,可见已经进入了D状态
root@apple:~# cat /proc/521/status&
Name: & insmod
State: &D (disk sleep)
Tgid: & 521
Pid: & &521
至此在等待两分钟后调试串口就会输出以下信息,可见每两分钟就会输出一次:
[ &360.625466]& INFO: task insmod:521 blocked for more than 120 seconds.
[ &360.631878] & & & Tainted: G & & & & & O & &4.1.15 #5
[ &360.637042] &echo 0 & /proc/sys/kernel/hung_task_timeout_secs& disables this message.
[ &360.644986] [
] (__schedule) from [
] (schedule+0x40/0xa4)
[ &360.652129] [
] (schedule) from [
] (schedule_preempt_disabled+0x18/0x1c)
[ &360.660570] [
] (schedule_preempt_disabled) from [
] (__mutex_lock_slowpath+0x6c/0xe4)
[ &360.670142] [
] (__mutex_lock_slowpath) from [
] (mutex_lock+0x44/0x48)
[ &360.678432] [
] (mutex_lock) from [
] (dlock_init+0x20/0x2c [dlock])
[ &360.686480] [
] (dlock_init [dlock]) from [
] (do_one_initcall+0x90/0x1e8)
[ &360.694976] [
] (do_one_initcall) from [
] (do_init_module+0x6c/0x1c0)
[ &360.703170] [
] (do_init_module) from [
] (load_module+0xd34)
[ &360.711284] [
] (load_module) from [
] (SyS_init_module+0xdc/0x130)
[ &360.719239] [
] (SyS_init_module) from [
] (ret_fast_syscall+0x0/0x54)
[ &480.725351]& INFO: task insmod:521 blocked for more than 120 seconds.
[ &480.731759] & & & Tainted: G & & & & & O & &4.1.15 #5
[ &480.736917] &echo 0 & /proc/sys/kernel/hung_task_timeout_secs& disables this message.
[ &480.744842] [
] (__schedule) from [
] (schedule+0x40/0xa4)
[ &480.752029] [
] (schedule) from [
] (schedule_preempt_disabled+0x18/0x1c)
[ &480.760479] [
] (schedule_preempt_disabled) from [
] (__mutex_lock_slowpath+0x6c/0xe4)
[ &480.770066] [
] (__mutex_lock_slowpath) from [
] (mutex_lock+0x44/0x48)
[ &480.778363] [
] (mutex_lock) from [
] (dlock_init+0x20/0x2c [dlock])
[ &480.786402] [
] (dlock_init [dlock]) from [
] (do_one_initcall+0x90/0x1e8)
[ &480.794897] [
] (do_one_initcall) from [
] (do_init_module+0x6c/0x1c0)
[ &480.803085] [
] (do_init_module) from [
] (load_module+0xd34)
[ &480.811188] [
] (load_module) from [
] (SyS_init_module+0xdc/0x130)
[ &480.819113] [
] (SyS_init_module) from [
] (ret_fast_syscall+0x0/0x54)
[ &600.825353]& INFO: task insmod:521 blocked for more than 120 seconds.
[ &600.831759] & & & Tainted: G & & & & & O & &4.1.15 #5
[ &600.836916] &echo 0 & /proc/sys/kernel/hung_task_timeout_secs& disables this message.
[ &600.844865] [
] (__schedule) from [
] (schedule+0x40/0xa4)
[ &600.852005] [
] (schedule) from [
] (schedule_preempt_disabled+0x18/0x1c)
[ &600.860445] [
] (schedule_preempt_disabled) from [
] (__mutex_lock_slowpath+0x6c/0xe4)
[ &600.870014] [
] (__mutex_lock_slowpath) from [
] (mutex_lock+0x44/0x48)
[ &600.878303] [
] (mutex_lock) from [
] (dlock_init+0x20/0x2c [dlock])
[ &600.886339] [
] (dlock_init [dlock]) from [
] (do_one_initcall+0x90/0x1e8)
[ &600.894835] [
] (do_one_initcall) from [
] (do_init_module+0x6c/0x1c0)
[ &600.903023] [
] (do_init_module) from [
] (load_module+0xd34)
[ &600.911133] [
] (load_module) from [
] (SyS_init_module+0xdc/0x130)
[ &600.919059] [
] (SyS_init_module) from [
] (ret_fast_syscall+0x0/0x54)
D状态死锁一般在驱动开发的过程中比较常见,且不太容易定位,内核提供这种hung task机制,开发人员只需要将这些输出的定位信息抓取并保留下来就可以快速的进行定位。
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致博客访问: 164992
博文数量: 56
博客积分: 0
博客等级: 民兵
技术积分: 3077
注册时间:
认证徽章:
APP发帖 享双倍积分
IT168企业级官微
微信号:IT168qiye
系统架构师大会
微信号:SACC2013
分类: 嵌入式
内核有spinlock的调试选项,在spinlock被获取时会记录它的owner。
owner是一个struct task_struct指针,在owner里有pid字段,通过pid就能确认是哪个进程持有锁。
自己做了个实验,在同一个函数里两次调用spin_lock,直接锁死,然后用kdb结合gdb来找锁的持有者,可行。
(关于本文中kdb和gdb的使用方法见)
=======================================================================
(1) 确认内核中打开编译选项 CONFIG_DEBUG_SPINLOCK=y
(2) 挂死的时候进kdb
(3) bt看到spinlock调用栈,找到lock地址
0xc2481ebc 0xc1158e24 _raw_spin_lock+0xbd (0xc241a2b0)
0xcxc1246815 _spin_lock+0x22 (0xc241a2b0)
0xc2481efc 0xf8408156 [network]tcp_write_timer+0x7f (0xc241a280)
0xcxc1030bbf run_timer_softirq+0x1c1
0xcxc102b0ac __do_softirq+0xa7
0xcxc102b173 do_softirq+0x26
0xcxc102b256 irq_exit+0x29
0xcxc100e33a smp_apic_timer_interrupt+0x6f (invalid)
0xcxc1003236 apic_timer_interrupt+0x2a (invalid, invalid, invalid)
在这里lock的地址是0xc241a2b0,也就是&lock的值,是函数的参数
(4) 根据偏移量得到lock指向的结构体中的owner字段的内存地址
gdb vmlinux......(gdb) p ((spinlock_t *)0)->owner
Cannot access memory at address 0xc
gdb p/x &0xc+0xc241a2b0
$1 = 0xc241a2bc
(5) 根据偏移量得到owner结构体中的pid字段的内存地址
gdb & p ((struct task_struct *)0)->pid
Cannot access memory at address 0x204
gdb p/x 0x204+0xc241a2bc
$2 = 0xc241a4c0
(6) 在kdb中查看pid的值[0]
kdb> &md 0xc241a4c0
c0 & %...%.....<...<.
所以pid是0x325=805
(7) 在kdb中ps看到pid 805是xxx进程,所以锁的持有者是xxx
阅读(3396) | 评论(1) | 转发(2) |
相关热门文章
给主人留下些什么吧!~~
专家点评:能把自己的项目经验通过代码和易懂的语言写出来与大家共享,真正达到了交流的目的。各个博文之间有连贯性,形成了一个问题的完整的解决方案。一个不错的代码共享交流的经历。(感谢参与原创评选活动,结果即将公布)
请登录后评论。}

我要回帖

更多关于 什么是进程死锁 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信