关于fork和execve系统调用
据说fork
系统调用会创建调用进程的克隆,然后(通常)子进程会发出execve
系统调用来更改其映像并运行新进程。为什么这两步?关于fork和execve系统调用
顺便说一句,execve
代表什么?
每一步都比较简单。在Unix中,你的进程有两个部分 - 一个带有应用程序代码的只读存储区(“text”)和一个可读写的存储区(“data”)。
叉克隆了读写区域,使文本页面保持独立。您现在有两个进程运行相同的代码。它们的区别在于寄存器值 - 来自分支的返回值 - 它将父项与子项分开。
exec执行取代文本页面,只留下数据页面。有很多形式的执行,取决于你传递给它的环境信息。有关变体的其他列表,请参阅http://linux.die.net/man/3/exec。
- EXEC:执行新的处理
- ν:的参数
- E使用阵列:指定以及环境
EXEC的其它变化比比皆是:
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg,..., char * const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
- l:列出功能上的参数
- 号码:使用$ PATH定位可执行文件
的“高管”系列函数替换当前的进程映像(从那里它被称为)有一个新的进程映像,因此调用图像被替换新的过程映像。例如。如果要从shell(/ bin/sh或/ bin/csh)运行'ls'命令,那么shell将分叉到一个新的进程,然后执行ls。一旦ls命令退出,它将控制返回到父进程,在本例中是父进程。
如果没有fork功能,那么shell会被'ls'进程所取代,当退出时会给你一个无法访问的终端,因为shell的内存映像在exec调用ls后被替换。
对于'exec'家族的变体,请看0x6adb015的答案。
两步骤的理由是灵活性。在这两个步骤之间,您可以修改新执行的程序将继承的子进程的上下文。
你可能要改变的,有些事情是:
- 文件描述符
- 用户/组ID
- 进程组和会话ID
- 当前目录
- 资源限制
- 调度优先级和亲和力
- 文件创建掩码如果你想让他们在孩子不同的设置(的umask)
如果没有分裂fork和exec,而是有一个单一菌种类的系统调用,那就需要采取的参数为这些过程的属性处理。例如,请参阅Windows API中的CreateProcess参数列表。
使用fork/exec,您可以在执行新程序之前更改任何可以继承的子进程属性。
设置文件描述符是儿童过程上下文中更常见的事情之一。如果要捕获程序的输出,通常会使用pipe(2)系统调用在父项中创建一个管道,在fork(2)之后,将关闭父进程中的写入结束并关闭在调用execve(2)之前读取子进程的结尾。 (您还将使用dup(2)将管道的子端设置为文件描述符1(标准输出))。在单个系统调用中,这可能是不可能的或者是限制性的。
真的,你不能用fork()做任何错误,因为它没有任何参数。它可以更简单吗? – 0x6adb015 2009-05-29 14:20:19
Umm,exec取代了整个mm,而不仅仅是“文本”......参见/usr/src/linux/fs/exec.c和/usr/src/linux/fs/binfmt_elf.c – ephemient 2009-05-29 15:25:04