exec , execl , execle , execlp , execv , execve , execvp , execvp , exect 或 fexecve 子例程

用途

执行文件。

标准 C 库 (libc.a)

语法

#include <unistd.h>
extern 
char **environ;
int execl (
 Path, 
 Argument0 [, Argument1, ...], 0)
const char *Path, *Argument0, *Argument
1, ...;
int execle (
 Path, 
 Argument0 [, Argument1, ...], 0,
        
 EnvironmentPointer)
const 
char *Path, *Argument0, *Argum
ent
1, ...;
char *const EnvironmentPointer[ ];
int execlp (
 File, 
 Argument0 [, Argument1
, ...], 0)
const char *File, *Argument0, *Argument
1, ...;
int execv (
 PathArgumentV)
const char *Path;
char *const ArgumentV[ ];
int execve (
 PathArgumentV,
        
 EnvironmentPointer)
const char *Path;
char 
*const ArgumentV[ ], *EnvironmentPointer
[ ];
int execvp (
 FileArgumentV)
const char *File;
char *const ArgumentV[ ];
int exect (
 Path,
 ArgumentV,
 EnvironmentPointer)
char *Path, *ArgumentV, *EnvironmentPointer [ ];
int fexecve (FileDescriptor, ArgumentV, EnvironmentPointer)
int FileDescriptor;
char *const ArgumentV[ ], *EnvironmentPointer[ ];

描述

所有形式的 执行 子例程在调用过程中执行一个新程序。 执行 子例程不会创建新进程,但会将当前程序覆盖为一个新程序,该程序称为 新进程映像。 新进程图像文件可以是以下三种文件类型之一:

  • XCOFF 文件格式的可执行二进制文件。
  • 包含 shell 过程的可执行文本文件 (只有 外塞普外塞夫普 子例程才允许此类型的新进程映像文件)。
  • 指定要运行的可执行二进制文件或 shell 过程的文件。

费克塞夫 子例程等同于 外显 子例程,只是 fexecve 子例程将打开文件的文件描述符作为第一个参数而不是路径名来执行。 但是,以下情况适用:

注意:
  • 如果文件是在打开操作后删除的 shell 过程,那么 费克塞夫 子例程将启动 shell ,但 shell 找不到该文件。
  • 如果文件是一个 shell 过程,并且文件的父目录在文件打开操作后被删除,那么 费克塞夫 子例程将返回 ENOENT 错误代码。
  • 费克塞夫 子例程不检查基于角色的访问控制 (RBAC) 执行许可权。

新进程映像从呼叫进程映像继承下列属性: 会话成员资格,补充组标识,进程信号掩码和暂挂信号。

提及的最后一种类型由具有以下语法的头进行识别:

#! Path [String]

#! 是文件 幻数,用于标识文件类型。 要执行的文件的路径名是由 路径 参数指定的。 字符串 参数是一个可选字符串,不包含任何制表符或空格字符。 如果指定了此字符串,那么它将作为新进程映像文件的名称前面的参数传递到新进程。 头必须以换行字符终止。 调用时,新进程会将路径参数作为 ArgumentV[0] 传递。 如果在新进程映像文件中指定了字符串参数,则执行子程序会将 ArgumentV[0] 设置为字符串路径参数值的串联值。 传递的其余参数与传递给 执行 子例程的那些参数相同。

执行 子例程尝试取消此进程未完成的 异步 I/O 请求数 。 如果无法取消异步 I/O 请求,那么应用程序将被阻止,直到这些请求完成为止。

除了 执行 子例程没有显式库路径参数之外, 执行 子例程与 负载 子例程类似。 相反, exec 子例程使用 LIBPATHLD_LIBRARY_PATH 环境变量。 设置时,将使用 LIBPATH 变量以支持 LD_LIBRARY_PATH; 否则,将使用 LD_LIBRARY_PATH 。 当运行 执行 子例程的程序具有比调用程序 (例如, 苏伊德 程序) 更多的特权时,忽略这些库路径变量。

