当前位置: 首页 > news >正文

Linux WDT 软件分析

linux WDT(看门狗)

看门狗子系统

  • 为什么要实现看门狗子系统?

因为要实现linux底层对WDT 不同硬件的统一控制
在driver部分中最终回去调用watchdog_dev

wdt 代码解析

  • 结构体使用场景和Attention
structxxxwdd_data;// 先定义数据本体wdd=&wdd_data;// 把wdd_data的地址赋值给指针wdd// 场景1:函数内临时使用小结构体 → 用变量voidset_short_config(){structxxxwdd;// 栈上变量,用完就销毁wdd.id=1;wdd.timeout=1000;// 临时使用,无需传递 → 直接用变量更简单}// 场景2:函数间传递配置 → 用指针(避免拷贝)voidset_hardware_config(structxxx*wdd){if(wdd==NULL){// 必加空指针检查!防止踩地址return;}wdd->id=2;wdd->timeout=2000;}// 场景3:动态分配(内核中)→ 用指针structxxx*create_hardware_instance(){// 堆内存分配(内核用kmalloc,用户态用malloc)structxxx*wdd=kmalloc(sizeof(structxxx),GFP_KERNEL);if(wdd==NULL){// 检查分配是否成功returnNULL;}// 初始化指针指向的结构体wdd->id=3;wdd->timeout=3000;returnwdd;// 返回指针,数据不会随函数结束销毁}//attention1.野指针解引用structxxx*wdd;wdd->id=1;// 错误!指针没指向任何有效内存,直接踩地址崩溃//修复:先赋值地址,再加空指针检查//attention2.返回栈变量的指针structxxx*get_wdd(){structxxxwdd;// 栈变量,函数结束就销毁return&wdd;// 返回野指针,后续访问必出问题}//修复:用 kmalloc/malloc 分配堆内存,或让调用方传入指针//attention3.混淆 . 和 ->structxxxwdd;wdd->id=1;// 错误!变量用.,指针用->structxxx*wdd_ptr=&wdd;wdd_ptr.id=1;// 错误!指针用->
  • 在设备树 .dtsi 文件中定义硬件的地址

其中 <0x0 … 对应的地址信息>

  • 进行匹配probe函数

其中的dw_wdt_of_match结构体中的 "snp,dw-wdt"和.dtsi下的匹配

//define the watchdog infostructwatchdog_info{...}//函数操作集合 原厂工程师实现structwatchdog_ops{...}//看门狗管理者 重启系统的函数structwatchdog_governor{...//重启系统之前调用void[*pretimeout]{strcut watchdog_device*wdd}}//实现的对 wdd的watchdog_device封装 作为硬件的启动驱动structwd_wdt{...strcut watchdog_device wdd}
mem=platform_get_resource(pdev,IORESOURCE_MEM,0);//获取 ./dtsi 中的设备地址信息

其中的看门狗信息可由 watchdog_info结构体进行获取赋值 ,代码如下:

  • 获取看门狗信息
wdd->info=&dw_wdt_ident;//设置最小时间wdd->min_timeout=1//设置最大时间wdd->max_hw_heartbeat_ms=dw_wdt_top_in_seconds(dw_wdt,DW_WHT_MAX_TOP)*1000;wdd->parent=dev

设置看门狗参数

  • 看门狗不停止
//需要设置禁止停止时候WDOG_NO_WAY_OUT

该参数的设置需要在linux mkconfig中打开config watchdog nowayoff 选项

  • 看门狗优先级
//设置优先级watchdog_set_restart_priority()

在设置不同 优先级0 ,128, 256 后系统内核会决定用哪个函数来进行重启。

//设置下列函数后watchdog_set_drvdate(wdd,dw_wdt);//可以用下列函数获取结构体watchdog_get_drvdate(wdd,dw_wdt);

看门狗核心代码

  • 看门狗初始化代码
staticint__initwatchdog_init(void){init err;err=watchdog_dev_init();if(err<0)return0;watchdog_deferred_registration();return0;}
  • id 号重分配机制
staticint__initwatchdog_init(void){init err;err=watchdog_dev_init();if(err<0)return0;watchdog_deferred_registration();return0;}
  • 在获取到wdd id 后可以进行调用ida_simple_get(&watchdog_ida, 0, MAX_DOGS, GFP_KERNEL);
  • 初始值为 id为-1 在 id<1 时会进行有一次的id分配

代码如下所示
调用的注册函数后注册判断

获取成功后,进行wdd->id = id 的赋值,再进行注册wdd
如果失败 再获取一次 再注册

看门狗停止

  • 判断系统重启时候的看门狗状态
if(test_bit(WDOG_STOP_ON_REBOOT,&wdd->status)){if(!wdd->ops-stop)pr_warn("watchdog%d:stop_on_reboot not supported\n",wdd->id);else{wdd->reboot_nb.notifier_call=watchdog_reboot_notifier;ret=register_reboot_notifier(&wdd->reboot_nb);if(ret){pr_err("watchdog%d:cannot not register reboot notifier(%d)\n",wdd->id,ret);watchdog_dev_unregister(wdd);ida_simple_remove(&watchdog_ida,id);returnret}}}if(wdd->ops->start){wdd->restart_nb->restart_handler(&wdd->restart_nb);ret=register_restart_handler(&wdd->restart_nb);if(ret)pr_warn("watchdog%d: Cannot register restart handler (%d)\n",wdd->id,ret);}

以上代码是进行对系统重启时候的stop函数存在判断
如果有则注册回调函数 watchdog_reboot_notifier 在启动时进行调用回调函数
如果有(wdd-> ops->start) 则注册,在重置系统时候进行回调函数register_restart_handler

