Linux 内核中的 nls_cp*.ko 不是「驱动」,而是 NLS 编码表模块。本文详细说明其作用和裁剪策略。
NLS 是什么?
NLS = Native Language Support(本地语言支持),是 Linux 内核对不同字符编码/代码页(Code Page)的翻译支持层。它主要服务于 FAT / VFAT / exFAT / ISO9660 等「文件名带非 UTF-8 编码」的文件系统,让内核能把磁盘上存储的 legacy 编码与内核使用的 UTF-8/Unicode 之间进行转换。
nls_cp*.ko不是硬件驱动,而是字符编码转换表的可加载内核模块。
nls_cp*.ko 对应什么?
cp = Code Page(Windows/DOS 体系代码页):
| 模块名 | 对应编码 | 典型使用场景 |
|---|---|---|
| nls_cp437.ko | IBM Code Page 437(美式 DOS/OEM) | 最基础的 OEM 字符集,VFAT 默认短文件名 |
| nls_cp850.ko | CP850(西欧 DOS) | 西欧多语言 DOS |
| nls_cp936.ko | CP936(GBK 简体中文) | 简体中文 Windows 的 FAT 卷常见 |
| nls_cp950.ko | CP950(Big5 繁体中文) | 繁体中文环境 |
| nls_cp1250.ko | Windows-1250(中东欧) | 波兰、捷克等 |
| nls_cp1251.ko | Windows-1251(西里尔) | 俄语等 |
| nls_cp1252.ko | Windows-1252(西欧 Latin-1 变体) | 西欧 Windows 最常见 |
| nls_cp932.ko | CP932 / Shift-JIS(日文) | 日文 Windows |
这些 .ko 本质上就是把一张「源编码 → Unicode (UTF-16)」的映射表编进内核模块,供 NLS 子系统查表用。
为什么 FAT/VFAT 特别需要它?
FAT 的文件名历史上有两副面孔:
- 短文件名(8.3):用 code page(如 CP437 / CP936)编码字节
- 长文件名(LFN):规范里说是 UTF-16LE,但老实现/老介质/老参数组合仍然跟 code page 关联
挂载 VFAT 时常看到:
mount -t vfat /dev/sdb1 /mnt -o codepage=936,iocharset=utf8
codepage=→ 选一个nls_cp*.ko(处理短文件名/8.3 的解码基准)iocharset=→ 选一个 NLS 作为「输出端字符集」(常见就是utf8,对应nls_utf8.ko)
内核在内部走的是:disk bytes (CP) → Unicode → output charset 的转换路径。
最少保留组合(最稳方案)
绝对底座
- nls_base(通常编进 vmlinux,不一定以独立 .ko 出现)
- nls_utf8 / nls_utf8.ko
没有 nls_base + utf8,FAT/VFAT 常用挂载路径很容易出问题。
最少 Code Page 模块
至少保留这两个就覆盖了 90% 现实情况:
- nls_cp437.ko —— VFAT/FAT 的「默认/兜底 codepage」(短文件名 8.3 解码)。内核在很多地方把它当 fallback,裁掉它经常换来一堆 warning 或直接失败
- nls_cp936.ko(GBK/简体中文)—— 中国大陆常见存量 U 盘/老设备格式化出来的 FAT,很可能用的是 cp936(GBK)
推荐最小可工作组合
nls_base (builtin)
nls_utf8
nls_cp437
nls_cp936 # 中国环境基本要它
如果还要支持其他区域老 U 盘:
- 西欧常见:
nls_cp850、nls_cp1252 - 日文:
nls_cp932 - 俄文:
nls_cp1251
狠裁方案:两条安全线
方案 A:只求「能挂上不报错」
- 留
nls_base + nls_utf8 + nls_cp437 - 其它
nls_cp*.ko可砍 - 挂载参数统一化:
mount -t vfat ... -o codepage=437,iocharset=utf8
可能牺牲短文件名可读性(中文文件名可能乱码)。
方案 B:确定所有 FAT 来源都是「现代 Windows 写入」
- 只留
nls_base + nls_utf8 + nls_cp437(cp437 仍是 fallback,不建议真删) - 把
CONFIG_NLS_CODEPAGE_437编为 builtin(而非 module),其余CONFIG_NLS_CODEPAGE_*关掉 - 做一次全量挂载回归测试
一句话总结
nls_cp*.ko是 Linux 内核的 Code Page 字符编码映射表模块,属于 NLS(Native Language Support)子系统,用来让 FAT/VFAT/exFAT/ISO9660 等文件系统正确把磁盘上的 legacy 编码文件名翻译成内核认识的 Unicode/UTF-8。它不是硬件驱动,而是「编码翻译表的可加载插件」。
如果你在排查某个设备/U 盘挂载时出现 FAT: codepage xxx not found 或 iocharset not found 这类报错,按上面的最小组合把对应的 nls_cp*.ko 编译进去就能解决。