包括 出口 子例程是为了与使用 跟踪 命令跟踪的较旧程序兼容。 正在执行的程序将强制进入硬件单步骤方式。

注: 出口 在 64 位方式下不受支持。
注: 当前, "图形库" 程序不能与另一个 "图形库" 程序重叠。 覆盖程序可以是一个非图形程序。 有关其他信息,请参阅 /usr/lpp/GL/README 文件。

参数

表 1. 参数
描述
路径 指定一个指向新进程图像文件的路径名的指针。 如果系统上安装了网络文件系统 (NFS) ,那么此路径可以跨入另一个节点。 在继续之前,会将数据复制到本地虚拟内存中。
文件 指定一个指向新进程映像文件的名称的指针。 除非 文件 参数是完整路径名,否则该文件的路径前缀是通过搜索 路径 环境变量中指定的目录获得的。 初始环境是由 shell 提供的。
注: 外塞普 子例程和 外塞夫普 子例程采用 文件 参数,但 执行 子例程的其余部分采用 路径 参数。 (有关该环境的信息,请参阅 环境 杂项设施和 命令。)
Argument0 [, Argument1, ...] 指向以 null 结束的字符串。 这些字符串构成可用于新流程的自变量列表。 根据约定,至少必须存在 Argument0 参数,并且该参数必须指向与 路径 参数或其最后一个组件相同的字符串。
ArgumentV 指定指向以 null 结束的字符串的指针数组。 这些字符串构成可用于新进程的自变量列表。 按照约定, ArgumentV 参数必须至少具有一个元素,并且必须指向与 Path 参数或其最后一个组件相同的字符串。 ArgumentV 参数的最后一个元素是空指针。
EnvironmentPointer 指向以 null 结束的字符串的指针数组。 这些字符串构成了新流程的环境。 EnvironmentPointer 参数的最后一个元素是空指针。
FileDescriptor 指定要执行的已打开文件的文件描述符。

运行 C 程序时,它将接收到以下参数:

main (ArgumentCount, ArgumentV, EnvironmentPointer)
int ArgumentCount;
char *ArgumentV[ ], *EnvironmentPointer[ 
];

在此示例中, ArgumentCount 参数是自变量计数,而 ArgumentV 参数是指向自变量本身的字符指针的数组。 按照惯例,参数ArgumentCount的值至少为 1,参数ArgumentV[0] 指向一个包含新处理图像文件名称的字符串。

C 语言程序的 例程会自动以运行时启动例程开始。 此例程设置 environ 全局变量,以便它指向传递到 EnvironmentPointer中的程序的环境数组。 您可以通过在程序中包含以下声明来访问此全局变量:

extern char **environ;

执行 执行外塞普 外塞夫普 子例程使用 恩维龙 全局变量来将调用进程当前环境传递到新进程。

在调用过程中打开的文件描述符保持打开状态,但设置了 在执行时关闭 标志的文件描述符除外。 对于那些保持打开的文件描述符,文件指针未更改。 (有关文件控制的信息,请参阅 fcntl.h 文件。)

新的进程映像中的状态转换描述符和消息目录描述符未定义。 对于新进程,在启动时运行相当于 setlocale 子例程的值,为其类别指定 全部 (LC_ALL) 值,并为其语言环境指定 "C" 值。

如果新程序需要共享库,那么 执行 子例程将查找,打开每个库并将它们装入到新进程地址空间中。 执行 的签发者正在使用的共享库的引用计数已递减。 将在 LIBPATH 环境变量中列出的目录中搜索共享库。 如果这些文件中有任何一个是远程文件,那么会将数据复制到本地虚拟内存中。

执行 子例程将所有捕获的信号重置为缺省操作。 导致缺省操作的信号在 执行 子例程之后继续执行此操作。 被忽略的信号仍然被忽略,信号掩码保持不变,并且信号堆栈状态被重置。 (有关信号的信息,请参阅 签名 子例程。)