初始化看门狗

  • 进行看门狗设dev_init

采用kthread_create_worker(0, ""watchdogd); 创建一个看门狗内核线程工作线程

/** * watchdog_dev_init - init dev part of watchdog core * * Allocate a range of chardev nodes to use for watchdog devices. * * Return: 0 if successful, error otherwise. */int__initwatchdog_dev_init(void){interr;watchdog_kworker=kthread_run_worker(0,"watchdogd");if(IS_ERR(watchdog_kworker)){pr_err("Failed to create watchdog kworker\n");returnPTR_ERR(watchdog_kworker);}sched_set_fifo(watchdog_kworker->task);err=class_register(&watchdog_class);if(err<0){pr_err("couldn't register class\n");gotoerr_register;}err=alloc_chrdev_region(&watchdog_devt,0,MAX_DOGS,"watchdog");if(err<0){pr_err("watchdog: unable to allocate char dev region\n");gotoerr_alloc;}return0;err_alloc:class_unregister(&watchdog_class);err_register:kthread_destroy_worker(watchdog_kworker);returnerr;}

在watchdog_ping_work 函数中进行喂狗

杂项设备和字符设备

>

杂项设备的注册流程

  • 定义struct miscdevice结构体,指定设备名(如 “watchdog”)、次设备号、file_operations(操作函数集);
  • 设置父设备等关联信息(watchdog_miscdev.parent = wdd->parent);
  • 调用misc_register(&watchdog_miscdev)完成注册,内核自动创建/dev/watchdog设备文件

字符设备的注册流程(传统方式) 要实现一个字符设备驱动,需要手动完成:

申请主设备号(静态指定或动态申请); 定义struct file_operations结构体(实现 open/read/write/ioctl 等操作函数); 调用cdev_init()初始化字符设备结构体; 调用cdev_add()将设备添加到内核; 创建/dev下的设备文件(手动 mknod 或自动创建设备节点)。

存在多个看门狗

存在普通看门狗 (Non-secure WDT (WDT_NS))由linux内核控制
而 安全看门狗 (SecureWDT (WDT_S) )由安全模块控制的

  • old 设备看门狗和新的兼通问题
if(wdd->id==0){old_wd_data=wd_data;watchdog_miscdev.parent=wdd->parent;err=misc_register(&watchdog_miscdev);

misc_register 注册看门狗 misc 设备到内核

  • misc_register():内核提供的 misc 设备注册函数,成功返回 0,失败返回负的错误码(如 - EBUSY 表示设备已被注册)。
  • 注册成功后:
    内核会在/dev/目录下创建看门狗设备文件(通常是/dev/watchdog);
    用户空间程序可通过 open/read/write/ioctl 等系统调用操作看门狗(比如喂狗、设置超时时间);
    该设备会关联到看门狗驱动的操作函数集(如watchdog_miscdev.fops指向的 file_operations)。

  • watchdog_register_pretimeout 中会确定看门狗是否支持超时预处理的功能,若没有则返回0
http://www.jsqmd.com/news/476745/

相关文章:

  • DeerFlow应用场景解析:如何用AI助手搞定学术研究和商业分析
  • C# 简单的异步文件下载器,可用于Unity
  • 【Java从入门到入土】04:循环的尽头是递归?不,是Stream!
  • PPT小白必看:从Word到PPT的5分钟高效转换技巧(附字体版权避坑指南)
  • OpenClaw启动后,web控制面板无法登录,返回信息:Not Found
  • 相机标定及其高阶应用
  • SLDS 自营物流系统:FO 业务全解析
  • IMS网络实战:PCRF与AF的Rx接口消息流程详解(附典型消息示例)
  • 尝试用openclaw完成一个复杂的开发任务(持续更新)
  • cartographer 第一篇(官网2D Pure localization)
  • 瑞芯微开发板固件烧写:从变砖边缘到成功启动的实战指南
  • QGIS实战:5分钟搞定天地图道路数据下载与裁剪(附详细步骤)
  • JavaEE进阶10——SpringMVC小练习
  • 优惠券、满减、折扣同时生效,价格到底怎么算?
  • TI DSP 6678缓存优化全解析:如何用MAR寄存器提升实时性
  • “是我!”庆祝马里奥40年来始终坚持的匠心精神
  • 端口敲门技术深度对比:knockd vs SPA vs SDP,谁更适合你的服务器防护?
  • GIS数据处理必备:ArcMap中北京54与WGS84坐标系的区别与转换技巧
  • 计算机网络的定义和分类
  • EPLAN端子排自定义:从零搭建到高效维护
  • Electron 实战:将用户输入保存到本地文件 —— 基于 `fs.writeFileSync` 与 IPC 的安全写入方案
  • SenseVoice-small-ONNX效果展示:中日韩三国语言混合演讲识别连贯性测试
  • ThinkPad 满分维修评级:进步、妥协与公正性质疑
  • MacBook Air M5:性价比提升与开源支持困境
  • 2024年企业级网络架构实战:跨地域OSPF与BGP混合组网解析
  • 游戏开发必知:透视投影与正交投影的7个核心差异及适用场景
  • pure-ftpd安全配置全指南:从防火墙规则到虚拟用户权限管理
  • 通用文件读写封装:告别重复造轮子,让 C 语言文件操作更高效
  • 个人GPU福音!Kook Zimage真实幻想Turbo在独立游戏美术中的落地实践
  • FFC实战:如何用Fast Fourier Convolution提升图像修复效果(附代码示例)