news 2026/9/25 2:50:49

jc 解析器 proc_mtrr:把 /proc/mtrr 的 MTRR 内存类型信息结构化输出为 JSON

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
jc 解析器 proc_mtrr:把 /proc/mtrr 的 MTRR 内存类型信息结构化输出为 JSON
  • 开发工具

【免费下载链接】jc

CLI tool and python library that converts the output of popular command-line tools, file-types, and common strings to JSON, YAML, or Dictionaries. This allows piping of output to tools like jq and simplifying automation scripts.

项目地址:https://gitcode.com/gh_mirrors/jc/jc
点击查看免费下载

本文围绕 jc 项目中的/proc/mtrr文件解析器(jc.parsers.proc_mtrr)展开,完整覆盖其命令行与 Python 模块两种调用方式、输出 Schema、原始/处理后输出差异,并结合 jc/parsers/proc_mtrr.py 源码与 tests/test_proc_mtrr.py 测试用例,讲清它如何把内核导出的 MTRR(Memory Type Range Register)寄存器信息逐行拆分为可被 jq、Python 脚本直接消费的结构化数据。

什么是 MTRR 与 /proc/mtrr

MTRR 是 x86 架构 CPU 提供的内存类型寄存器,用于指定某段物理地址范围的缓存行为。Linux 内核通过虚拟文件系统文件/proc/mtrr导出当前系统中生效的 MTRR 条目。其原始输出是一个定宽、混用冒号与逗号的文本列表,每行描述一个寄存器,形如:

reg00: base=0x000000000 ( 0MB), size= 2048MB, count=1: write-back reg01: base=0x080000000 ( 2048MB), size= 1024MB, count=1: write-back ... reg08: base=0xe8000000 (3712MB), size= 32MB: write-combining, count=1 reg11: base=0xfb000000 (4016MB), size= 4kB: uncachable, count=1

其中type字段(write-back、write-combining、uncachable)表示缓存策略;base与括号中的 MB 值给出起始物理地址;size给出覆盖范围;count表示该条目使用的 MTRR 寄存器数量。这类输出常见于内存性能调优、GPU/设备 BAR 映射排查等场景,但原文本中数字与单位混杂、行内分隔符不统一,直接交给脚本处理很麻烦——这正是 jc 这个解析器解决的问题:把它转成 JSON / YAML / Python 字典,方便| jq或自动化脚本进一步加工。

使用方式:三种 CLI 形式与 Python 模块形式

与 jc 的其它 Proc 解析器一致,proc_mtrr支持三种等价的命令行用法:

# 方式一:通过 proc 通用解析器(自动识别 /proc/mtrr) $ cat /proc/mtrr | jc --proc # 方式二:magic 语法,直接把 /proc 文件路径交给 jc $ jc /proc/mtrr # 方式三:直接指定具体解析器 $ cat /proc/mtrr | jc --proc-mtrr

在 Python 中以模块方式调用时,两种 parser 名都可以使用:

import jc # 通过 proc 通用解析器(自动分发) result = jc.parse('proc', proc_mtrr_file) # 或直接指定 proc_mtrr 解析器 result = jc.parse('proc_mtrr', proc_mtrr_file)

