关于fork和execve系统调用

问题描述:

据说fork系统调用会创建调用进程的克隆,然后(通常)子进程会发出execve系统调用来更改其映像并运行新进程。为什么这两步?关于fork和execve系统调用

顺便说一句,execve代表什么?

每一步都比较简单。在Unix中,你的进程有两个部分 - 一个带有应用程序代码的只读存储区(“text”)和一个可读写的存储区(“data”)。

叉克隆了读写区域,使文本页面保持独立。您现在有两个进程运行相同的代码。它们的区别在于寄存器值 - 来自分支的返回值 - 它将父项与子项分开。

exec执行取代文本页面,只留下数据页面。有很多形式的执行,取决于你传递给它的环境信息。有关变体的其他列表,请参阅http://linux.die.net/man/3/exec

+0

真的,你不能用fork()做任何错误,因为它没有任何参数。它可以更简单吗? – 0x6adb015 2009-05-29 14:20:19

+6

Umm,exec取代了整个mm,而不仅仅是“文本”......参见/usr/src/linux/fs/exec.c和/usr/src/linux/fs/binfmt_elf.c – ephemient 2009-05-29 15:25:04

  • 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(标准输出))。在单个系统调用中,这可能是不可能的或者是限制性的。