请解释exec()函数及其家族 [英] Please explain the exec() function and its family

查看:46
本文介绍了请解释exec()函数及其家族的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

什么是 exec()函数及其家族?为什么使用此功能以及其功能如何?

What is the exec() function and its family? Why is this function used and how does its work?

请任何人解释这些功能.

Please anyone explain these functions.

推荐答案

简而言之,在UNIX中,您具有进程和程序的概念.进程是程序在其中执行的环境.

Simplistically, in UNIX, you have the concept of processes and programs. A process is an environment in which a program executes.

UNIX执行模型"背后的简单思想是:是您可以执行两种操作.

The simple idea behind the UNIX "execution model" is that there are two operations you can do.

首先是 fork() ,这将创建一个全新的进程,其中包含当前程序的副本(大部分),包括其状态.这两个过程之间存在一些差异,这使他们能够确定哪个是父级,哪个是子级.

The first is to fork(), which creates a brand new process containing a duplicate (mostly) of the current program, including its state. There are a few differences between the two processes which allow them to figure out which is the parent and which is the child.

第二个是 exec() ,它用一个全新的程序替换了当前进程中的程序.

The second is to exec(), which replaces the program in the current process with a brand new program.

从这两个简单的操作中,就可以构建整个UNIX执行模型.

From those two simple operations, the entire UNIX execution model can be constructed.

要在上面添加更多细节:

To add some more detail to the above:

fork() exec()的使用体现了UNIX的精神,因为它提供了一种非常简单的方式来启动新进程.

The use of fork() and exec() exemplifies the spirit of UNIX in that it provides a very simple way to start new processes.

fork()调用几乎复制了当前进程,几乎在所有方面都相同(并非所有内容被复制,例如某些资源限制实施,但其想法是创建尽可能接近的副本).只有一个进程调用 fork(),但是两个进程从该调用返回-听起来很奇怪,但确实很优雅

The fork() call makes a near duplicate of the current process, identical in almost every way (not everything is copied over, for example, resource limits in some implementations, but the idea is to create as close a copy as possible). Only one process calls fork() but two processes return from that call - sounds bizarre but it's really quite elegant

新进程(称为子进程)获得不同的进程ID(PID),并将旧进程(父进程)的PID作为其父进程PID(PPID).

The new process (called the child) gets a different process ID (PID) and has the PID of the old process (the parent) as its parent PID (PPID).

由于两个进程现在正在运行完全相同的代码,因此它们需要能够分辨出哪个是哪个- fork()的返回代码提供了此信息-子代为0,父级获取子级的PID(如果 fork()失败,则不会创建任何子级,并且父级会获得错误代码).

Because the two processes are now running exactly the same code, they need to be able to tell which is which - the return code of fork() provides this information - the child gets 0, the parent gets the PID of the child (if the fork() fails, no child is created and the parent gets an error code).

这样,父级就知道子级的PID,并且可以与之通信,杀死它,等待它等等(子级始终可以通过调用 getppid()来找到其父级进程).

That way, the parent knows the PID of the child and can communicate with it, kill it, wait for it and so on (the child can always find its parent process with a call to getppid()).

exec()调用用新程序替换了进程的全部当前内容.它将程序加载到当前进程空间中,并从入口点运行它.

The exec() call replaces the entire current contents of the process with a new program. It loads the program into the current process space and runs it from the entry point.

因此,通常经常依次使用 fork() exec()来使新程序作为当前进程的子进程运行.当您尝试运行诸如 find 之类的程序时,shell通常会执行此操作-shell进行分叉,然后子进程将 find 程序加载到内存中,并设置所有标准的命令行参数I/O等.

So, fork() and exec() are often used in sequence to get a new program running as a child of a current process. Shells typically do this whenever you try to run a program like find - the shell forks, then the child loads the find program into memory, setting up all command line arguments, standard I/O and so forth.

