Linux hibernation 休眠唤醒全链路解析:swap、dev_pm_ops 与内核功耗子系统
1. 从一次休眠唤醒失败说起hibernation 到底在做什么很多人第一次接触 Linux 的 hibernation休眠都是被一个很具体的需求逼出来的笔记本合盖之后希望整机断电第二天打开还能回到原来的工作状态内存里的东西一个不少。这个需求和 suspend挂起最大的区别在于——suspend 只是把大部分硬件关掉内存还在供电维持数据而 hibernation 是把内存里的全部内容写到磁盘上然后整机彻底断电唤醒时再从磁盘读回来。换句话说hibernation 是用磁盘换电的方案代价是慢收益是断电也不丢状态。我在实际项目里遇到过最典型的一个故障设备执行echo disk /sys/power/state之后屏幕黑了但电源指示灯还亮着风扇还在转等了几分钟没有任何反应只能长按电源键强制关机。重启之后dmesg里能看到一堆PM: Cannot find swap device和PM: Cannot get swap writer的报错。这个现象背后其实牵扯到 hibernation 整条链路的几个关键环节swap 空间够不够、swap 设备能不能被内核正确识别、dev_pm_ops的回调有没有按顺序执行、镜像写入过程中有没有设备提前掉线。这篇文章就把这条链路从头到尾梳理一遍重点讲清楚每个阶段内核到底做了什么、哪些地方最容易出问题、出问题之后怎么定位。需要先说明的是hibernation 属于 Linux 内核功耗子系统Power Management里最复杂的一块它同时涉及内存管理、块设备、设备模型、ACPI 等多个子系统。本文不会去逐行读源码而是以一个从业者在调试 hibernation 问题时需要掌握的完整心智模型为目标把流程、关键数据结构、常见坑点讲透。如果你正在做嵌入式 Linux 的电源管理、或者在调试一台机器的休眠唤醒问题这篇内容应该能帮你少走不少弯路。关键词里提到的swap、dev_pm_ops、内核功耗子系统是理解整条链路的三个抓手swap 决定了镜像往哪写、dev_pm_ops决定了设备怎么被冻结和恢复、功耗子系统则提供了sysfs这套用户态接口。下面按执行顺序逐个展开。2. hibernation 的四个阶段freeze、snapshot、write、power down2.1 用户态触发路径与 sysfs 接口触发 hibernation 最直接的方式是往/sys/power/state写diskecho disk /sys/power/state这个写操作会进入内核的state_store()最终调用hibernate()。但在这之前用户态通常还要做几件事确认/sys/power/disk里的模式platform、shutdown、reboot、suspend等确认/sys/power/image_size的限制以及最关键的——确保有可用的 swap。/sys/power/disk这个文件决定了 snapshot 写完之后系统怎么进入低功耗。platform表示交给固件ACPI 的 S4shutdown表示走正常的关机流程reboot表示重启。大多数发行版默认是platform因为唤醒速度最快。但有些机器固件的 S4 实现有问题改成shutdown反而更稳代价是唤醒要走一次完整的开机自检。提示调试阶段建议先把/sys/power/disk设成shutdown排除固件 S4 路径的干扰确认 snapshot 和 restore 本身没问题之后再切回platform。2.2 阶段一冻结用户进程与内核线程hibernation 的第一步和 suspend 一样是 freeze。内核会遍历所有用户态进程把它们逐个冻结freeze_processes()然后冻结可冻结的内核线程freeze_kernel_threads()。冻结的本质是给进程发一个假信号让它们停在安全点上不再持有任何会阻碍 snapshot 的锁。这一步最容易出问题的地方是某个内核线程没有正确实现冻结回调或者某个驱动在 workqueue 里提交了无法被冻结的任务。表现就是echo disk之后卡在Freezing user space processes ...这一行不动等很久之后打印Freezing of tasks failed after 20.00 seconds。遇到这种情况/sys/power/pm_freeze_timeout可以调大超时但根本解法还是找到那个不配合的线程。2.3 阶段二生成内存快照snapshot冻结完成之后内核调用hibernate_preallocate_memory()预分配内存然后进入create_image()。这里的核心动作是把当前内存里的所有页除了标记为nosave的页复制到一个快照里。注意这个快照不是立刻写到磁盘而是先在内存里组织好因为写磁盘的过程中内核自己还要用内存。快照的大小直接决定了需要多大的 swap。理论上需要保存的页数乘以页大小就是镜像的原始大小但实际写入时会做压缩LZO 或 LZ4所以最终占用的 swap 通常比原始内存小。/sys/power/image_size就是用来限制镜像大小的默认值大约是内存的 2/3。如果你把 swap 分得比内存还大那基本不会因为空间不足失败如果 swap 比内存小很多就要靠压缩率来赌了。2.4 阶段三把镜像写入 swap这是整个流程里最重的一步。内核通过 swap writer 把快照数据写到 swap 分区或 swap 文件里。写入过程中所有非 boot 设备会被逐步关闭通过dev_pm_ops的freeze/poweroff回调只留下写 swap 需要的那个块设备。这里有个关键点写 swap 的设备本身不能被关掉。如果 swap 在 SATA 盘上那 SATA 控制器和这块盘必须保持供电直到写完。内核通过dpm_suspend()和dpm_poweroff()两个阶段来控制设备关闭的顺序dev_pm_ops里的回调就是在这两个阶段被调用的。2.5 阶段四进入低功耗与唤醒恢复镜像写完内核执行power_down()根据/sys/power/disk的设置走platform或shutdown。唤醒时bootloader 或固件把控制权交回内核内核检测到 swap 里有有效的 hibernation 镜像就进入 restore 流程重新初始化必要的设备把镜像读回内存然后解冻进程恢复执行。整个 restore 过程对用户来说是透明的——你看到的还是休眠前的桌面但底层其实经历了一次完整的设备重新初始化和内存重建。这也是为什么 hibernation 对驱动的要求比 suspend 更高suspend 只是把设备挂起再恢复而 hibernation 是设备被彻底断电后重新走一遍 probe 流程部分设备或者 restore 回调。3. swap 空间hibernation 的硬门槛与常见误判3.1 swap 分区和 swap 文件的差异swap 可以是独立分区也可以是文件。两者在 hibernation 场景下的行为有细微差别。swap 分区的好处是内核可以直接通过块设备偏移访问不需要经过文件系统层写入路径更短、更可靠。swap 文件则需要内核能定位到文件在磁盘上的物理块这在有日志、有 CoW 的文件系统比如 btrfs上会变得复杂。我个人的经验是如果这台机器的主要用途就是跑 hibernation优先用 swap 分区。如果只能用 swap 文件ext4 上相对稳妥btrfs 上要特别小心因为 btrfs 的 CoW 特性可能导致文件块在写入过程中被重新分配内核拿到的物理块映射就失效了。3.2 到底需要多大的 swap这是被问得最多的问题。一个常见的经验法则是 swap 至少等于内存大小但这个说法过于粗糙。更准确的做法是看/sys/power/image_size的当前值和实际内存使用量。场景建议 swap 大小说明内存 8G日常占用 3G4G 以上压缩后镜像通常 1.5G~2.5G内存 16G日常占用 10G12G 以上高占用场景压缩收益有限内存 32G跑虚拟机建议 32G虚拟机内存页压缩率低嵌入式 512M512M~768M留出压缩和元数据余量判断标准其实很简单/sys/power/image_size默认是内存的 2/3如果你的 swap 小于这个值内核会尝试压缩到 swap 能放下为止压不下就失败。所以最保险的做法是 swap 不小于image_size。3.3 swap 没被识别那些让人抓狂的报错回到开头那个故障。PM: Cannot find swap device这个报错通常意味着内核在 resume 或者 hibernate 时找不到之前用的 swap。原因可能有几种swap 分区在/etc/fstab里用的是 UUID但内核命令行resume参数用的是设备路径两者对不上swap 文件所在的文件系统在 resume 时还没挂载内核无法解析文件位置使用了 LVM 或加密卷resume 时这些层还没初始化。对于 swap 分区正确的做法是在内核命令行里加resume/dev/sdaX或者resumeUUIDxxx并且确保这个参数和实际 swap 一致。对于 swap 文件还需要额外指定resume_offset这个偏移量可以用filefrag -v或者swap-offset工具算出来。注意resume参数写错不会导致系统起不来但会导致唤醒时找不到镜像系统会当成一次冷启动你休眠前的工作全部丢失。这个坑非常隐蔽因为冷启动看起来正常只是数据没了。4. dev_pm_ops设备在休眠链路里的角色分工4.1 dev_pm_ops 的回调集合struct dev_pm_ops是设备驱动向功耗子系统注册回调的入口里面和 hibernation 相关的回调主要有这几组freeze/thaw用于 snapshot 之前的冻结和 snapshot 之后的解冻poweroff/restore用于写镜像之前的关设备和唤醒之后的恢复suspend/resumesuspend 路径用hibernation 的某些阶段也会复用prepare/complete在 freeze 之前和 thaw 之后调用用于做准备工作。这几组回调的执行顺序是有严格规定的。prepare先于freezefreeze先于poweroff。唤醒时顺序反过来restore先于thawthaw先于complete。理解这个顺序是排查某个设备在休眠后状态不对类问题的关键。4.2 为什么有些设备必须实现 restore 而不是 resume这是 hibernation 和 suspend 最大的差异点之一。suspend 时设备只是进入低功耗状态寄存器的值可能还保留着resume回调只需要把设备唤醒即可。但 hibernation 时设备被彻底断电寄存器全部丢失唤醒后设备相当于重新上电restore回调需要把设备重新初始化到休眠前的状态。如果一个驱动只实现了resume没实现restore在 hibernation 唤醒后设备可能处于未初始化状态表现就是网卡不工作、声卡没声音、触摸板失灵。这类问题的排查方法是在dmesg里找唤醒后设备 probe 相关的日志看它走的是哪条路径。4.3 设备关闭顺序与依赖关系dpm_poweroff()会按照设备树的层级从叶子往根关闭dpm_restore()则从根往叶子恢复。这个顺序保证了父设备比如 PCI 控制器在子设备比如挂在它下面的网卡之后关闭、之前恢复。如果驱动之间的依赖关系没有通过设备树正确表达就可能出现父设备已经关了子设备还在访问它的情况表现是写镜像过程中卡死或者报 I/O 错误。这类问题往往需要看dpm_list的实际顺序可以通过打开CONFIG_PM_DEBUG和CONFIG_PM_ADVANCED_DEBUG来打印详细的设备顺序。5. 一次完整的排查链路从卡死到定位5.1 现象记录与初步判断假设你遇到的现象是echo disk /sys/power/state之后终端输出停在PM: Syncing filesystems ... done.然后就没有然后了。这时候不要急着重启先看能不能通过串口或者 SSH 拿到更多信息。如果是本地终端试试AltSysRq组合键SysRq的w可以打印当前所有任务栈SysRq的t可以打印所有线程栈。拿到任务栈之后重点看有没有任务卡在hibernate()相关的调用链上比如create_image、swap_writepage、dpm_poweroff。这一步的目的是判断卡在哪个阶段。5.2 分阶段验证如果卡在 freeze 阶段问题多半在进程冻结。检查/sys/power/pm_freeze_timeout调大之后重试看是否能过。如果还是不行用echo 1 /sys/power/pm_debug_messages打开详细日志看是哪个任务没冻结。如果卡在 snapshot 阶段通常是内存不足或者有页无法被保存。检查dmesg里有没有PM: Not enough free memory之类的报错。这时候可以尝试减小/sys/power/image_size让内核少保存一些页。如果卡在写 swap 阶段问题多半在块设备或者 swap 本身。检查dmesg里有没有 I/O 错误确认 swap 设备在写镜像期间保持可用。5.3 用 ftrace 追踪关键函数对于更隐蔽的问题ftrace 是利器。可以这样追踪 hibernation 相关的函数调用cd /sys/kernel/debug/tracing echo function current_tracer echo hibernate set_ftrace_filter echo 1 tracing_on echo disk /sys/power/state # 唤醒后 cat trace这样能看到hibernate路径下所有函数的调用顺序和耗时快速定位到卡在哪个函数。如果hibernate本身没被追踪到说明问题发生在更早的阶段比如state_store或者freeze_processes。5.4 常见报错与对应处理报错信息可能原因处理方向Cannot find swap deviceresume 参数错误或 swap 未激活检查内核命令行和 fstabNot enough free memoryswap 太小或内存占用过高扩大 swap 或减小 image_sizeFreezing of tasks failed某进程/线程无法冻结查任务栈定位PM: Image not found镜像写入失败或 resume 参数错检查写入日志和 resume 配置Restarting tasks ... done后设备异常驱动 restore 回调缺失检查驱动 dev_pm_ops6. 嵌入式场景下的特殊考量6.1 内存受限时的策略嵌入式设备内存通常很小512M 甚至 256M 很常见。这种场景下 hibernation 的挑战在于swap 空间可能比内存还小压缩率成为关键。LZ4 比 LZO 快但压缩率略低如果 CPU 性能不是瓶颈选 LZO 能省更多空间。另一个策略是减少需要保存的页。内核提供了nosave内存区域的概念一些明确不需要保存的内存比如 DMA 缓冲区、固件保留区可以标记为nosave这样镜像会小很多。具体做法是在设备树或者内核启动参数里配置。6.2 唤醒源配置嵌入式设备唤醒通常靠特定的中断源比如按键、RTC、USB 插入。这些唤醒源需要在设备树里正确配置并且对应的驱动要支持wakeup能力。如果唤醒源没配好设备休眠后就叫不醒只能断电重启。配置唤醒源的通用方法是往/sys/devices/.../power/wakeup写enabled但嵌入式场景下更推荐在设备树里静态配置避免依赖用户态脚本。6.3 与 suspend 的取舍不是所有场景都需要 hibernation。如果设备只是短时间不用suspend 更快、对驱动要求更低。只有当需要长时间断电、或者电池电量极低需要彻底断电保数据时hibernation 才有价值。在嵌入式项目里我通常会把两者都配上让用户态根据电量和使用场景动态选择。7. 几个我踩过的坑和对应的经验第一个坑是 swap 文件放在 btrfs 上。当时图省事直接在 btrfs 根分区建了个 swap 文件swapon正常suspend 也正常但 hibernation 写入到一半就报 I/O 错误。后来查资料才知道 btrfs 的 CoW 会导致文件块在写入过程中被重新分配内核预取的物理块映射失效。换成 ext4 的独立分区之后问题消失。这个坑的教训是hibernation 对 swap 的底层稳定性要求比普通 swap 高得多。第二个坑是resume参数用了设备路径但系统里磁盘顺序会变。有一次机器上插了 U 盘重启后/dev/sda变成了 U 盘原来的系统盘变成/dev/sdb结果resume/dev/sda2指向了错误的位置唤醒时找不到镜像直接冷启动。后来统一改成resumeUUIDxxx问题再没出现过。UUID 不随设备顺序变化这是它比设备路径可靠的根本原因。第三个坑是某个 USB 控制器的驱动没实现restore回调。现象是 hibernation 唤醒后 USB 键盘鼠标全部失灵但系统本身是活的能通过网络 SSH 进去。查驱动代码发现它只实现了resume而 hibernation 唤醒走的是restore路径回调为空导致控制器没被重新初始化。补上restore回调之后问题解决。这个案例说明调试 hibernation 问题时不能只看设备有没有被挂起还要看唤醒后有没有被正确恢复。第四个坑和image_size有关。有一次在一台 16G 内存的机器上swap 只分了 8G日常内存占用 6G 左右按理说够用。但那次刚好开了几个虚拟机内存占用冲到 12Ghibernation 直接失败。后来把image_size从默认的 2/3 调小到 8G让内核在 snapshot 阶段就主动丢弃一些可回收页虽然丢了一些缓存但至少能成功休眠。这个取舍在内存紧张时很实用。8. 调试工具与配置清单把常用的调试手段和配置项整理成一张表方便排查时对照工具/配置路径或命令用途power state/sys/power/state触发 suspend/hibernatedisk mode/sys/power/disk选择 platform/shutdownimage size/sys/power/image_size限制镜像大小freeze timeout/sys/power/pm_freeze_timeout调整冻结超时pm debug/sys/power/pm_debug_messages打开详细日志ftrace/sys/kernel/debug/tracing追踪函数调用SysRqAltSysRqw/t打印任务栈resume 参数内核命令行resume指定 swap 位置swap 状态swapon --show、/proc/swaps确认 swap 可用配置层面建议在/etc/default/grub里显式写上resumeUUIDxxx然后update-grub生效。对于 swap 文件还要加上resume_offset。这两个参数是 hibernation 能否正常唤醒的决定性因素比任何驱动配置都重要。最后分享一个我常用的验证方法配置好之后先手动执行一次systemctl hibernate等机器完全断电后重新开机看能否回到休眠前的状态。如果能再测试合盖休眠、定时休眠等场景。每次改动 swap 或内核参数之后都要重新验证一遍因为这类配置的错误往往不会立刻暴露而是在某次唤醒时才突然出现。

