c-exec和execve等exec系列系统调用的函数之间有什么区别



我最近一直在学习一门系统编程课程,我完成了系统调用exec()execve()到目前为止,我还找不到这两者之间的任何区别,甚至维基百科也没有给出明确的解释,所以exec()execve()间有区别吗。

请有人简要描述exec家族系统调用,如execl()Executiv()xecle()execvp()。

没有exec系统调用——这通常用于将所有execXX调用称为一个组。它们基本上都做相同的事情:将一个新程序加载到当前进程中,并为其提供参数和环境变量。不同之处在于程序的查找方式、参数的指定方式以及环境的来源。

  • 名称中带有v的调用采用一个数组参数来指定新程序的argv[]数组。自变量的末尾由包含NULL的数组元素表示。

  • 名称中带有l的调用将新程序的参数作为函数本身的可变长度参数列表。参数的末尾由(char *)NULL参数表示。您应该始终包括类型转换,因为NULL被允许是一个整数常量,并且在调用变元函数时默认的参数转换不会将其转换为指针。

  • 名称中有e的调用需要一个额外的参数(在l的情况下是一个或多个参数)来提供新程序的环境;否则,程序将继承当前进程的环境。这是以与argv数组相同的方式提供的:execve()的数组,execle()的独立自变量。

  • 如果程序中没有目录(即不包含/字符),则名称中带有p的调用会搜索PATH环境变量以查找程序。否则,程序名称始终被视为可执行文件的路径。

  • FreeBSD5.2添加了另一个变体:execvP(大写P)。这与execvp()类似,但它不是从PATH环境变量中获得搜索路径,而是函数的显式参数:

int execvP(const char *file, const char *search_path, char *const argv[]);

使用man exec并读取:

The execv(), execvp(), and execvpe() functions provide an array of pointers to 
null-terminated strings that represent the argument list available to the new program. 
The first argument, by convention, should point to the filename associated with the file 
being executed. The array of pointers must be terminated by a NULL pointer. 

execv

int execv(const char *path, char *const argv[]);

所以你传递一个数组作为参数

int execle(const char *path, const char *arg,
..., char * const envp[]);

几乎相同,但不是作为数组,而是作为值(字符串)的列表,后面跟着一个指定环境的数组。

此处:

int execvp(const char *file, char *const argv[]);

您正在调用一个没有路径的文件,因此它希望您在调用之前已经处于正确的path中。

最后但同样重要的是:

int execve(const char *filename, char *const argv[],
char *const envp[]);

与前一个类似,但现在有两个数组,用于参数和环境变量。

由于所有这些函数都属于exec()家族,因此,根据extra characters,让我differentiate具有以下含义,

1.execve():

p:不存在=>要运行的程序名称将取自pathname

v:spresent=>参数将作为array传递

e:present=>环境将取自envp argument

2.execle():

p:不存在=>要运行的程序名称将取自pathname

l:present=>参数将作为list传递

e:present=>环境将取自envp argument

3.execlp():

p:present=>要运行的程序的名称将取自指定的filename,或者系统将PATH变量中的search for program file

l:present=>参数将作为list传递

e:不存在=>环境将取自caller's environ

4.execvp():

p:present=>要运行的程序的名称将取自指定的filename,或者系统将取自PATH变量中的search for program file

v:spresent=>参数将作为array传递

e:不存在=>环境将取自caller's environ

5.execv():

p:不存在=>要运行的程序名称将取自pathname

v:spresent=>参数将作为array传递

e:不存在=>环境将取自caller's environ

6.execl():

p:不存在=>要运行的程序名称将取自pathname

l:present=>参数将作为list传递

e:不存在=>环境将取自caller's environ

主要理念

exec()函数族用新的进程映像替换现有的进程映像。这与fork()系统调用有明显的不同,在fork系统调用中,父进程和子进程共存于内存中。

exec()函数族

int execv (const char *filename, char *const argv[])

文件名是新进程映像的文件。

argv表示一个以null结尾的字符串数组。此数组的最后一个元素必须是空指针。

int execl (const char *filename, const char *arg0, …)

与execv相同,但参数是作为单独的字符串(用逗号分隔)而不是数组/向量提供的。

int execve (const char *filename, char *const argv[], char *const env[])

与execv相同,但它允许为新的进程映像指定环境变量。

int execle (const char *filename, const char *arg0, …, char *const env[])

与execl相同,但它允许为新的进程映像指定环境变量。

int execvp (const char *filename, char *const argv[])

与execv函数相同,但如果文件名不包含斜杠,它会搜索标准环境变量PATH来查找文件名。

以下是标准环境变量的列表:

https://www.gnu.org/software/libc/manual/html_node/Standard-Environment.html#Standard-环境

int execlp (const char *filename, const char *arg0, …)

与execl函数相同,只是if作为execvp函数执行文件名搜索。

备注

在Linux系统中,如果在shell或终端上键入envprintenv,您将获得一个标准环境变量列表。

这些函数的参数不同。

函数execl、execlp和execle要求将新程序的每个命令行参数指定为单独的参数。
  • execv、execvp和execve,我们必须构建一个指向参数的指针数组,而这个数组的地址就是这三个函数的参数。

  • execve、execle函数允许我们将指针传递给指向环境字符串的指针数组。其他四个函数在调用过程中使用environ变量将现有环境复制到程序中。

  • 字母p表示函数采用文件名参数,并使用PATH环境变量查找可执行文件
  • 字母l表示函数采用参数列表,并且与字母v互斥,这意味着它采用argv[]向量
  • 字母e表示函数采用envp[]数组,而不是使用当前环境。

  • 新程序从调用过程中继承了以下附加功能。

  • Process ID and the Parent Process ID
    Real user ID and Real Group ID
    Supplementary group IDs
    Process group ID
    Session ID
    Controlling terminal
    Time left until alarm clock
    Current working directory
    Root directory
    File mode creation mask
    File locks
    Process signal mask
    Pending signals
    Resource limits
    Values for tms_utime, tms_stime, tms_cutime, and tms_cstime.
    
    • 实际用户ID和实际组ID在整个exec中保持不变,但有效ID可以更改,这取决于所执行程序文件的设置用户ID和设置组ID位的状态

    要回答问题的第一部分,特别是在Linux的上下文中,只有一个系统调用,它是execve(而不是exec)。所谓的"exec家族"的其余部分(execlexecleExecutivexecve等)都是内核系统调用的GLIBC包装器,也就是execve

    在exec家族中,有些函数的功能和调用方式略有不同:

    1. 名称中包含字母p的函数(execvpexeclp)接受程序名称,并在当前执行路径中按该名称搜索程序;不包含p的函数必须被赋予要执行的程序的完整路径。

    2. 名称中包含字母v的函数(execvexecvp和execve)接受新程序的参数列表,将其作为指向字符串的以NULL结尾的指针数组。包含字母l(execlexeclp和execle)使用C语言的varargs机制接受参数列表。

    3. 名称中包含字母e的函数(execveexecle)接受一个附加参数,即环境变量数组。论点应该是指向字符串的以NULL结尾的指针数组。每个字符串应当具有CCD_ 65的形式。

    最新更新