如果新进程映像文件的SetUserID模式位被设置,执行子程序就会将新进程的有效用户 ID 设置为新进程映像文件的所有者 ID。 同样,如果新进程映像文件的SetGroupID模式位被设置,新进程的有效组 ID 将被设置为新进程映像文件的组 ID。 新进程的实际用户标识和实际组标识与调用进程的用户标识和实际组标识保持相同。 (有关 SetID 方式的信息,请参阅 chmod 子例程。)

执行 操作结束时,该过程的已保存用户标识和已保存组标识始终分别设置为该过程的有效用户标识和有效组标识。

如果设置了一个或两个标识方式位,并且要执行的文件是远程文件,那么文件用户和组标识将在服务器上进行出站转换。 然后,将它们传输到客户机节点,并根据入站转换表对其进行转换。 这些已翻译的标识将成为新进程的用户和组标识。

对 shell 脚本的 注: 设置标识设置标识 投标不会影响最终执行的进程的用户或组标识。

对新进程禁用概要分析。

新流程将从调用流程继承以下属性:

  • Nice 值 (请参阅 getpriority 子例程, 设置优先级 子例程, 子例程)
  • 进程标识
  • 父进程标识
  • 进程组标识
  • 塞马季 值 (请参阅 塞地布 子例程)
  • tty 组标识 (请参阅 退出退出 退出 (_出口) 子例程, 签名 子例程)
  • 跟踪 标志 (请参阅 跟踪 子例程的请求 0)
  • 直到闹钟信号的剩余时间 (请参阅 incinterval 子例程, setitimer 子例程和 闹铃 子例程)
  • 当前目录
  • 根目录
  • 文件方式创建掩码 (请参阅 Umask 子例程)
  • 文件大小限制 (请参阅 乌勒明 子例程)
  • 资源限制 (请参阅 格特尔林特 子例程, 塞特尔林特 子例程和 vlimit 子例程)
  • tms_utime,tms_stime,tms_cutimetms_ctime特姆斯 结构的字段 (请参阅 时代 子例程)
  • 登录用户标识

成功完成后, 执行 子例程将标记为要更新st_atime文件的字段。

示例

  1. 要运行命令并向其传递参数,请输入:
    execlp("ls", "ls", "-al", 0);
    外塞普 子例程在 路径 环境变量中列出的每个目录中搜索 命令,然后用此命令覆盖当前的进程映像。 除非无法执行 命令,否则将不返回 外塞普 子例程。
    注: 此示例不运行 shell 命令处理器,因此由 shell 解释的操作 (例如,在文件名中使用通配符) 无效。
  2. 要运行 shell 以解释命令,请输入:
    execl("/usr/bin/sh", "sh", "-c", "ls -l *.c", 
    0);
    这会运行带有 -c 标志的 命令,该标志指示以下参数是要解释的命令。 此示例使用 execl 子例程而不是 execlp 子例程,因为指定了完整路径名 /usr/bin/sh ,因此不需要进行路径搜索。

    在子进程中运行 shell 命令通常比简单地使用 执行 子例程更有用,如此示例中所示。 执行此操作的最简单方法是使用 系统 子例程。

  3. 以下是一个新进程文件的示例,该文件指定了要运行的程序:
    #! /usr/bin/awk -f
    { for (i = NF; i > 0; --i) print $i }
    如果此文件已命名reverse,在命令行上输入以下命令:
    reverse chapter1 chapter2
    此命令运行以下命令:
    /usr/bin/awk -f reverse chapter1 chapter2
    注: 执行 子例程仅使用新进程映像文件的第一行,而忽略它的其余部分。 此外, 奥克 命令将跟在 # (井号) 后面的文本解释为注释。

返回值

在成功完成后, 执行 子例程不会返回,因为调用进程映像由新进程映像覆盖。 如果执行子程序返回调用进程,则返回值为-1,并设置errno全局变量来标识错误。

错误代码

如果 执行 子例程不成功,那么它将返回以下一个或多个错误代码:

