高通Camx架构调试实操:UMD/KMD日志开启与离线合并
早些年做高通平台Camera调试最耗时的往往不是解问题本身而是在一堆堆不明所以的日志里找方向。Log打少了现场复现不充分问题就越查越糊涂Log开多了又密到让人看不进去反而把关键点淹没掉。更麻烦的是用户态和内核态的日志如果不在一起一个问题要来回横跳两个终端时间戳还对不上等整明白流程半天已经没了。这篇内容主要围绕高通Camx架构下的调试基本功展开UMD用户态驱动层日志怎么开、KMD内核态驱动层日志怎么开、Camx的图像Dump怎么做最后分享一个我用过的离线日志合成脚本思路能把用户态和内核态的log按时间顺序合并到一起。做Camera驱动、系统集成或者图像效果调试的朋友应该都能用得上。1. 先搞清楚要打哪层日志Camx架构的UMD与KMD1.1 Camx在高通Camera栈里的位置高通平台从SM8250骁龙865这一代开始就把老的mm-camera架构逐步往CamxCamera eXtension上迁移。到现在Camx已经是高通主流平台的标准Camera框架上接Android Camera HAL层下连内核的Camera驱动。日常调试时我们通常把整个链路拆成三层来看App与Camera Framework、HAL与Camx CoreUMD层、内核Camera驱动KMD层。Camx Core用户态这部分实际会加载libcamxhwl、libcamxswl这类库还会配合Chi-CDKCamera Hardware Interface去做node的定制编排。KMD层则是Camera Subsystem的内核驱动部分包括cam_sync、cam_req_mgr、cam_isp、cam_sensor、cam_cpas这些模块负责更底层的中断、寄存器操作和sensor的I2C配置。单看某一层日志往往只能看到问题的一半。比如预览黑屏问题可能出在sensor上下电、也可能出在ISP的streamon失败、还可能出在HAL侧的pipeline没有真正start。所以我一般会建议调试开始前先决定要开哪几层日志而不是一口气全开。1.2 UMD与KMD分工为什么两侧日志都要开Camx里有个非常核心的设计理念叫“Pipeline-based”底层通过Request机制驱动sensor、ISP、IPE等节点。用户态Camx Core负责构建pipeline、分发request、处理HAL回调内核态则负责硬件调度、中断处理、buffer管理。以一条出图链路为例HAL发起processCaptureRequestCamx Core会给pipeline的各node填好配置通过IOCTL下发到KMDKMD的cam_req_mgr收到后登记request再逐级调度给ISP硬件。如果用户态日志显示request已经发出去了但内核日志里没看到对应的request arrival那基本可以确认问题出在KMD入口之前。反过来如果内核日志已经出图完成但HAL侧迟迟收不到回调那大概率是UMD的event分发或者buffer状态机卡住了。所以调试时我习惯把UMD Log和KMD Log一起开哪怕先不分析内容也要保证时间戳能对齐。这里需要提一下高通在车规平台上会把Camx和安全相关的补丁合在一起内核版本也会跟着CAF Kernel走不同平台Log开关的位置和格式会有差异但核心思路不会变。1.3 日志链路整体策略开日志之前先想清楚两个问题问题大概在哪个模块可复现性怎么样如果问题可稳定复现优先开目标模块的详细日志周边模块保持默认级别。如果问题像幽灵一样偶发那建议直接开全链路日志并且在复现后立刻抓取。全开日志会对帧率有一点影响特别是ISP统计相关的日志打多了会延长出图耗时复现出来的现象可能和用户崩溃时的现象不完全一样这个要有心理准备。2. UMD Log开启实操从环境变量到CamxOverrides2.1 UMD日志的打印路径Camx UMD层打印日志底层走的是系统Log机制。Android平台上Camx相关日志会打到logcat里TAG一般是CamX、ChiNode、CHICONTEXT这些。用adb logcat直接抓也能看到但因为Camx日志量实在太大了系统通常会把大部分日志打到独立的文件节点再通过属性开关控制。常用的获取方式adb shell logcat -d -v threadtime | grep -E CamX|ChiNode|Camx camx_umd.log如果平台上有独立的Camx log文件路径一般在/vendor/logs或者/data/vendor/camera这类文件是Camx侧的转储日志比logcat里的内容更完整字段也更规整。2.2 camxoverridesettings.txt 关键配置项Camx提供了一套运行时配置机制集中在camxoverridesettings.txt文件里平时就放在vendor/etc/camera目录下。这个文件本质上是键值对可以配置很多调试开关和内部参数。需要先确认相机进程有没有读这个文件有些平台会用generateoverride脚本把配置合到/vendor/etc/camera/camxoverridesettings.txt如果改动没生效大概率就是文件路径不对或者权限不对。下面是我常用的几个Log相关的配置配置项作用推荐值camxLoggingEnable总开关让Camx内部输出日志TRUEcamxLoggingMode日志模式1表示输出到logcat2表示输出到文件3表示都输出3camxLoggingLevel全局日志级别0为error1为warning2为info3为debug2camxLoggingMask按模块bitmask控制可按需组合0xFFFFFFFFCamxLogDumpIspISP相关dump节点开关TRUE实际配置时不要上来就全开这会非常吵而且影响性能。建议按模块拆。调试sensor对焦时就开sensor和AF相关的配置调试3A统计时就开stats和AFDump相关的配置。2.3 配置完成后如何验证改完配置文件后重启camearaProvider进程。adb shell pkill -f camera.provider adb shell pkill -f cameraserver然后重新打开相机App观察logcat里CamX的日志是否明显增多。如果增加量不明显先用一个简单的Exposure补偿命令确认配置是否被加载adb shell getprop | grep -i camx如果这个属性没有输出对应调试属性那可能是Camx native层没读取overrides文件需要把配置放到init加载完的路径下确保属性权限正确。我在某些平台上踩过坑改完配置总不生效折腾半天发现是文件放到了/vendor/etc/camera/下但平台实际读取的是/odm/etc/camera/。所以拿到一个新平台第一件事就是确认camxoverridesettings.txt默认路径。3. KMD Log开启实操内核侧到底怎么打开3.1 KMD日志节点与动态调试KMD层的高通Camera驱动里各个模块都有自己的打印默认情况下有很多是关闭的需要打开动态调试开关。内核日志查看基础命令adb shell dmesg kmd.log adb shell cat /proc/kmsg kmd.log模块化的打印推荐用内核的dynamic_debug机制可以在运行时打开某个文件的pr_debug不需要重新编译内核。以cam_isp模块为例adb shell echo file cam_isp.c p /sys/kernel/debug/dynamic_debug/control如果debugfs没有挂载需要先挂载adb shell mount -t debugfs none /sys/kernel/debug打开之后cam_isp.c里所有pr_debug的日志就会输出到dmesg里。内核对Camera模块驱动的文件名通常是cam_xxx.c对应模块cam_req_mgr.c、cam_isp.c、cam_sensor.c、cam_sync.c、cam_cpas.c。3.2 使能trace event打点比dynamic_debug更强大的是高通Camera驱动里的trace event。这套机制在内核的tracefs里挂了一组Camera相关的事件节点采集成perfetto或者trace文件后可以做很精细的时间线分析。开启trace eventadb shell echo 0 /sys/kernel/debug/tracing/tracing_on adb shell echo /sys/kernel/debug/tracing/trace adb shell echo 1 /sys/kernel/debug/tracing/events/camera/enable adb shell echo 1 /sys/kernel/debug/tracing/tracing_on复现问题后停止抓取adb shell echo 0 /sys/kernel/debug/tracing/tracing_on adb shell cat /sys/kernel/debug/tracing/trace trace_camera.txt这套trace几乎能钩到每次request从UMD下来的完整流转路径包括哪个时刻进了cam_req_mgr、哪个时刻ISP开始处理、哪个时刻产生sof/ef。排查帧率波动、出图时序问题时作用非常突出。3.3 高级技巧panic与超时场景的last_kmsg系统卡死或者camera进程崩溃时往往来不及手动抓dmesg。这种情况要看last_kmsg或者pstore。部分平台会把上次启动时的内核日志保存在/sys/fs/pstore/console-ramoops重启后还能读出来adb shell cat /sys/fs/pstore/console-ramoops last_kmsg_pstore.txt还有一种常见做法是打开高通平台的t32抓取内核log不过这项操作对大多数调试场景来说开销过高实际生产环境不建议直接上。需要先确认平台是否支持pstore如果支持能省下很多反复复现的时间。4. Dump图像让平台把数据吐出来4.1 图像dump的应用场景与数据链路Log再全也只是间接反映状态。遇到图像效果类问题、ISP的统计值异常问题、sensor输出异常问题时直接用dump图说话会更有说服力。Camx的dumplog分成几个维度Sensor raw dump直接dump sensor输出的raw图检查sensor出图是否正常ISP统计dumpdump AF、AEC、AWB等统计信息用来分析3A收敛过程YUV/RGB中间图dump在ISP处理链路的不同node上dump出图定位问题发生在哪个节点raw dump的数据量很大一片raw图动辄几十MB调试前要确认sensor分辨率同时注意dump时间不要过长免得存储空间被写满。4.2 ChiDump与各个节点配置Camx的Dump开关通常也在camxoverridesettings.txt里配置。比如开启raw dump可以配置配置项作用推荐值ChiDump总开关控制用户态dump节点数据TRUEChiDumpModedump模式按7位bit控制哪些node对应节点位的值ChiDumpNodeMask需要dump的node的mask按node填入ChiDumpPathdump文件的输出目录/data/vendor/cameraAfDumpAF统计dump开关TRUEAecDumpAEC统计dump开关TRUE这里的ChiDumpMode和ChiDumpNodeMask需要对照Chi节点ID去配置。最直观的办法是先把Mode设成全F把NodeMask也设成全Fdump一轮看看有哪些目录和文件产生再根据文件名反推节点ID缩小范围。需要提醒的是Camx的dump路径默认是/data/vendor/camera如果dumpserver进程没有权限写这个目录dump会静默失败。遇到dump不出来第一步检查这个目录是否存在、以及目录权限。4.3 dump出来怎么看dump出来的文件一般有两种格式纯二进制raw文件和带头部的dump文件。raw文件可以用Python的numpy加载也可以直接用高通的QPST工具离线解析。我习惯的做法是先用Python脚本解析raw文件看文件名里的信息一个常见的dump文件名格式大概是IMG_20250101_120000_[PIPELINE_ID]_[NODE_ID]_[FRAME_ID].raw文件名携带的信息包括时间、pipeline id、node id、frame id这正好能和log里的时间戳对应上。解析raw文件时如果尺寸不对可以先查看文件大小通过像素格式和分辨率反推是否正确。例如一个1920x1080的NV12图每帧大小应该约等于192010803/2。对于3A统计dump出来的文件一般是txt或bin里面记录的是图像各个区域的亮度均值、对焦评价值等。分析这类文件时可以按frame id逐条绘制曲线这样能很直观看到AEC收敛过程有没有来回震荡。5. 离线Log合成脚本让用户态与内核态同屏5.1 为什么要离线合成Log抓是抓到了但分析仍然费劲。UMD的logcat是threadtime格式每一行都带进程号、线程号、时间戳内核的dmesg则是另一个时间体系两个文件的时间戳参照不一样直接对比基本没法用。我遇到过不止一次用户态log显示某个request已经返回了内核侧同一时间的log却显示硬件还没有启动查了一圈发现两个时间轴差了十几秒。把两侧日志合到一起本质上做一件事把两边的日志时间统一到一个坐标系里。时间对齐完成后所有日志都按顺序排列可以直接从日志流上还原一帧从HAL下发到ISP出图的完整链路。5.2 脚本设计思路与代码我写过一个Python脚本思路不复杂读取UMD日志文件解析每行开头的日期时间logcat默认“MM-DD HH:mm:ss.mmm”threadtime格式里还带进程号。读取KMD日志文件解析dmesg时间一般是“秒.毫秒”或者带时间戳需要结合开机时间换算。人工选择一个同步锚点比如系统开机时刻或UMD和KMD共同打印的一条进程启动日志。统一成绝对时间戳后排序输出。锚点的选择最关键。如果平台能在启动时同步记录开机时刻那直接用systime换算dmesg里的时间加开机时刻offset即可。如果拿不到准确开机时间就找一条两侧都存在的日志例如“camx_initialize”或“CamxCreate”日志把它们视作同一时刻再反推偏移量。下面是脚本的核心示例供参考#!/usr/bin/env python3 # -*- coding: utf-8 -*- Offline Log Merger for Camx UMD/KMD logs 用法: python3 log_merger.py --umd umd.log --kmd kmd.log --boot-time 2025-01-01 12:00:00.000 import argparse import re from datetime import datetime, timedelta UMD_TIME_RE re.compile(r^(\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3})) KMD_TIME_RE re.compile(r^\[\s*(\d\.\d)\]) def parse_umd_time(line, year): m UMD_TIME_RE.match(line) if not m: return None, line dt datetime.strptime(f{year}-{m.group(1)}, %Y-%m-%d %H:%M:%S.%f) return dt, line[m.end():].strip() def parse_kmd_time(line, boot_time): m KMD_TIME_RE.match(line) if not m: return None, line seconds float(m.group(1)) dt boot_time timedelta(secondsseconds) return dt, line[m.end():].strip() def main(): ap argparse.ArgumentParser() ap.add_argument(--umd, requiredTrue) ap.add_argument(--kmd, requiredTrue) ap.add_argument(--boot-time, requiredTrue) ap.add_argument(--year, default2025) args ap.parse_args() boot_time datetime.strptime(args.boot_time, %Y-%m-%d %H:%M:%S.%f) entries [] with open(args.umd, r, errorsignore) as f: for line in f: dt, content parse_umd_time(line, args.year) if dt: entries.append((dt, UMD, content)) with open(args.kmd, r, errorsignore) as f: for line in f: dt, content parse_kmd_time(line, boot_time) if dt: entries.append((dt, KMD, content)) entries.sort(keylambda x: x[0]) fmt %Y-%m-%d %H:%M:%S.%f with open(merged_log.txt, w) as out: for dt, tag, content in entries: out.write(f{dt.strftime(fmt)[:-3]} [{tag}] {content}\n) print(f合并完成共 {len(entries)} 条日志输出到 merged_log.txt) if __name__ __main__: main()脚本本身不复杂但胜在实用。实际使用时UMD日志的年份如果跨年要去日志里确认或者从文件修改时间推断KMD日志如果平台没有提供开机时刻可以在脚本里加一个“手动对齐时间戳”参数用两侧都有的一条日志来锚定。5.3 实际使用效果与局限用这个脚本处理完日志之后整个日志流里UMD和KMD是交错的。比如一条3840x2160的抓拍请求日志顺序会是这样10:00:01.123 [UMD] Camx::RequestProcessor: New request 42 received 10:00:01.124 [UMD] Camx::HWL: Submitting request 42 to KMD, pipeline0 10:00:01.125 [KMD] cam_req_mgr: apply_request req_id42 10:00:01.130 [KMD] cam_isp: hw acquire req_id42, slot3 10:00:01.142 [KMD] cam_isp: notify_sof req_id42 10:00:01.150 [UMD] Camx::StatsProcessor: SOF received req_id42这样一眼就能看出request在哪个环节停留了多长时间UMD有没有及时收到KMD的sof事件。局限也很明显如果两侧时间戳对不齐合并后顺序就会错乱所以第一步还是要核对锚点。另外脚本只是文本处理不会区分进程线程如果同时打开多个camera场景建议先在UMD侧标记pipeline id再进脚本合并。6. 常见问题与排查技巧实录6.1 常见问题速查表现象可能原因处理建议UMD Log只有少量打印overrides文件路径不对或属性未加载确认平台读取路径重启camera providerKMD动态调试无输出debug分区未挂载或权限不足先mount debugfs检查节点访问权限图像dump没有文件生成dump目录不存在或dumpserver无写权限手动创建目录并chmod 777dump文件生成了但无法解析dump格式不是默认格式对照文件名和文件大小反推像素格式日志时间戳对不上锚点选错用启动时刻或特定日志对齐打开大量日志后卡顿日志量过大拖慢帧率分级开启只保留目标模块detail日志系统重启后log丢失日志没有落盘或落盘分区清理提前设置pstore或设置日志循环缓冲区6.2 我的几点避坑心得第一个心得很实际改完camxoverridesettings后一定要确认改的文件被正确加载。不要把时间浪费在猜配置上用一个特殊字符串比如“DUMP_TEST_ON”写进去再搜log里有没有出现有就是加载了。第二个心得抓KMD日志时尽量同时抓一份time stamp的锚点。可以在开camera前执行一次“date”把这个输出也存下来后面换算dmesg时间就方便很多。如果不做等日志抓完想对时间轴时就晚了。第三个心得图像dump尽量从raw开始。有时候效果问题绕来绕去看中间yuv会觉得无从下手但如果直接看raw没问题起码能把sensor摘出去如果raw本身有问题那就直接查sensor端出图和I2C配置问题范围一下子就缩小了。第四个心得高通平台不同子系统对日志处理的细节虽然有差异但整体思路是通用的找开关、开日志、抓现场、对时间轴。把这一套标准化之后无论是给产线复现问题还是远程让现场工程师抓log沟通成本都会小很多。最后再分享一个细节楼道里经常看到同事调试时开着一堆终端窗口刷日志其实真正有效的调试时间往往只集中在复现的那两分钟里。把Log开关做成一套标准操作文档抓log流程做成脚本每次复现前只需要一条命令启动抓取复现后一条命令停止抓取并把日志打包出来。这套流程一旦跑顺调试效率能提升一大截这也是我不厌其烦写这篇文章的原因。

