返回

文章详情

超越 fork() + exec()

Hacker News2026年6月6日 14:34

[仅限 LWN 订阅者内容] 欢迎来到 LWN.net 以下仅限订阅者的内容已由 LWN 订阅者提供给您。成千上万的订阅者依赖于 LWN 获取来自 Linux 和自由软件社区的最佳新闻。如果您喜欢这篇文章,请考虑订阅 LWN。感谢您访问 LWN.net!自 Unix 最早的日子以来,两个核心进程相关的系统调用是 fork(),创建一个子进程作为父进程的副本,以及 exec(),在当前进程的位置运行新的程序。在 Linux 内核中,这些系统调用更为人知的是 clone() 和 execve(),但核心功能仍然保持不变。虽然这种进程创建模型具有优雅之处,但也有其不足之处。李晨最近提出的向内核添加 “生成模板” 的建议在当前形式下不会被接受,但它可能指向未来一种新的进程创建原语。fork() 是一个相对昂贵的系统调用;它必须为子进程复制整个进程状态(包括内存)。多年来已经进行了许多优化,但 fork 仍然是一个根本上昂贵的操作。更糟的是,fork() 调用通常紧接着一个 exec(),这将丢弃为子进程小心复制的所有内存。多年来,进行了一些尝试(如 vfork())来优化这种情况,但这一模式仍然比应有的要贵。生成模板 李晨的补丁集采用了一种有趣的方法来优化 fork() 和 exec() 的模式。它专注于重复启动运行相同可执行文件的进程的应用程序;例如,想象一个必须重复运行 Git 以获取有关存储库内容信息的程序。在这种情况下,程序可以建立一个模板来加速这些调用,从而将设置成本分摊到多个操作中。这个模板将通过 spawn_template_create() 系统调用创建: struct spawn_template_create_args { __aligned_u64 flags; __s32 execfd; __u32 exec_flags; __aligned_u64 filename; /* 省略的一些字段 */ }; int spawn_template_create(struct spawn_template_create_args *args, size_t args_size); 这个调用将返回一个表示可执行文件模板的文件描述符,可以指定为文件描述符(execfd)或绝对路径(filename),但不能两者都指定。为了创建模板,内核将打开指定的文件,并缓存一堆信息,以便将来更快地运行该文件。有关的应用程序可能会多次运行一个给定的可执行文件,但每次调用在许多方面都是不同的。特定调用的详细信息必须放入这个结构的一个实例中: struct spawn_template_spawn_args { __aligned_u64 flags; __aligned_u64 pidfd; __aligned_u64 argv; __aligned_u64 envp; __aligned_u64 actions; __aligned_u64 actions_len; __aligned_u64 reserved[4]; }; argv 字段是一个指向要传递给程序的参数列表的指针,而 envp 指向其环境。相反,对文件描述符和信号处理的更改是通过 actions 传递的,它是指向数组的指针: struct spawn_template_action { __u32 type; __u32 flags; __s32 fd; __s32 newfd; __aligned_u64 arg; }; 例如,如果在子进程中应该关闭文件描述符四,则相关的 spawn_template_action 结构将其类型设置为 SPAWN_TEMPLATE_ACTION_CLOSE 并将 fd 设置为四。还有其他动作用于复制文件描述符、打开文件、更改工作目录和更改信号处理。填写完 spawn_template_spawn_args 结构后,可以使用以下命令运行新进程: int spawn_template_spawn(int template_fd, struct spawn_template_spawn_args *args, int args_size); 从内部来看,这个系统调用遵循类似于正常 fork()/exec() 路径的过程。李晨注意到,执行新文件时应用的所有正常检查仍然有效。但模板中的缓存信息使整个过程比以前更快。快多少?封面信提供的基准测试结果显示约 2% 的改进,这可能看起来不算很多,但对于符合预期模式的应用程序来说,可能会有所不同。朝向 posix_spawn() 这项工作的最详细评审由 Mateusz Guzik 提出,他表示:“这个问题对我来说很重要,我已经思考了很长时间。整个 fork + exec 习语是糟糕的,需要被淘汰。”他指出,补丁集的重点有点奇怪,因为它没有触及 fork() 部分。他表示,大部分成本就在那里,因此优化工作应该寻求将其从图景中移除。与其复制当前进程,不如“创建一个全新的进程是正确的方法”。Christian Brauner 对此表示赞同

赞助内容

NordVPN Next-gen Antivirus

本站免费、广告极少。如果觉得有帮助,可以请我们喝杯咖啡 —— 任何金额都对持续运营有实际帮助。

请我喝杯咖啡