内核模块包
内核模块包 (KMP) 是一种让任何人以一种干净的方式打包内核模块的方法,以便在内核更新时能够妥善处理。
kABI 稳定性
已加载的内核模块是 Linux 内核的一部分,可以访问内核的所有数据结构。因此,它需要使用完全正确的内核配置、正确的编译器标志以及——最重要的是——正确的内核源代码进行编译。在实际情况下,通常只访问导出的符号,但最近的 2.6 内核中导出的内核符号超过 6000 个。
由于内核内部接口 (kABI) 相当不稳定且经常变化,内核更新很容易更改一些接口。这将破坏为旧版本编译的内核模块。幸运的是,这可以通过符号版本控制检测到,从而防止模块加载到内核中,从而防止数据损坏。
Novell 确实花费了相当大的精力,在为企业内核进行维护更新时,避免以不兼容的方式更改 kABI;但这并不意味着独立于内核提供商提供内核模块的人员需要为 kABI 更改做好准备——只是频率要低得多。当发布服务包或当无法通过其他方式修复关键错误或严重安全问题时,就会发生更改。
历史
这种内核及其模块之间的紧密联系使得发行版(包括 SUSE/Novell)将它们全部编译在一起,并全部提供在一个二进制内核 RPM 中。用户需要的每个内核模块(主要是驱动程序)都需要包含在内核中,因此它会在每次内核安全更新时重新编译。
处理内核模块这种方法已经达到了极限
- 尽管愿意接受树中的模块,但存在第三方内核模块,并且没有采取任何措施来正确处理在内核更新时的这些模块。在最坏的情况下,这可能导致系统在内核更新后无法启动——显然不是最佳的用户体验。
- 并非总是可以提供模块。存在法律限制、代码质量或可移植性问题,或者只是缺少测试的可能性(无论是由于缺少硬件还是缺少人力或知识)。
- 有时,内核模块在发行版发布时还没有准备好——然后,以后提供模块/驱动程序(或现有模块的更新版本)将非常有用。
内核模块包的出现
这个想法是干净地集成那些不是发行版提供的内核 RPM 的一部分的内核模块。任何具有相应知识的人都可以创建一个与特定内核版本匹配并与之配合工作的内核模块。要解决的真正难题是在内核安全更新时维护模块提供的功能。如果可能,通过重用模块来实现这一点,如果需要,则需要重新编译模块。
为了解决这个问题,在内核更新时会采取以下步骤
- 检测第三方内核模块
- 对于每个模块,检查它是否仍然适用于新内核(通过查看所有需要的符号及其版本)
- 如果它仍然有效,请确保它可以并且将由新内核重用
- 如果它与新内核不兼容
- 尝试下载新的内核模块 RPM
- 如果不可用,则显示错误消息(默认情况下中止更新)
这是用户所看到的一切——安装了内核模块包后,如果需要,更新将自动下载和安装。
但是,要使这一切发生,发行版和模块提供商需要做一些工作
为了确保新的内核模块被重新编译并在服务器上提供,发行版可以提供让人们注册其模块的功能;然后,模块创建者可以在影响它们的 kABI 更改时收到通知。这是可选的,但可以节省时间,因为这些通知通常可以在内核发布之前完成。以后,这应该也可以在 openSUSE 提供的构建服务中完成。
或者,发行版还可以提供自行重新编译模块——Novell 确实以这种方式提供一些额外的模块——并且 Novell Partner Engineering(以前:Developer Services)为合作伙伴提供此服务——请参阅 Linux drivers 页面以获取更多信息,如果这对您的公司有兴趣。
在 kABI 更改的情况下,仅对正确的内核源代码重新编译模块就可以完成工作——Novell 的政策是不需要在安全更新中更改代码(即 kAPI 更改)。这甚至适用于 SLES 服务包,尽管在那里不可能完全没有例外。但是,即使这种简单的重新编译也可能需要一些工作,Novell 现在会密切关注更改并努力避免 SLES 和 SUSE Linux 的安全/维护更新的 kABI 更改。但是,SLES 服务包通常会更改 kABI 的很大一部分——并且预计 openSUSE factory 内核会经常进行 kABI 更改,因为在那里会跟踪上游开发。
内核模块包格式
根据 SUSE Linux 的版本,使用两种不同的机制来检查模块与内核的兼容性。对于 SLES9SP3/NLD9SP3/OESv1SP2 和 SUSE Linux 10.0(这些版本随后称为 Code9),有一个单独的工具称为 kernel-update-tool 来完成这项工作。它在内核更新时被调用,并执行所有检查和下载。对于 SLES10/SLED10/OESv2 和 SUSE Linux 10.1 及更高版本(随后称为 Code10),该解决方案已集成到正常的系统安装、配置和更新工具中。因此,对内核符号的依赖关系已映射到 RPM 依赖关系,依赖关系解析器将尝试使用可用的安装/更新源来满足这些依赖关系,从而自动下载所需的模块或检测缺少的依赖关系。
内核模块包是包含内核模块 (.ko 文件) 和一些元数据的普通 RPM。为了识别第三方内核模块、查找更新等,内核模块包需要符合打包约定。打包约定分别针对较旧的 Code9(openSUSE 10.0 和 SLES9)解决方案、Code10(openSUSE 10.1 和 SLES10)解决方案以及较新的 Code11(openSUSE 11.1 和 SLES11)解决方案进行记录。
提供可下载更新的解决方案也略有不同。虽然 Code9 需要将 RPM 安排在 http(或 ftp)服务器上的特定目录结构中,但 Code10 和 Code11 解决方案需要 YaST 安装源的格式——我们建议使用 yum 格式——Code11 也可以使用 rpm-md 存储库。
像任何其他 RPM 一样,内核模块包应该具有 GnuPG 签名。更新程序将检查它,如果软件包未签名、由未知方签名或已损坏,则会发出抱怨。在初始安装时,安装文档或安装脚本应建议将模块包提供程序的 GnuPG 签名密钥导入到 RPM 密钥环中,以将该 RPM 包提供程序标记为受信任。密钥导入不应在秘密中进行,而应在安装软件包的管理员明确同意的情况下进行。
初始模块安装
以上讨论了如何让第三方内核模块在内核更新时幸免于难,而不会给用户带来麻烦。但是,最初如何找到额外的模块?
- 模块包可以作为产品的一部分。供应商可以将 RPM 包含在驱动程序 CD 或任何正常的软件分发渠道中。对于 Code10,建议使用一个微型脚本来注册更新源并提供将 GnuPG 包签名密钥导入到 RPM 密钥环中。
- 模块包可以提供下载。可以下载 RPM(Code9),或者可以在安装时(或之后)在安装程序/更新程序(Code10/11)中将下载位置作为安装和更新源输入(Code10/11)。
- 用户可以通过搜索供应商的网站、阅读供应商或其他人的文档、关注 openSUSE 的提示、搜索引擎等来找到下载站点。
- 为了节省搜索工作,一个更好的自动化机制,使用软件/驱动程序门户,软件提供商可以在其中注册额外的安装/更新源,这些源可以在 YaST 安装时选择性地提供,正在准备中。根据检测到的硬件提供软件包也是设计的一部分。
打包格式规范还确保为不同内核版本创建的模块,如果与系统中安装的内核兼容,将用于安装的内核。
支持和认证
支持和认证仅与企业产品(SLES、NLD/SLED、OES)相关。在这种情况下,支持是指客户能够打开支持呼叫并获得保证的个人关注(包括工程工作)以解决他们报告的问题的能力。
内核模块可以访问内核地址空间,并且很容易危及操作系统的稳定性和可靠性。未知于 Novell 的模块状态为“不受支持”,并且在加载时会向 syslog 生成警告消息并“污染”内核。如果用户加载了这样的不受支持的内核模块,Novell 无法做很多事情来帮助解决内核问题。相反,应该在没有加载此类模块的情况下重现该问题,以便进行调试。
但是,模块提供商可以使模块获得“外部支持”状态;为此,他需要与 Novell 密切合作。需要建立适当的支持渠道接口,以便 Novell 支持和模块提供商能够共同处理客户问题。模块提供商必须承诺在 SLES 的整个生命周期内维护该模块。内核模块包需要按照上述规则构建——最好由 Novell 的构建服务(Novell Partner Engineering)构建。以这种方式构建的模块也可以进行测试和认证,从而成为认证系统的一部分。
Specfile 机制
在 specfile 序言中,请求 kernel-syms(拉取 kernel-devel)和 modutils 存在。
Requires: kernel-syms modutils SourceN: %name-kmp-preamble
在 %description 之前,指定此项以生成 kmp 子包
%kernel_module_package -p %name-kmp-preamble -x ec2 xen
该-p参数指定要添加到每个 kmp 子包的额外 rpm 标签。-x标志(如果提供)请求从构建中排除这些内核风味。反之是省略-x并仅指定要构建的风味。
一些标签来自一个空“KMP”子包的标签
%package KMP Summary: The kernel modules for xyz Group: System/Kernel %description KMP This provides blahblah.
在 kmp 序言文件中,%1 表示风味,%2 表示包版本。在此文件中,可以有一行或多行以下行
- Enhances: kernel-%1
“Enhances”是反向“Suggests”。在安装 kernel-flavor 时,可以建议 mypkg-kmp-flavor 子包。 - Supplements: packageand(kernel-%1:%name)
“Supplements”是反向“Recommends”。如果 kernel-flavor 也存在于系统中,或者将要存在于系统中,则将建议安装 mypkg-kmp-flavor 子包。
每个 kmp 已经提供了“mypkg-kmp”和“mypkg-kmp-flavor”。