相关新闻

OPNET QoS仿真实践:队列调度、DiffServ标记与参数调优解析

OPNET QoS仿真实践:队列调度、DiffServ标记与参数调优解析

简介:面向计算机网络仿真学习者的OPNET 14.5 QoS作业资源包,内容对应《计算机网络仿真OPNET实用指南》中的“提供服务质量支持”章节,覆盖FIFO、RED、WRED、WFQ、WFQ-LLQ五种队列调度与拥塞避免机制。压缩包共102个文件,以工程文件…

2026/10/15 21:17:56 阅读更多 →
本地部署私有化智能问答助理:从模型选型到知识库调参的完整指南

本地部署私有化智能问答助理:从模型选型到知识库调参的完整指南

简介:面向需要本地化部署智能问答服务的开发者,这套示例项目基于Gradio构建交互界面,并整合FAISS与Sentence-Transformers实现文档上传、向量检索与自动应答,适用于知识库查询、企业内部问答等场景。压缩包共18个文件,…

2026/10/15 9:26:03 阅读更多 →
Windsurf Cascade迁移实战:Provider路由从gpt-6-sol到gpt-6.1-sol

Windsurf Cascade迁移实战:Provider路由从gpt-6-sol到gpt-6.1-sol

Windsurf 后端把模型从 gpt-6-sol 升级到 gpt-6.1-sol 之后,最折磨人的往往不是模型本身,而是 Cascade 里那些对不上的 provider 路由。你明明把模型名改成了 gpt-6.1-sol,Cascade 却照样报“模型不支持”、路由找不到 API key,甚…

