linux读写信号量,读写信号量与实时进程阻塞挂死问题

本文详细分析了一个由于实时进程和读写信号量交互导致的系统阻塞问题。进程H和K在处理内存锁定时,由于实时线程H的优先级和调度问题,导致K进程及H自身的部分线程陷入D状态。问题关键在于H的一个线程H1持有读锁未释放,使得其他进程无法获取锁,最终通过深入内核调用栈找到问题根源。
摘要由CSDN通过智能技术生成

问题终于处理清楚了,如此坑爹的问题,陆陆续续的搞了有近月的时间,现在有时间写一个过程与总结。

问题现象:进程H需要每隔10s发消息给M(类似watchdog的功能),否则就会有功能异常的告警,业务发现了异常的告警,恰好OS监控日志中记录下了进程H当时是D状态,持续了约20s就恢复过来了,然后就没有然后,啥日志也没有。对于这个问题,各位老大进行亲切友好的交谈,双方达成一致意见:放到攻关团队中搞,OS重点投入。

拿到问题的时候,一堆日志里面翻来翻去,除了知道进程H当时D状态(而且进程H拆出了大约70~120个线程),就没有其他有效信息。问题也不重现。本着“没有搞不定的问题,只有不重现的问题”的原则,构造条件准备重现问题。

在增大业务量做压力重现的时候,神奇的事情发生了,H主线程没有发生D状态,另外一个K进程则进入了D状态,最关键的是杀掉H进程后,K进程就恢复正常了,否则就会一直D状态长时间不恢复。看来H进程和K进程是有关系的,那就先入手必现的问题,把K进程的问题搞定。 由于K D状态是必现问题,就可以通过cat /proc/`pidof K`/stack

将进程的调用栈打印出来,根据栈的信息看到看到K进程D状态的过程:(其实proc的栈缺的太多,很多中间过程全靠脑补) K进程调用了mlock用来锁定内存(使其不置换到SWAP上,降低效率),mlock干活之前使用lru_add_drain_all回刷pagevec(pagevec是什么),lru_add_drain_all对每个CPU下发work函数lru_add_drain_per_cpu。int lru_add_drain_all(void)

{

return schedule_on_each_cpu(lru_add_drain_per_cpu);

}

int schedule_on_each_cpu(work_func_t func)

{

int cpu;

struct work_struct __percpu *works;

works = alloc_percpu(struct work_struct);

if (!works)

return -ENOMEM;

get_online_cpus();

//对每个CPU循环

for_each_online_cpu(cpu) {

struct work_struct *work = per_cpu_ptr(works, cpu);

//将func添加到work结构体中

INIT_WORK(work, func);

//将work结构体添加到任务(work)队列里面

schedule_work_on(cpu, work)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值