0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Linux内核实际项目中的死锁

麦辣鸡腿堡 来源:嵌入式Linux充电站 作者:Vincent 2023-09-27 15:24 次阅读

实际项目中的死锁

下面的例子要复杂一些,这是从实际项目中抽取出来的死锁,更具有代表性。

#include < linux/init.h >
#include < linux/module.h >
#include < linux/kernel.h >
#include < linux/kthread.h >
#include < linux/freezer.h >
#include < linux/delay.h >


static DEFINE_MUTEX(mutex_a);
static struct delayed_work delay_task;
static void lockdep_timefunc(unsigned long);
static DEFINE_TIMER(lockdep_timer, lockdep_timefunc, 0, 0);

static void lockdep_timefunc(unsigned long dummy)
{
    schedule_delayed_work(&delay_task, 10);
    mod_timer(&lockdep_timer, jiffies + msecs_to_jiffies(100));
}

static void lockdep_test_work(struct work_struct *work)
{
    mutex_lock(&mutex_a);
    mdelay(300);//处理一些事情,这里用mdelay替代
    mutex_unlock(&mutex_a);
}

static int lockdep_thread(void *nothing)
{
    set_freezable();//清除当前线程标志flags中的PF_NOFREEZE位,表示当前线程能进入挂起或休眠状态。
    set_user_nice(current, 0);
    while(!kthread_should_stop()){
        mdelay(500);//处理一些事情,这里用mdelay替代

        //遇到某些特殊情况,需要取消delay_task
        mutex_lock(&mutex_a);
        cancel_delayed_work_sync(&delay_task);
        mutex_unlock(&mutex_a);
    }

    return 0;
}


static int __init lockdep_test_init(void)
{
    printk("figo:my lockdep module initn");
    
   struct task_struct *lock_thread;

   /*创建一个线程来处理某些事情*/
   lock_thread = kthread_run(lockdep_thread, NULL, "lockdep_test");

   /*创建一个延迟的工作队列*/
   INIT_DELAYED_WORK(&delay_task, lockdep_test_work);

   /*创建一个定时器模拟某些异步事件,如中断等*/
   lockdep_timer.expires = jiffies + msecs_to_jiffies(500);
   add_timer(&lockdep_timer);
 
    return 0;
}


static void __exit lockdep_test_exit(void)
{
  printk("goodbyen");
}

MODULE_LICENSE("GPL");
module_init(lockdep_test_init);
module_exit(lockdep_test_exit);

首先创建一个lockdep_thread内核线程,用于周期性地处理某些事情,然后创建一个名为lockdep_test_worker的工作队列来处理一些类似于中断下半部的延迟操作,最后使用一个定时器来模拟某些异步事件(如中断)。

在lockdep_thread内核线程中,某些特殊情况下常常需要取消工作队列。代码中首先申请了一个mutex_a互斥锁,然后调用cancel_delayed_work_sync()函数取消工作队列。另外,定时器定时地调度工作队列,并在回调函数lockdep_test_worker()函数中申请mutex_a互斥锁。

接下来的函数调用栈显示上述尝试获取mutex_a锁的调用路径。两个路径如下:

(1)内核线程lockdep_thread首先成功获取了mutex_a互斥锁,然后调用cancel_delayed_work_sync()函数取消kworker。注意,cancel_delayed_work_sync()函数会调用flush操作并等待所有的kworker回调函数执行完,然后才会调用mutex_unlock(&mutex_a)释放该锁。

图片

(2)kworker回调函数lockdep_test_worker()首先会尝试获取mutex_a互斥锁。 注意,刚才内核线程lockdep_thread已经获取了mutex_a互斥锁,并且一直在等待当前kworker回调函数执行完,所以死锁发生了

图片

下面是该死锁场景的CPU调用关系:

CPU0                      CPU1
----------------------------------------------------------------
内核线程lockdep_thread
lock(mutex_a)
   cancel_delayed_work_sync()
等待worker执行完成     
                                  delay worker回调函数
                                  lock(mutex_a);尝试获取锁
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 内核
    +关注

    关注

    3

    文章

    1363

    浏览量

    40228
  • Linux
    +关注

    关注

    87

    文章

    11225

    浏览量

    208920
  • 死锁
    +关注

    关注

    0

    文章

    25

    浏览量

    8066
  • 函数
    +关注

    关注

    3

    文章

    4304

    浏览量

    62428