2026/10/13 12:19:17 阅读更多 →

最新新闻

目标检测后处理:IOU与NMS从原理到工程化实战

目标检测后处理:IOU与NMS从原理到工程化实战

做目标检测的朋友都知道,模型跑通只是第一步,真正决定最终效果上限的,往往是两段看起来很不起眼的计算:IOU与NMS。IOU负责衡量两个检测框到底重合成什么样,NMS负责把同一目标周围那些重复的、多出来的框“压”下去。无…

2026/10/15 21:19:30 阅读更多 →
Docker Compose部署WeKnora:从环境规划到上线运维的完整指南

Docker Compose部署WeKnora:从环境规划到上线运维的完整指南

我第一次帮人部署WeKnora时,对方给的服务器上已经跑了七八个业务,系统里Python和Node版本乱成一锅粥。当时我们几乎没有犹豫,直接用Docker部署WeKnora,把服务、数据库、缓存全部容器化隔离,不到半天就正常跑起来&#…

2026/10/15 21:19:30 阅读更多 →
500k长上下文实战:Codex与ChatGPT Work工作流重构指南

500k长上下文实战:Codex与ChatGPT Work工作流重构指南

直接说结论:从16k到128k,再到200k,然后跳到500k,这个数字看着只是“变大了”,但真正用起来你会发现,这根本不是同一个物种。我花了几个晚上把 Codex 和 ChatGPT Work 里的长上下文工作流重新跑了一遍&#…