相关新闻

CFD边界层网格与y+实战:从理论估算到Fluent Meshing设置

CFD边界层网格与y+实战:从理论估算到Fluent Meshing设置

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

2026/10/5 9:47:38 阅读更多 →
ROS2+SLAM+Nav2打造可调试扫地机器人全栈指南

ROS2+SLAM+Nav2打造可调试扫地机器人全栈指南

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

2026/10/5 9:47:38 阅读更多 →
Xilinx FPGA程序固化指南:从Bit文件到MCS文件的转换与选型

Xilinx FPGA程序固化指南:从Bit文件到MCS文件的转换与选型

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

2026/10/5 9:47:38 阅读更多 →

最新新闻

从零构建 coding agent CLI:TUI、Agent Loop 与 LLM 函数调用实战

从零构建 coding agent CLI:TUI、Agent Loop 与 LLM 函数调用实战

1. 从“pi”这个标题说起:一个极简命名背后的技术野心第一次看到“pi”这个项目标题,很多人会本能地联想到数学常数,或者树莓派(Raspberry Pi),再或者某个缩写。但如果你最近在开发者社区里泡过&#xff0c…

2026/10/5 11:16:56 阅读更多 →
ZYNQ EMIO调试UART完整指南:从引脚规划到串口实测

ZYNQ EMIO调试UART完整指南:从引脚规划到串口实测