关于 magic 语法,jc/parsers/proc.py 的模块文档还补充了两个实用细节:所有jc选项必须写在/proc路径之前;该语法还支持“slurp”方式一次传入多个文件(例如jc /proc/*/stat),输出会包在数组里,并附带_file字段用于关联输入输出,--meta-out选项可额外列出/proc输入文件名。

输出 Schema 与字段说明

解析后的结果为字典列表,每个字典对应一行 MTRR 寄存器记录:

[ { "register": string, "type": string, "base": string, "base_mb": integer, "size": integer, "count": integer, "<key>": string # additional key/values are strings } ]

各字段含义如下:

字段类型来源与说明
registerstring每行首段,如reg00、reg08,标识 MTRR 寄存器编号
typestring行尾的缓存类型:write-back/write-combining/uncachable等
basestring十进制与括号 MB 值之前的十六进制起始地址,保留原始字符串(含前导 0),如"0x000000000"
base_mbinteger括号内标注的起始地址(MB 为单位),如2048
sizeintegersize=后的数值部分,单位(MB/kB)在处理后被剥离,见下文说明
countinteger该条目占用的 MTRR 寄存器数量,通常为1
<key>stringSchema 中保留的扩展位:任何额外解析出的key=value对都会以字符串形式并入

parse()函数签名与参数说明(与文档一致):

def parse(data: str, raw: bool = False, quiet: bool = False) -> List[Dict]
参数类型说明
datastring待解析的/proc/mtrr文本
rawboolean为True时返回未做类型处理的原始结构化输出
quietboolean为True时抑制告警信息

返回值是一个List[Dict],即原始或已处理的结构化数据。

完整示例:从 12 个寄存器到 JSON

仓库测试夹具 tests/fixtures/linux-proc/mtrr 收录了一份覆盖三种缓存类型、12 个寄存器(reg00–reg11)的真实样例输入,处理后的完整输出见 tests/fixtures/linux-proc/mtrr.json。取其中若干条展示(处理后):

$ cat /proc/mtrr | jc --proc -p
[ { "register": "reg00", "type": "write-back", "base": "0x000000000", "base_mb": 0, "size": 2048, "count": 1 }, { "register": "reg08", "type": "write-combining", "base": "0xe8000000", "base_mb": 3712, "size": 32, "count": 1 }, { "register": "reg11", "type": "uncachable", "base": "0xfb000000", "base_mb": 4016, "size": 4, "count": 1 } ]

而原始(-r)模式下的对应输出为:

$ cat /proc/mtrr | jc --proc-mtrr -p -r
[ { "register": "reg00", "type": "write-back", "base": "0x000000000", "base_mb": "0", "size": "2048MB", "count": "1" }, { "register": "reg08", "type": "write-combining", "base": "0xe8000000", "base_mb": "3712", "size": "32MB", "count": "1" } ]

两种模式的差异值得注意:

  • raw 模式:base_mb、size、count全部是字符串,且size保留原始单位("2048MB"、"4kB"),便于与内核原文逐字核对;
  • 默认(处理后)模式:这三个字段被转为整数,size的单位后缀被剥离("4kB"→4)。也就是说,处理后的size是“原文数值”而非统一 MB 值——对 reg11 这样的 kB 级条目,size: 4实际表示 4kB。在下游做字节换算时应结合 raw 输出判断原始单位,这是使用该解析器时最需要留意的一个语义细节。

源码走读:proc_mtrr.py 的解析实现

解析实现位于 jc/parsers/proc_mtrr.py,核心只有parse()(L124-L183)与_process()(L102-L121)两个函数。

1. 入口校验。parse()先调用jc.utils.compatibility(__name__, info.compatible, quiet)检查运行平台(该解析器声明compatible = ['linux'],见 L94),再通过jc.utils.input_type_check(data)与jc.utils.has_data(data)做输入类型和空数据检查;空输入直接返回空列表。

2. 行级拆分。对每一行执行re.split(r',|:', line),即以逗号或冒号作为分隔符(L151)。这一步能同时兼容两种行内排版:

reg00: base=0x000000000 ( 0MB), size= 2048MB, count=1: write-back reg08: base=0xe8000000 (3712MB), size= 32MB: write-combining, count=1

第一行中type在count之后,第二行中count在type之后——字段顺序并不固定。

3. 字段识别策略。拆分后:

  • 第一个片段是寄存器名(reg00等);
  • 第二个片段形如base=0x000000000 ( 0MB),用split(maxsplit=1)拆出base十六进制串与括号内 MB 值,后者再经replace('(', '').replace(')', '').replace('MB', '').strip()清洗为纯数字(L156-L160);
  • 其余片段中,包含=的一律按key=value收入键值字典(即size=...、count=...);不含=的则被认定为缓存类型type(L162-L167)。

这个“含等号即键值、不含等号即类型”的判别规则,正是该解析器能同时处理上面两种字段顺序、并对未来新增key=value字段保持开放的原因——这与 Schema 中<key>扩展位的设计相呼应。

4._process()的整型化。处理后阶段对每个条目的size、count、base_mb三个键调用 jc/utils.py 中的convert_to_int()(L252-L279):该函数用正则[^0-9\-\.]剥掉所有非数字字符(保留-与.)后再做int()转换,因此"2048MB"→2048、"4kB"→4。这也解释了前文提到的“处理后size丢失单位”的行为。

proc 通用解析器如何自动分发到 proc_mtrr

当使用jc --proc或 magic 语法jc /proc/mtrr时,并不直接调用proc_mtrr,而是由 jc/parsers/proc.py 的签名识别机制完成分发。该文件在parse()中维护了一组特征正则与解析器名的映射表procmap,其中 MTRR 的识别签名为(L177):

mtrr_p = re.compile(r'^reg\d+: base=0x[0-9a-f]+ \(')

即要求至少一行以reg<数字>: base=0x<十六进制> (开头,命中后映射到proc_mtrr模块(L236),并动态加载调用其parse()。若内容无法被任何签名匹配,则抛出ParseError('Proc file could not be identified.')。这也意味着jc.parse('proc', data)与jc.parse('proc_mtrr', data)在 mtrr 文本上得到相同结果。

测试验证

单测 tests/test_proc_mtrr.py 使用夹具对(tests/fixtures/linux-proc/mtrr 原文 / tests/fixtures/linux-proc/mtrr.json 期望值)做了两项断言:

  1. test_proc_mtrr_nodata:空字符串输入应返回[];
  2. test_proc_mtrr:对 12 行样例输入解析后的字典列表应与夹具 JSON 完全相等。

这保证了从write-back到uncachable的各类行、以及两种字段顺序排列(如 reg08 行size在type之前)都能被正确解析为整型化的结构化结果。测试可通过仓库根目录的 runtests.sh 随全量测试一起运行,单跑该解析器对应用例即可验证其回归稳定性。

解析器元信息与适用前提

从 jc/parsers/proc_mtrr.py 的info类可确认以下元数据:

元信息值
version1.0
description/proc/mtrrfile parser
authorKelly Brazil
compatiblelinux
tagsfile
hiddenTrue

适用前提与限制:

  • 平台限制:compatible = ['linux'],且输入必须是/proc/mtrr风格文本(x86 系内核的 MTRR 导出),在其它系统上运行兼容性检查时会给出告警;
  • hidden 标记:从源码结构看,该解析器被标记为hidden = True,属于 jc 中不常出现在常规列表中的 Proc 细分解析器。按照 jc/parsers/proc.py 文档的说明,具体 Proc 文件解析器清单可通过jc -hh或jc -a查看,其 Schema 亦可借助jc --help --proc-mtrr打印;
  • 输入来源:解析器只依赖文本内容而非文件路径,因此除直接读/proc/mtrr外,把保存下来的/proc/mtrr快照文件喂给它同样有效(测试夹具正是这样做的);
  • 下游使用:默认整数化输出适合直接| jq '.[] | select(.type=="write-combining")'这类过滤统计;若需要保留MB/kB单位原文做二次换算,应加-r使用 raw 输出。

小结

jc.parsers.proc_mtrr用不到 200 行代码(含文档字符串)解决了/proc/mtrr这类“分隔符混用、字段顺序不定”的内核导出文本的结构化问题:以“含等号即键值、不含等号即类型”的启发式实现了对多种行内排版的兼容,通过convert_to_int提供数值化默认输出,同时保留-r原始模式以便追溯原文单位。无论是编写内存类型排查脚本,还是把 MTRR 配置纳入监控采集,cat /proc/mtrr | jc --proc-mtrr都是把它变成可计算数据的最短路径。

  • 开发工具

【免费下载链接】jc

CLI tool and python library that converts the output of popular command-line tools, file-types, and common strings to JSON, YAML, or Dictionaries. This allows piping of output to tools like jq and simplifying automation scripts.

项目地址:https://gitcode.com/gh_mirrors/jc/jc
点击查看免费下载
上一篇:libzmq性能调优完全指南:perf基准测试剖析与高并发低延迟优化技巧
下一篇:CANN / asc-devkit: asc_loadalign_brc_elem BRC搬入API

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/25 2:50:08

从Anaconda到Miniconda:轻量级Python环境管理实战指南

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

作者头像 李华
网站建设 2026/9/25 2:46:44

4路CAN FD免驱工具:LTE远程调试+故障注入全解析

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

作者头像 李华
网站建设 2026/9/25 2:44:26

猫抓浏览器扩展最短路径实操:网页媒体嗅探与 M3U8 离线保存

猫抓浏览器扩展最短路径实操&#xff1a;网页媒体嗅探与 M3U8 离线保存 【免费下载链接】cat-catch 猫抓 浏览器资源嗅探扩展 / cat-catch Browser Resource Sniffing Extension 项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch 猫抓&#xff08;cat-catch…

作者头像 李华