2026/10/15 21:19:30 阅读更多 →
TxBENCH硬盘检测全攻略:性能测试、SMART健康与翻新盘识别

TxBENCH硬盘检测全攻略:性能测试、SMART健康与翻新盘识别

简介:TxBENCH 电脑及硬盘检测工具是一套面向电脑 DIY 爱好者、硬件评测人员及普通用户的 SSD 检测资源,覆盖基础读写测试、大文件拷入高级测试、安全擦除与驱动信息查看等核心功能,可帮助判断硬盘性能是否达到预期,并兼顾旧盘数据…

2026/10/15 21:19:30 阅读更多 →
Halcon+MFC工业模板匹配实战:从环境搭建到产线鲁棒部署

Halcon+MFC工业模板匹配实战:从环境搭建到产线鲁棒部署

简介:本资源是一个基于Halcon与MFC联合开发的模板匹配实战Demo,面向具备C基础和图像处理入门经验的Windows桌面应用开发者,解决工业视觉中目标定位、多尺度形状识别与灰度匹配等典型需求。项目完整实现形状匹配、形状缩放匹配及灰度匹配三类核…

2026/10/15 21:19:30 阅读更多 →
MySQL零基础入门:从安装到增删改查实战教程

MySQL零基础入门:从安装到增删改查实战教程

写这篇教程的初衷很简单——我见过太多人一上来就啃官方文档,结果被术语劝退;也见过不少人背了一堆命令,却连数据库都没装好。MySQL作为最流行的开源关系型数据库,它其实没有传说中那么难,难的是没人告诉你第一步该干嘛…

2026/10/15 21:18:29 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/15 16:18:54 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/15 19:41:51 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/15 13:48:15 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 9:49:14 阅读更多 →