但是不需要将它们一起使用.例如,如果程序同时包含父代码和子代码,则完全可以接受不带以下 exec()的程序调用 fork()您所做的操作,每个实现都有限制).

But they're not required to be used together. It's perfectly acceptable for a program to call fork() without a following exec() if, for example, the program contains both parent and child code (you need to be careful what you do, each implementation may have restrictions).

守护进程使用了​​很多(现在仍然使用),这些守护进程只是在TCP端口上侦听,并派生自己的副本来处理特定的请求,而父进程又返回侦听.对于这种情况,该程序同时包含父子代码.

This was used quite a lot (and still is) for daemons which simply listen on a TCP port and fork a copy of themselves to process a specific request while the parent goes back to listening. For this situation, the program contains both the parent and the child code.

类似地,知道自己已完成并且只想运行另一个程序的程序不需要先 exec()然后再子级的wait()/waitpid().他们可以使用 exec()将子级直接加载到当前进程空间中.

Similarly, programs that know they're finished and just want to run another program don't need to fork(), exec() and then wait()/waitpid() for the child. They can just load the child directly into their current process space with exec().

某些UNIX实现具有优化的 fork(),该格式使用它们称为写时复制"的功能.这是一个技巧,可以延迟在 fork()中复制进程空间,直到程序尝试更改该空间中的某些内容为止.这对于仅使用 fork()而不使用 exec()的程序很有用,因为它们不必复制整个进程空间.在Linux下, fork()仅复制页表和新的任务结构,而 exec()将完​​成分离"任务.记忆这两个过程.

Some UNIX implementations have an optimized fork() which uses what they call copy-on-write. This is a trick to delay the copying of the process space in fork() until the program attempts to change something in that space. This is useful for those programs using only fork() and not exec() in that they don't have to copy an entire process space. Under Linux, fork() only makes a copy of the page tables and a new task structure, exec() will do the grunt work of "separating" the memory of the two processes.

如果在 fork 之后调用 exec (这是大多数情况),这将导致对进程空间的写操作,并且然后在允许修改之前将其复制给子进程.

If the exec is called following fork (and this is what happens mostly), that causes a write to the process space and it is then copied for the child process, before modifications are allowed.

Linux还有一个 vfork(),它甚至经过了优化,在两个进程之间共享着几乎所有的东西.因此,子代的操作受到某些限制,父代会暂停直到子代调用 exec() _exit().

Linux also has a vfork(), even more optimised, which shares just about everything between the two processes. Because of that, there are certain restrictions in what the child can do, and the parent halts until the child calls exec() or _exit().

父级必须停止(不允许子级从当前函数返回),因为两个进程甚至共享同一堆栈.对于经典的 fork()用例,紧随其后的是 exec().

The parent has to be stopped (and the child is not permitted to return from the current function) since the two processes even share the same stack. This is slightly more efficient for the classic use case of fork() followed immediately by exec().

请注意,有一整套 exec 调用( execl execle execve 等)),但上下文中的 exec 表示它们中的任何一个.

Note that there is a whole family of exec calls (execl, execle, execve and so on) but exec in context here means any of them.

下图说明了典型的 fork/exec 操作,其中 bash shell用于通过 ls 命令列出目录:

The following diagram illustrates the typical fork/exec operation where the bash shell is used to list a directory with the ls command:

+--------+
| pid=7  |
| ppid=4 |
| bash   |
+--------+
    |
    | calls fork
    V
+--------+             +--------+
| pid=7  |    forks    | pid=22 |
| ppid=4 | ----------> | ppid=7 |
| bash   |             | bash   |
+--------+             +--------+
    |                      |
    | waits for pid 22     | calls exec to run ls
    |                      V
    |                  +--------+
    |                  | pid=22 |
    |                  | ppid=7 |
    |                  | ls     |
    V                  +--------+
+--------+                 |
| pid=7  |                 | exits
| ppid=4 | <---------------+
| bash   |
+--------+
    |
    | continues
    V

这篇关于请解释exec()函数及其家族的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