linux exec函数,python中exec函数的作用

1. exec函数的说明

fork ) )函数通过系统调用创建与原始进程父进程)几乎相同的进程。 子进程是父进程的副本,获取父进程的数据区域、堆和堆栈等资源的副本。 请注意,子进程保留了上述存储区域的“复制”。 这意味着父子进程不共享这些存储空间。 由于linux将父进程的地址空间内容复制到子进程中,因此子进程是独立的地址空间。 也就是说,这两个过程会做完全一样的事情。

在fork后的子进程中使用exec函数系列可以加载和运行其他程序。 子进程将替换原始进程,并做与父进程不同的事情。

exec函数系列可以根据指定的文件名或目录名查找可执行文件,以代替原始调用过程中的数据段、代码段和堆叠栈段。 运行后,除进程号外,原始调用进程的所有内容都被新程序的内容替换。 此外,这里的可执行文件可以是二进制文件,也可以是Linux上的任意可执行脚本文件。

在Linux上使用exec函数系列主要有以下两种情况

如果进程确定自己对系统和用户不再有任何贡献,它可以调用exec函数系列来播放自己;如果一个进程想运行另一个进程,它可以调用fork函数来创建新进程,然后将任何exec函数3.exec函数族语法

实际上,Linux没有exec函数,有六个以exec开头的函数族。 下表介绍了exec函数族的六个成员函数的语法。

这六个函数在使用函数名称和语法的规则方面存在细微差异,但我们将比较并介绍可执行文件的搜索方式、参数传递方式和环境变量。

如何搜索:上表中的前四个函数都按完整的文件目录路径或绝对路径进行搜索。 最后两个函数以p结尾的两个函数)只能提供文件名,系统将自动从环境变量“$PATH”指示的路径中进行搜索。 传递参数:有两种方法:一种是一次枚举一个参数,另一种是将所有参数组合成一个指针数组进行传递。 其中字符“l”表示各个枚举的方式,字符“v”表示将所有参数一起传递给指针数组,将该数组的开头地址作为参数传递,在请求数组中的最后一个指针时为NULL ) )环境以” e “结尾的两个函数可以在envp[]中指定当前进程使用的环境变量,并替换该进程继承的所有环境变量。 3.PATH环境变量的说明

PATH环境变量包含目录表,系统通过由PATH环境变量定义的路径搜索执行代码。 PATH环境变量的定义包括目录之间的“; ”。分隔符以“.”结尾。 PATH环境变量的定义位于用户的. profile或. bash_profile中。 以下示例定义了将/hsdxtg、/usr/hsdxtg和当前目录这三个目录指定为搜索执行代码的PATH环境变量。

PATH=/hsdxtg:/usr/hsdxtg .

导出$ path

4 .过程中环境变量的说明

在Linux上,shell进程是所有执行代码的父进程。 执行代码运行时,shell进程会fork子进程,然后调用exec函数执行执行代码。 Sehll进程堆栈包含该用户下的所有环境变量,如果使用四个没有” e “的函数重新生成执行代码,Sehll进程会将所有环境变量复制到生成的新进程中。 如果使用带有” e “的两个函数,则新进程不会继承shell进程的环境变量,envp[]数组会自己设置环境变量。

5.exec函数家族关系

实际上,这六个函数中只有execve是真正的系统调用,其他五个是库函数,它们最终调用一个名为execve的系统调用。 调用关系如下图所示。

6.exec函数系列调用的示例如下

char *const ps_argv[]={‘ps ‘,’-o ‘,’ pid,ppid,session,tpgid,comm,NULL’};

char * const PS _ envp [ ]={ ‘ path=/hsdxtg :/usr/hsdxtg ‘,’ TERM=console ‘,NULL};

execl )/hsdxtg/ps )、PS )、-o )、) pid、ppid、pgrp、session、tpgid、comm )、NULL );

execv )/hsdxtg/PS )、ps_argv );

execle )/hsdxtg/ps )、PS )、-o )、) pid、ppid、pgrp、session、tpgid、comm )、NULL、ps_envp );

ht:26px”>execve”/hsdxtg/ps”, ps_argv, ps_envp);

execlp”ps”, “ps”, “-o”, “pid,ppid,pgrp,session,tpgid,comm”, NULL);

execvp”ps”, ps_argv);

请注意exec函数族形参展开时的前两个参数,第一个参数是带路径的执行码(execlp、execvp函数第一个参数是无路径的,系统会根据PATH自动查找然后合成带路径的执行码),第二个是不带路径的执行码,执行码可以是二进制执行码和Shell脚本。

7.exec函数族使用注意点

在使用exec函数族时,一定要加上错误判断语句。因为exec很容易执行失败,其中最常见的原因有:

