ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

为什么系统睡不进去?一次讲透 Linux 内核 wakeup_source 唤醒源机制

为什么系统睡不进去?一次讲透 Linux 内核 wakeup_source 唤醒源机制 为什么系统睡不进去一次讲透 Linux 内核 wakeup_source 唤醒源机制【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux凌晨三点你让服务器休眠的机器功耗监控突然飙升翻日志才发现是网卡收到一个入网包就把系统从睡眠边缘拽了回来。问题出在你根本不知道系统里是谁在阻止休眠。Linux 内核本源码树的 wakeup_source 就是干这件事的——任何能阻止系统休眠的组件都要先在这张统计表上登记内核每次入睡前都会核对一遍只要有一个源处于活跃状态休眠当场中止。 debugfs 下三秒定位活跃唤醒源读代码之前先把工具拿在手里。只要 debugfs 已挂载一条命令cat /sys/kernel/debug/wakeup_sources输出会列出当前所有已注册的唤醒源每个源的活跃时长、事件次数、超时次数都在表里。抓现行时盯住活跃时间非零、事件数还在涨的那一行。休眠路径被中止时内核自己也会调用pm_print_active_wakeup_sources()见drivers/base/power/wakeup.c把活跃源打到日志里你直接在 dmesg 里 grepPM:就行。想自己写监控脚本的话内核态可以整表遍历idx wakeup_sources_read_lock(); for_each_wakeup_source(ws) { if (ws-active) pr_info(busy: %s\n, ws-name); } wakeup_sources_read_unlock(idx);for_each_wakeup_source宏定义在include/linux/pm_wakeup.h基于 SRCU 实现遍历时即使有人并发注册或注销也不会踩到悬空指针。wakeup_source 结构体字段按时间、计数、状态三问来读struct wakeup_source的定义也在include/linux/pm_wakeup.h。逐字段念注释容易走神不如先问我想回答什么问题再找对应的字段。它挡了多久last_time记录最近一次被触碰的单调时钟值total_time累计活跃总时长max_time记录单次连续挡休眠的最长纪录start_prevent_time和prevent_sleep_time则专门统计它给自动休眠争取了多少时间。timer配timer_expires构成倒计时事件发生后内核只会再留这个源几秒就自动放手一次中断风暴没法把系统扣住几分钟。它干了多少次这种事event_count累计唤醒事件总数active_count和relax_count分别记激活与释放次数expire_count数超时自动释放发生了几次。wakeup_count最值得盯——它记的是中止休眠的次数这个数字持续上涨基本就是它把系统钉在了唤醒态。它现在活跃吗active是单个位的状态位name与id负责展示和统计表的行标识dev指向对应设备sysfs 里的统计正是挂在它下面wakeirq则把该设备专属的唤醒中断绑定进来。从注册到注销一次完整调用链走读以 eventpollfs/eventpoll.c为例一个唤醒源的完整生命就是四步ws wakeup_source_register(NULL, eventpoll); /* 注册分配 id挂入全局链表 */ __pm_stay_awake(ws); /* 激活置 active开始计时 */ /* 数秒后定时器自动跑 pm_wakeup_timer_fn()或手动 __pm_relax(ws) */ wakeup_source_unregister(ws); /* 注销摘链 */全局链表就住在drivers/base/power/wakeup.c里。eventpoll 并不是一开始就创建唤醒源而是首次需要挡休眠时才懒注册epoll关闭、最后一个带唤醒能力的文件被移除时再注销。用户空间走的是同一条链路kernel/power/wakelock.c里/sys/power/wake_lock里每一个锁背后都是一个同名的 wakeup_sourceGC 线程发现某把锁闲置超过 5 分钟且已释放就顺手注销避免遗留的锁永远压着系统。kernel/power/autosleep.c里的 autosleep 唤醒源也是常驻居民职责是把系统休眠的触发往后延。Documentation/power/ 与三条源码路径这套机制的价值在于把系统为什么睡不进去从猜谜变成查表先 debugfs 定位再按计数归因最后顺着调用链找到驱动里的注册点。Documentation/power/休眠与唤醒的设计说明和 sysfs 接口drivers/base/power/wakeup.c链表、事件计数与 debugfs 导出的实现include/linux/pm_wakeup.hwakeup_source 全部 API 的入口【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表