0

我需要从服务器分叉一个 exec。由于我的服务器内存占用很大,我打算使用vfork()/linux clone()。我还需要为stdin/ stdout/打开管道stderr。这是否允许使用clone()/ vfork()

4

2 回答 2

2

从标准:

[..] 如果创建的进程修改了除用于存储返回值vfork()的类型变量以外的任何数据,或从被调用的函数返回,或在成功调用或之前调用任何其他函数,则行为未定义函数族之一。pid_tvfork()vfork()_exit()exec

调用setuidor之类的函数的问题pipe在于它们可能会影响父进程和子进程之间共享的地址空间中的内存。如果您之前需要做任何事情exec,最好的方法是编写一个小的 shim 进程来执行您需要的任何操作,然后exec转到最终的子进程(可能是通过 提供的参数argv)。

shim.c
======

enum {
    /* initial arguments */
    ARGV_FILE = 5, ARGV_ARGS
};
int main(int argc, char *argv[]) {
    /* consume instructions from argv */
    /* setuid, pipe() etc. */
    return execvp(argv[ARGV_FILE], argv + ARGV_ARGS);
}
于 2012-07-24T12:20:29.473 回答
1

我会改用clone()标志CLONE_VFORK|CLONE_VM;有关详细信息,请参见man 2 clone

因为CLONE_FILES没有设置,所以子进程有自己的文件描述符,可以关闭和打开标准描述符,完全不影响父进程。

因为克隆的进程是一个单独的进程,它有自己的用户和组 ID,所以通过setresgid()and设置它们setresuid()(可能调用setgroups()initgroups()首先设置额外的组 - 请参阅man 2 setresuidman 2 setgroupsman 3 initgroups了解详细信息) 根本不会影响父母。

CLONE_VFORK|CLONE_VM标志意味着这应该clone()表现得像vfork(),子进程在与父进程相同的内存空间中运行,直到execve()调用。

这种方法避免了使用中间可执行文件时的延迟——它非常重要——但这种方法完全是 Linux 特定的。

于 2012-07-25T12:41:21.743 回答