找不到文件或路径,此时errno被设置为ENOENT。数组argv和envp忘记用NULL结束,此时errno被设置为EFAULT。没有对用可执行文件的运行权限,此时errno被设置为EACCES。 8.exec后新进程保持原进程以下特征

环境变量(使用了execle、execve函数则不继承环境变量);

Ÿ进程ID和父进程ID;

实际用户ID和实际组ID;

附加组ID;

进程组ID;

会话ID;

控制终端;

当前工作目录;

根目录;

文件权限屏蔽字;

文件锁;

进程信号屏蔽;

未决信号;

资源限制;

tms_utime、tms_stime、tms_cutime以及tms_ustime值。

对打开文件的处理与每个描述符的exec关闭标志值有关,进程中每个文件描述符有一个exec关闭标志FD_CLOEXEC),若此标志设置,则在执行exec时关闭该描述符,否则该描述符仍然打开。除非特地用了fcntl设置了该标志,否则系统的默认操作是在exec后仍保持这种描述符打开,利用这一点可以实现I/O重定向。

9.各个函数使用举例

1 #ifdef HAVE_CONFIG_H 2 #include <config.h> 3 #endif 4 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <unistd.h> 8 #include <string.h> 9 #include <errno.h> 10 11 int mainint argc, char *argv[]) 12 { 13 //以NULL结尾的字符串数组的指针,适合包含v的exec函数参数 14 char *arg[] = {“ls”, “-a”, NULL}; 15 16 /** 17 * 创建子进程并调用函数execl 18 * execl 中希望接收以逗号分隔的参数列表,并以NULL指针为结束标志 19 */ 20 if fork) == 0 ) 21 { 22 // in clild 23 printf “1————execl————\n” ); 24 if execl “/hsdxtg/ls”, “ls”,”-a”, NULL ) == -1 ) 25 { 26 perror “execl error ” ); 27 exit1); 28 } 29 } 30 31 /** 32 *创建子进程并调用函数execv 33 *execv中希望接收一个以NULL结尾的字符串数组的指针 34 */ 35 if fork) == 0 ) 36 { 37 // in child 38 printf”2————execv————\n”); 39 if execv “/hsdxtg/ls”,arg) < 0) 40 { 41 perror”execv error “); 42 exit1); 43 } 44 } 45 46 /** 47 *创建子进程并调用 execlp 48 *execlp中 49 *l希望接收以逗号分隔的参数列表,列表以NULL指针作为结束标志 50 *p是一个以NULL结尾的字符串数组指针,函数可以DOS的PATH变量查找子程序文件 51 */ 52 if fork) == 0 ) 53 { 54 // in clhild 55 printf”3————execlp————\n”); 56 if execlp “ls”, “ls”, “-a”, NULL ) < 0 ) 57 { 58 perror “execlp error ” ); 59 exit1); 60 } 61 } 62 63 /** 64 *创建子里程并调用execvp 65 *v 望接收到一个以NULL结尾的字符串数组的指针 66 *p 是一个以NULL结尾的字符串数组指针,函数可以DOS的PATH变量查找子程序文件 67 */ 68 if fork) == 0 ) 69 { 70 printf”4————execvp————\n”); 71 if execvp “ls”, arg ) < 0 ) 72 { 73 perror “execvp error ” ); 74 exit 1 ); 75 } 76 } 77 78 /** 79 *创建子进程并调用execle 80 *l 希望接收以逗号分隔的参数列表,列表以NULL指针作为结束标志 81 *e 函数传递指定参数envp,允许改变子进程的环境,无后缀e时,子进程使用当前程序的环境 82 */ 83 if fork) == 0 ) 84 { 85 printf”5————execle————\n”); 86 if execle”/hsdxtg/ls”, “ls”, “-a”, NULL, NULL) == -1 ) 87 { 88 perror”execle error “); 89 exit1); 90 } 91 } 92 93 /** 94 *创建子进程并调用execve 95 * v 希望接收到一个以NULL结尾的字符串数组的指针 96 * e 函数传递指定参数envp,允许改变子进程的环境,无后缀e时,子进程使用当前程序的环境 97 */ 98 if fork) == 0 ) 99 {100 printf”6————execve———–\n”);101 if execve “/hsdxtg/ls”, arg, NULL ) == 0)102 {103 perror”execve error “);104 exit1);105 }106 }107 return EXIT_SUCCESS;108 }运行结果Linux)

1————execl————. .. .deps exec exec.o .libs Makefile2————execv————. .. .deps exec exec.o .libs Makefile3————execlp————. .. .deps exec exec.o .libs Makefile4————execvp————. .. .deps exec exec.o .libs Makefile5————execle————. .. .deps .libs Makefile exec exec.o6————execve———–. .. .deps .libs Makefile exec exec.o

Published by

风君子

独自遨游何稽首 揭天掀地慰生平

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注