收藏 人收藏

    评论

    相关推荐

    FreeRTOS实时内核实用指南

    FreeRTOS实时内核实用指南
    发表于 09-18 08:02

    关于在实际项目中如何设计软件实现延时?

    在现有的很多入门教程中,程序延时都是使用delay()函数,就是让CPU在空转,什么事情都不做。这个方法在演示实验或者一些简单的应用还可以使用,但是应用到实际的复杂项目中,就不行了。这会消耗大量
    发表于 12-12 16:14

    如何进行嵌入式Linux内核实时化研究?

    的设计原理和RTLinux类似,也是一个实时性应用接口。那我们究竟该如何进行嵌入式Linux内核实时化研究?修改APIC中断函数,将APIC中断和8254中断排序,使得硬实时中断的优先级大于普通8254中断。
    发表于 08-06 07:15

    如何搭建linux内核实验平台

    5.3实验内容——创建Linux内核和文件系统1.实验目的通过移植Linux内核,熟悉嵌入式开发环境的搭建和Linux
    发表于 12-16 08:08

    linux处理机调度与死锁

    linux处理机调度与死锁 掌握处理机的三级调度 掌握作业调度及进程调度的概念 理解调度算法的评价准则 掌握并灵活运用常用的几种作业调度、
    发表于 04-28 14:59 0次下载

    嵌入式Linux内核实时性研究及改进

    分析了嵌入式Linux 存在实时性缺陷的原因,从Linux 调度机制入手提出了可行的改进方案,并详细阐述了代码实现。经测试,改进后的内核实时性能得到很大提高。在嵌入式技术
    发表于 07-30 10:13 8次下载

    嵌入式内核实

    嵌入式内核实
    发表于 01-22 13:58 0次下载

    用crash工具分析Linux内核死锁的一次实战分享

    内核死锁问题一般是读写锁(rw_semaphore)和互斥锁(mutex)引起的,本文主要讲如何通过ramdump+crash工具来分析这类死锁问题。
    的头像 发表于 03-17 09:27 1.6w次阅读
    用crash工具分析<b class='flag-5'>Linux</b><b class='flag-5'>内核</b><b class='flag-5'>死锁</b>的一次实战分享

    最硬核的Linux内核文章

    内核。 拥有超过1300万行的代码,Linux内核是世界上最大的开源项目之一,但是内核是什么,它用于什么? 02 什么是
    的头像 发表于 10-19 17:46 2096次阅读
    最硬核的<b class='flag-5'>Linux</b><b class='flag-5'>内核</b>文章

    快速理解什么是Linux内核以及Linux内核的内容

    01 前言 本文主要讲解什么是Linux内核,以及通过多张图片展示Linux内核的作用与功能,以便于读者能快速理解什么是Linux
    的头像 发表于 10-21 12:02 4258次阅读
    快速理解什么是<b class='flag-5'>Linux</b><b class='flag-5'>内核</b>以及<b class='flag-5'>Linux</b><b class='flag-5'>内核</b>的内容

    如何使用Linux内核实现USB驱动程序框架

    Linux内核提供了完整的USB驱动程序框架。USB总线采用树形结构,在一条总线上只能有唯一的主机设备。 Linux内核从主机和设备两个角度观察USB总线结构。本节介绍
    发表于 11-06 17:59 20次下载
    如何使用<b class='flag-5'>Linux</b><b class='flag-5'>内核实</b>现USB驱动程序框架

    Linux内核的链表数据结构

    Linux内核实现了自己的链表数据结构,它的设计与传统的方式不同,非常巧妙也很通用。
    的头像 发表于 03-24 11:34 815次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>内核</b>的链表数据结构

    Linux内核实现内存管理的基本概念

    本文概述Linux内核实现内存管理的基本概念,在了解基本概念后,逐步展开介绍实现内存管理的相关技术,后面会分多篇进行介绍。
    发表于 06-23 11:56 797次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>内核实</b>现内存管理的基本概念

    Linux内核死锁lockdep功能

    的编程思路,也不可能避免会发生死锁。在Linux内核中,常见的死锁有如下两种: 递归死锁:如在中断延迟操作中使用了锁,和外面的锁构成了递归
    的头像 发表于 09-27 15:13 677次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>内核</b><b class='flag-5'>死锁</b>lockdep功能

    内核实时操作系统的介绍

    内核实时操作系统(Microkernel Real-Time Operating System, μRTOS)是一种专为实时设计的操作系统。它采用微内核架构,以提高系统的可靠性、安全性和可扩展性。以下是关于微内核实时操作系统的
    的头像 发表于 05-11 17:13 470次阅读