表 2。 如果 exec 子例程不成功,那么错误代码为
描述
EACCES 新进程映像文件不是一个普通文件。
EACCES 新进程映像文件的方式将拒绝执行许可权。
ENOEXEC 执行 子例程既不是 外塞普 子例程也不是 外塞夫普 子例程。 新进程映像文件具有相应的访问许可权,但其标题中的幻数无效。
ENOEXEC 新进程图像文件的头中有有效的幻数,但该头已损坏或对于要运行该文件的机器而言不正确。
ETXTBSY 新进程图像文件是一个纯过程 (共享文本) 文件,当前由某个进程打开以进行写入。
ENOMEM 新进程需要的内存超过系统施加的最大值 ( MAXMEM 编译器选项) 所允许的内存量。
E2BIG 新进程参数列表中的字节数大于系统强加的限制。 此限制是系统可配置值,可由超级用户或系统组用户使用 SMIT 进行设置。 有关详细信息,请参阅 内核可调参数
EFAULT PathArgumentV EnvironmentPointer参数指向进程地址空间之外。
EPERM 在进程映像文件上设置SetUserIDSetGroupID模式位。 服务器或客户机上的转换表不允许此用户或组标识的转换。

如果 执行 子例程由于需要路径名解析的条件而不成功,那么它将返回以下一个或多个错误代码:

表 3。 如果 exec 子例程由于需要路径名解析的条件而失败,那么错误代码
描述
EACCES 对路径前缀的组件的搜索许可权被拒绝。 由于安全安装,访问可能被拒绝。
EFAULT 路径 参数指向进程的已分配地址空间之外的位置。
EIO 操作期间发生输入/输出 (I/O) 错误。
ELOOP 在转换 路径 参数时迂到过多的符号链接。
ENAMETOOLONG 路径名的组件超过 255 个字符,并且进程具有 不允许截断 属性 (请参阅 乌勒明 子例程) ,或者整个路径名超过 1023 个字符。
ENOENT 路径前缀的某个组件不存在。
ENOENT 已命名符号链接,但它所引用的文件不存在。
ENOENT 路径名为空。
ENOTDIR 路径前缀的组件不是一个目录。
ESTALE 该进程的根目录或当前目录位于已卸载的虚拟文件系统中。

此外,在旧进程映像被覆盖后,使用新进程文件时可能会发生一些错误。 这些错误包括设置新数据和堆栈寄存器方面的问题,映射共享库方面的问题,或者读取新进程文件方面的问题。 因为不可能返回到调用过程,所以当发生其中一个错误时,系统会将 SIGKILL 信号发送到过程。

如果在映射共享库时发生错误,那么在将信号 SIGKILL 发送到进程之前,会将描述错误原因的错误消息写至标准错误。 如果无法映射共享库,那么子例程将返回下列其中一个错误代码:

表 4。 无法映射共享库时的错误代码
描述
ENOENT 共享库文件的路径名中的一个或多个组件不存在。
ENOTDIR 共享库文件的路径前缀的组件不是一个目录。
ENAMETOOLONG 共享库文件的路径名前缀的组件超过了 255 个字符,或者整个路径名超过了 1023 个字符。
EACCES 对共享库文件的路径前缀中列出的目录的搜索许可权被拒绝。
EACCES 共享库文件方式拒绝执行许可权。
ENOEXEC 共享库文件具有相应的访问许可权,但是它的头中的幻数无效。
ETXTBSY 共享库文件当前已打开,供其他某个进程写入。
ENOMEM 共享库需要的内存超过系统施加的最大值所允许的内存量。
ESTALE 进程根目录或当前目录位于已卸载的虚拟文件系统中。
EPROCLIM 如果 WLM 正在运行,那么可能已达到类中的进程数,线程数或登录数的限制。

如果 费克塞夫 子例程不成功,那么它还可能返回下列其中一个错误代码:

表 5。 如果 fexecve 子例程不成功,那么错误代码为
描述
EBADF FileDescriptor 参数未指定有效的打开文件描述符。
ENOENT FileDescriptor 参数指向 shell 过程,但文件的原始父目录已被删除。

如果在系统上安装了 NFS ,那么如果以下情况成立,那么 exec 子例程也可能失败:

表 6。 系统上安装了 NFS 时的错误代码
描述
ETIMEDOUT 连接已超时。