NetBSD GSoC 2026:测试兼容性 Linux 系统调用
摘要
一份 Google Summer of Code 2026 项目报告详细介绍了使用 Linux Test Project 改进 NetBSD 的 Linux 兼容层测试的努力,包括编译测试、创建包和记录系统调用模拟。
<p><a href="https://lobste.rs/s/im7lnc/netbsd_gsoc_2026_testing_compat_linux">评论</a></p>
查看缓存全文
缓存时间: 2026/09/08 21:08
# NetBSD博客
来源:https://blog.netbsd.org/tnf/entry/gsoc2026_testing_compat_linux_2
## 2026年Google编程之夏报告:测试兼容Linux:系统调用测试(第二部分)(https://blog.netbsd.org/tnf/entry/gsoc2026_testing_compat_linux_2)
2026年9月7日 发布者:*Leonardo Taccari*
Linux和NetBSD标志与锤子
本报告由Henrique Brito撰写,是2026年Google编程之夏项目的一部分。
这是系列报告的第二部分。您可以在Google编程之夏2026报告:测试兼容Linux:系统调用测试(第一部分)(https://blog.netbsd.org/tnf/entry/gsoc2026_testing_compat_linux)中阅读第一部分。
## 简介与描述
`compat_linux(8)` (https://man.netbsd.org/compat_linux.8) 是NetBSD内核层面的Linux二进制文件兼容层。它允许通过一个轻量级的内核翻译层运行Linux程序,而非完全模拟。其核心功能之一就是为这些程序模拟Linux系统调用。
迄今为止,该功能的测试完善程度不如NetBSD的其他组件。本项目的目标是利用Linux自身的测试套件LTP(Linux测试项目)(https://linux-test-project.readthedocs.io/),来验证`compat_linux`的可用性和兼容性。
LTP是一个知名且经过实战检验的框架,已用于验证Linux行为,那么为何不用它来验证NetBSD的`compat_linux`呢?
## 已完成工作
在此项目中,我让LTP测试能够在NetBSD下编译、按设计运行,记录了一些更相关的系统调用模拟,并发现了一些涉及`compat_linux`的非常有趣的行为。
### 在`compat_linux`下编译测试
此步骤涉及修复并使用最近从pkgsrc-wip (https://www.pkgsrc.org/wip/) 拉入pkgsrc的`suse15_gcc12`。修复包括添加一些包含相关代码的缺失RPM包,例如:
- `linux_glibc_devel`:添加了许多Linux头文件,对编译底层LTP测试至关重要。
- `glibc_devel_static`:使用gcc进行静态编译所必需。
### 创建脚本/包
为了在NetBSD上正确运行测试,需要创建一个“管理”脚本来弥补两个操作系统之间的差距。为了分发该脚本并自动化LTP的下载和编译,我们决定创建一个包。幸运的是,pkgsrc的阶段与我们的需求非常相似:一个用于下载LTP的**fetch**,一个用于编译它的**build**,以及一个用于安装它的**install**。
`compat_linux_test_project`包尚未合并到官方pkgsrc树中,但您可以在此处我的个人分支中找到它(https://github.com/henriquebritoM/pkgsrc/tree/compat_linux_test_project/emulators/compat_linux_test_project)。
### 测试文档
对于我们认为更基础的系统调用(即更频繁使用、被更多应用程序使用)进行了更深入的分析和测试。这些测试随后被编目并整齐地记录在一份电子表格(https://docs.google.com/spreadsheets/d/1FJM8PhpQttSHX4nicSUxa5UAazJBpvJ7UnPuZELScLw/edit?usp=sharing)中,以供将来参考。我还为最终可能的修复添加了一些建议。
电子表格截图,显示包含系统调用、LTP测试、状态、进度、问题类型、详细信息和多个备注的表格(https://docs.google.com/spreadsheets/d/1FJM8PhpQttSHX4nicSUxa5UAazJBpvJ7UnPuZELScLw/edit?usp=sharing)
### 日志、配置文件和其他GSoC项目产物
项目期间使用的所有原始日志和相关文件都存储在一个在线驱动器(https://drive.google.com/drive/folders/1Mf4EcyfIf2KeEJWxs5cqjiwY20Rpln6Y?usp=sharing)中,任何想查看的人都可以自由访问。
### 最终测试
为了更好地理解`compat_linux`的当前状态,我在`compat_linux`上运行了完整的LTP系统调用测试套件。在此阶段,发现了许多有趣且相关的结果。详情见下文“结果”部分。
## 挑战
起初,我认为这将是一个相当直接的项目,但结果证明它比我预想的更具挑战性和趣味性。在这次GSoC期间,我遇到了许多大大小小的挑战,其中一些列举如下:
第一个是“如何编译LTP”。我最初的建议是不要在NetBSD上编译测试,而是在Linux机器上静态编译它们并使用生成的二进制文件。由于多种原因,这并非合适的想法。我的导师Stephen随后建议我们可以使用`suse15_gcc12`包。这是个好主意,也有点有趣:从Linux引入一个编译器,并通过`compat_linux`使用它来编译测试,以验证`compat_linux`的可用性。幸运的是,该包的状态已经很好,只需添加一些缺失的RPM包即可运行。
第二个是关于“如何将我的脚本转换为pkgsrc包”。我创建脚本时的最初方法是尽可能自动化,因此它会在一个脚本中检查LTP版本、下载、编译等所有步骤。在转向pkgsrc时,我意识到框架内部已经实现了其中许多功能。因此我最终不得不将我的逻辑移入pkgsrc。pkgsrc是一个非常完整且令人愉快的包系统,即使我没有相关经验(当然,在导师的帮助下),我也能够掌握并使用它。
第三个是关于“静态编译还是动态编译”。动态测试更小,但运行时需要`suse15_base`包,而静态测试则不需要其他任何东西。因此起初,静态编译似乎是可行之道,但当我们检查两者的包大小时,问题出现了:静态包约5GB,而动态包为545MB。对于测试包来说不太合适。经过对gcc参数的一些调整,我成功将动态包的大小减小到80MB。
## 结果
在`compat_linux`中运行测试用例提供了关于其当前状态的许多有用见解。在我看来,它非常完善,涵盖了大多数常用/使用所需的内容。只有当Linux系统调用开始偏离POSIX,具有Linux专属功能或不同行为时,`compat_linux`才开始缺乏覆盖,因为在`compat_linux`中实现这些函数基本上需要“重新创建”该系统调用。
### `/proc/self/maps`的差异
运行`mmap04`测试用例时,我发现它失败了,因为LTP无法正确读取`/proc/self/maps`。
这是因为Linux以可变长度的十六进制数字显示地址,会去掉最左边的零(保持最少8位十六进制数字),而NetBSD则使用固定的16位十六进制数字来显示地址。
Linux:
Linux下“cat /proc/self/maps”的截图
NetBSD:
NetBSD下“cat /proc/self/maps”的截图
根据`mount_procfs(8)`手册页(https://man.netbsd.org/mount_procfs.8),maps应以“类似于Linux中实现的proc文件系统的形式”实现,因此这是行为上的差异。
参见tech-kern@邮件列表上的讨论帖(https://mail-index.netbsd.org/tech-kern/2026/08/01/msg031204.html)。
### `writev`和`iovcnt`
模拟的系统调用`writev(2)` (https://man.netbsd.org/writev.2) 行为存在差异,但此差异与我们发现的大多数差异不同。
根据POSIX (https://pubs.opengroup.org/onlinepubs/9799919799/functions/writev.html),当`iovcnt`为0时,`writev`应返回`EINVAL`。NetBSD及其`compat_linux`实现遵循了此规定。另一方面,Linux表现出不同的行为,它不将`iovcnt = 0`视为错误,而是返回成功。
### `copy_file_range`上的SMAP违规
此系统调用模拟是在2024年GSoC中实现的,但现在才开始被纳入NetBSD主流版本,始于NetBSD 11。问题是在内核空间中简单解引用用户空间指针,没有适当处理,这会触发SMAP违规,导致内核恐慌。
显示`copy_file_range()`内核恐慌跟踪和寄存器信息的ddb(4)截图
这种情况仅在`off_in`或`off_out`不为`NULL`时发生,这是在实现过程中未捕捉到的一个边缘情况。
让我们看一下负责此问题的代码(https://github.com/NetBSD/src/blob/5a7765109d6feb3a897b349b8d58572a0b7812f2/sys/compat/linux/common/linux_file.c#L1126-L1132):
```c
if ((SCARG(uap, off_in) != NULL && *SCARG(uap, off_in) < 0) || <- 解引用
(SCARG(uap, off_out) != NULL && *SCARG(uap, off_out) < 0) || <- 解引用
vattr_in.va_type != VREG || vattr_out.va_type != VREG) {
error = EINVAL;
DPRINTF("%s: Invalid offset or file type\n", __func__);
goto out;
}
```
这里,`*SCARG(uap, off_in/off_out)`试图在内核空间解引用用户空间指针。我认为这是一个很好的例子,说明了为什么我们应该使用LTP来验证`compat_linux`中新系统调用实现的兼容性和功能性。
在撰写本文时,`copy_file_range`的修复尚未进入NetBSD代码树,但您可以在此处找到补丁(https://gist.github.com/henriquebritoM/87b3b041bb5622e095b6b138fc9b5b28)。
### 通过`rt_sigqueueinfo`杀死用户进程 ;)
这是我在该项目中遇到的最有趣的事情。这是在测试`rt_sigqueueinfo`系统调用时发现的。我注意到它发生了一些奇怪的事情,类似于`copy_file_range`,但又不完全一样。运行LTP测试时,我的SSH会话会断开,脚本会停止,其他一切都会暂停,直到重启后才恢复正常。起初我以为是内核恐慌,但似乎什么都没发生:dmesg中没有记录,没有恐慌屏幕,什么都没有。所以我不得不检查`compat_linux`的`rt_sigqueueinfo`实现和LTP测试用例。造成问题的测试用例(https://github.com/linux-test-project/ltp/blob/3c0271a307bd765c2fd652c325762a90ddf5d46f/testcases/kernel/syscalls/rt_sigqueueinfo/rt_sigqueueinfo02.c#L38-L39)使用了`tgid`为-1,这本意是代表一个不存在的`tgid`。但`compat_linux`的实现(https://github.com/NetBSD/src/blob/5a7765109d6feb3a897b349b8d58572a0b7812f2/sys/compat/linux/common/linux_signal.c#L639-L658)与Linux不同,在其逻辑中使用了`kill(2)` (https://man.netbsd.org/kill.2)。将线索连接起来,我注意到`kill(2)`对`-1`有一个特殊用法,用于广播信号。碰巧的是,测试用例与系统调用模拟结合,作为副作用杀死了所有进程。我们仍在讨论对此应如何处理。
## 关于脚本
如上所述,在NetBSD上正确运行LTP测试需要某种“粘合剂”来处理两个操作系统之间的差异。这是通过创建一个专门的脚本来解决的。该脚本安装为`compat_linux_test_project`,可以运行完整的系统调用套件或选定的子集,生成结构化的、按系统调用分类的日志,并将新运行结果与基线日志集进行比较,以突出回归、修复和其他更改。已知会导致挂起或内核恐慌的测试用例默认被跳过,但在需要时仍可显式运行。
### 安装方法
由于该包尚未合并到官方pkgsrc树中,您可以直接从我的分支构建它:
```sh
git clone https://github.com/henriquebritoM/pkgsrc.git
cd pkgsrc
git checkout compat_linux_test_project
cd emulators/compat_linux_test_project
make install
```
### 使用方法
最常见的用例之一是运行某个系统调用(或一组系统调用)的测试。
为此,您可以执行:
```sh
compat_linux_test_project -s readv,writev,open,close -d output_dir
```
这将运行所有与`readv`、`writev`、`open`和`close`系统调用相关的测试用例,并将生成的日志存储在`output_dir`中。
输出目录的内容应类似于:
```
# tree -F output_dir/
output_dir/
|-- close/
| |-- close01.log
| `-- close02.log
|-- open/
| |-- open01.log
| |-- open02.log
| |-- open03.log
| |-- open04.log
| |-- open06.log
| |-- open07.log
| |-- open08.log
| |-- open09.log
| |-- open10.log
| |-- open11.log
| |-- open12.log
| |-- open13.log
| |-- open14.log
| `-- open15.log
|-- readv/
| |-- readv01.log
| `-- readv02.log
`-- writev/
|-- writev01.log
|-- writev02.log
|-- writev03.log
|-- writev05.log
|-- writev06.log
`-- writev07.log
4 directories, 24 files
```
更多提示,您可以使用帮助选项列出完整的包使用说明:
```sh
compat_linux_test_project --help
```
预期输出:
```
NAME
compat_linux_test_project - package to run LTP tests on NetBSD
SYNOPSIS
compat_linux_test_project [options]
DESCRIPTION
compat_linux_test_project is a package to download, build, and run
the Linux Test Project (LTP) test suite on NetBSD, intended for
testing the compat_linux compatibility layer.
It automates fetching, building, and executing LTP tests, helping
to identify missing syscalls, behavioral differences, and other
issues in NetBSD's Linux compatibility subsystem.
If no --syscall option is passed, the default behavior is to test
every possible syscall. This uses the LTP runtest/syscalls file to
determine what to test and in which order. This means that the syscall
name cannot be correctly-determined sometimes, resulting in suboptimal
output in the logs. This also takes some time and is not
recommended, except in some niche cases.
All tests belong to Linux Testing Project, this package only ports
them to make them run on NetBSD. Support the Linux Test Project by
checking their official website:
https://github.com/linux-test-project/ltp
OPTIONS
-d, --output-dir output_dir
Directory where output is written.
In test-run mode (default): new logs are stored here,
overwriting any older logs already there.
In comparison mode (-c): the categorized comparison results
(compared_logs/) are stored here instead.
-s, --syscall syscall1[,syscall2,...]
A comma-separated list of which syscalls to test.
The script will search for them using the LTP runtest file,
so the name may be slightly different from the syscall name
(though this is unusual).
WARNING: some syscalls are excluded from the default (full)
run because they are known to cause problems (e.g. kernel
panics or hangs, see check_for_testcase_issue() in the
script). If you explicitly list one of these syscalls here,
the script will still run it, but will print a warning first.
-r, --reproducible
Sets the LTP environment variable LTP_REPRODUCIBLE_OUTPUT to 1.
According to LTP documentation, this "suppresses printing TINFO
and TDEBUG messages and discards the actual content of the
other messages printed by the test (suitable for a
reproducible output)."
This flag should be set if the logs are meant to be compared.
-c, --compare logs_dir
Compares logs_dir against a baseline, highlighting
their differences. For a consistent comparison, both
sets of logs should have been gathered using the
'reproducible' mode ('-r' flag).
The baseline defaults to the reference logs shipped with the
package, or to whatever is passed via '-b'.
If '-s' is also passed, the comparison is restricted to the
syscalls listed there.
The comparison is done as follows:
Checks for tests that are new, tests that are no longer
present, and tests whose result changed. Changed results are
further split into regressions (e.g. PASS -> FAIL), fixes
(e.g. FAIL -> PASS) and other changes (e.g. shift in skipped
or warnings). Some testcases are known to depend on
functionality with no equivalent in NetBSD and are marked
as
```
相似文章
基于 NetBSD 的研究
本 NetBSD 画廊页面重点展示了各类基于该操作系统的学术及工业研究项目,包括 NASA 的卫星 TCP 实验、KAME IPv6/IPsec 项目以及高速网络演示。
NetBSD GSoC 2026 改进 RAIDframe
这篇文章报道了Google Summer of Code 2026年在NetBSD中改进RAIDframe的工作,包括实现用于多磁盘镜像的N-way RAID 1和添加RAID scrubbing支持。
GEFS on OpenBSD: 早期预览版
GEFS,一个安全可靠且支持快照的文件系统,其早期预览版已移植到 OpenBSD。该移植版本是实验性的,存在若干问题,但已开放供社区测试。
GNU Hurd 2026年第二季度新闻
GNU Hurd的2026年第二季度报告重点介绍了9pfs写入支持、AArch64内核补丁、POSIX msync验证以及各种错误修复的进展。
GCC 16及以后版本中的BPF支持
何塞·马奇西(José Marchesi)和GCC-BPF团队提供了GCC 16中BPF支持的更新,突出了在与LLVM功能对等方面取得的进展,以及内核BPF自测通过率的提升。