ZYNQ 开发里有两件事几乎绕不开:一件是调试,一件是串口。做调试离不开 UART,做 UART 调试又绕不开 MIO 和 EMIO 的选择。我最早做 ZYNQ 的时候,习惯直接用 PS 端 MIO 接出来的 UART0,板子一上电就能在串口终端里看到 B…

2026/10/5 11:16:56 阅读更多 →
跨学科仿生设计:AI代理模型与多尺度仿真融合的数据驱动优化框架

跨学科仿生设计:AI代理模型与多尺度仿真融合的数据驱动优化框架

简介:这是一份聚焦跨学科融合仿生设计的系统性技术文档,面向机器人、新材料与AI交叉领域的研究者、工程师及高年级学生,系统讲解如何将机器学习、深度学习、材料基因组、多尺度建模与拓扑优化等方法整合到仿生设计全流程中。文档共593页&…

2026/10/5 11:16:56 阅读更多 →
智慧工厂AI安防平台设计:从架构到落地全流程指南

智慧工厂AI安防平台设计:从架构到落地全流程指南

简介:《AI赋能的智慧工厂安防平台建设方案》演示文稿是一份面向智慧工厂安防规划与智能制造升级的方案型资源,适合安防系统集成商、工厂信息化人员及管理者参考,可用于解决传统工厂安防管理分散、响应滞后、智能化程度不足等问题。内容围绕综…

2026/10/5 11:16:56 阅读更多 →
K8s服务发现与网络策略:读懂原理到实战避坑指南

K8s服务发现与网络策略:读懂原理到实战避坑指南

1. 前言:为什么服务发现和网络策略是K8s运维的两道必答题无论你是刚把第一个Pod跑起来,还是已经在生产环境里折腾了大半年,Kubernetes的服务发现和网络策略一定都绕不开。简单说,服务发现解决的是“流量到底该打到哪个Pod上”的问…

2026/10/5 11:16:56 阅读更多 →
Superpowers工作流:AI原生开发的认知增强层实战指南

Superpowers工作流:AI原生开发的认知增强层实战指南

1. 项目概述:Superpowers 不是超能力,而是开发者工具链的“认知增强层”你搜“superpowers”时看到的满屏 Claude Code、Antigravity、Codex CLI、Cursor,不是漫威电影彩蛋,也不是某个神秘组织的代号——这是2024年中后期&#xf…

2026/10/5 11:15:55 阅读更多 →

日新闻

马斯克杀回智能体战场,Grok 4.5万亿参数撑腰,Cursor接手数字白领项目:用TaoToken统一Key跑通多模型Agent工作流

马斯克杀回智能体战场,Grok 4.5万亿参数撑腰,Cursor接手数字白领项目:用TaoToken统一Key跑通多模型Agent工作流

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

2026/10/5 0:00:22 阅读更多 →
AI编程工具插件机制详解:plugin.json配置与加载失败排查指南

AI编程工具插件机制详解:plugin.json配置与加载失败排查指南

1. 从“plugins”这个词说起:它到底在解决什么问题如果你最近在折腾 AI 编程工具,尤其是 Cursor、Codex CLI、Claude Code 这类带 CLI 的编辑器或命令行助手,那你大概率绕不开一个词——plugins。这个词本身不新鲜,从浏览器到 IDE…

2026/10/5 0:00:23 阅读更多 →
第26课:OpenClaw|日志审计与问题诊断:把日志链路改到 TaoToken 的排查清单

第26课:OpenClaw|日志审计与问题诊断:把日志链路改到 TaoToken 的排查清单

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

2026/10/5 0:00:23 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

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

2026/10/5 5:06:42 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

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

2026/10/5 1:10:22 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

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

2026/10/5 3:06:17 阅读更多 →

月新闻

我发现了一个新思路:用 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/4 11:40:45 阅读更多 →
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/4 9:43:54 阅读更多 →
黑夜航拍船只数据集训练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/4 20:14:29 阅读更多 →