本篇博客经参考资料1整理、修改而成。

1       exec 函数执行时,是用一个全新的程序代替了当前进程的正文、数据、堆栈段,但是它并没有改变进程ID,执行后进程ID依旧是之前的进程ID。其函数原型如下:

     #include <unistd.h>extern char **environ;int execl(const char *pathname, const char *arg, .../* (char  *) NULL */);int execlp(const char *file, const char *arg, .../* (char  *) NULL */);int execle(const char *pathname, const char *arg, .../*, (char *) NULL, char *const envp[] */);int execv(const char *pathname, char *const argv[]);int execvp(const char *file, char *const argv[]);int execvpe(const char *file, char *const argv[],char *const envp[]);

此6个函数按照exec后面的参数可以分为以下3类:

(1)带‘l’的。l是list,是指函数的参数以list的形式出现的,参数形式如下:arg0,arg1...argn,最后一个参数须以(char *)NULL结束。主要函数有execl(), execlp(), execle()。通常情况下,第一个参数是路径名,如果是完整路径名,则执行完整路径名,如果只是文件名,则从进程当前工作目录寻找。

程序1:execl.c

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>int main(int argc, char *argv[])
{printf("before execl\n");if(execl("/bin/ls","ls","-l",(char *)0)==-1){fprintf(stderr,"execl error ,error is %d,msg is %s\n",errno,strerror(errno));}printf("after execl\n");exit(0);
}

程序执行后,会用全新的程序替代当前进程,执行结果如下:

可以看出,程序执行结束后,"after execl" 没有打印出来,因为进

程上下文已被切换成新的,原程序不再执行。如果pathname 使用文件名,当从当前工作目录查找,如果查找不到,便会出错。

修改execl.c源文件中的execl行为(execl2.c):

if(execl("ls","ls","-l",(char *)0)==-1)

显示找不到文件,后main继续执行,打印出了“after execl”。如果更改工作目录为/bin,因为/bin目录有ls的执行文件,所以程序执行结果一样成功,类似第一个结果截图。

(2)带‘v’的,v 是vector,代表参数是以vector的形式出现,参数个数总数为2个,第二个参数为指针数组char *const argv[],代表了后面的参数以指数组的形式出现,并且以空指针NULL结束。主要函数有execv(), execvp(), execvpe()。第一个参数pathname的意义与execl的第一个参数pathname 相同。

源程序execv.c

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>int main(void)
{printf("before execl\n");char *argv[]={"ls","-l",(char *)0};if(execv("/bin/ls",argv)==-1){fprintf(stderr,"execv error ,error is %d,msg is %s\n",errno,strerror(errno));}printf("after execl\n");exit(0);
}

执行结果如下:

(3)带‘p’的,p 代表“PATH”,是指程序的第一个参数filename ,是从当前环境变量PATH值寻找,即如果第一个参数不是完整路径的话,将从PATH寻找可执行文件,也包括当前工作目录。如果第一个参数中有‘/’,则PATH寻找过程被忽略。主要函数有:execlp(), execvp(), execvpe()。

源程序execlp.c

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>int main(int argc, char *argv[])
{printf("before execl\n");if(execlp("ls","ls","-l",(char *)0)==-1){fprintf(stderr,"execlp error ,error is %d,msg is %s\n",errno,strerror(errno));}printf("after execl\n");exit(0);
}

执行结果如下

因为新建的文件越来越多,所以输出结果会相应的增加。

(4)带‘e’的。'e'代表environment,是指程序将当前的环境变量替换为参数char *const envp[]指向的环境表,并执行程序。这样的函数都有带有一个参数char *const envp[],出现在函数参数表中的位置均为最后一个位置。主要的函数有两个execle(), execvpe(),就是其它四个函数是用调用进程的环境表environ来执行,而这两个函数是用envp 代替environ 来执行,envp 是一个指针数组,以NULL 结束。

以下程序先打印当前环境表envrion的值,然后创建新环境表,并打印出来。

源程序:printenv.c

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>extern char **environ;int main(void)
{
char **p=environ;
while(*p)
{
printf("%s\n",*p);
p++;
}
exit(0);
}

输出执行文件,gcc printenv.c -o printenv ,

源程序execl3.c,先打印当前进程的环境表

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>int main(int argc, char *argv[])
{printf("before execl\n");if(execl("printenv","printenv",(char *)0)==-1){fprintf(stderr,"execl error ,error is %d,msg is %s\n",errno,strerror(errno));}printf("after execl\n");exit(0);
}

输出结果是进程中当前环境表的值

然后利用execle 函数打印新环境表的值

源程序execle.c

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>int main(int argc, char *argv[])
{printf("before execl\n");char * envp[]={"AA=11","BB=22","cc=33",NULL};if(execle("printenv","printenv",(char *)0,envp)==-1){fprintf(stderr,"execle error ,error is %d,msg is %s\n",errno,strerror(errno));}printf("after execl\n");exit(0);
}

输出结果如下:

可以看到环境表已经替换。

2 函数返回值。

上述6个函数,没有正确返回值,只有出错返回值,出错时,函数返回-1,并赋值errno,常见的错误码如下:

(1)E2BIG:envp,arg0等参数表太大

(2)EACCES :第一个参数执行权限不允许

(3)ENOENT:第一个参数文件或路径不存在

(4)ENOEXE 执行文件出错

3 补充

exec函数执行成功时,执行新程序的进程除了进程ID 不变外,还有下面项保持不变。

(1)进程ID 和父进程ID

(2)实际用户ID和实际组ID

(3)附加组ID

(4)进程组ID
(5)会话ID

(6)控制终端

(7)闹钟尚预留时间

(8)当前工作目录

(9)根目录

(10)文件模式创建屏蔽字

(11)文件锁

(12)进程信号屏蔽

(13)未处理信号

(14)资源限制

(15)tms_utime、tsm_stime、tms_cutime、tms_cstime

(16)environ(带‘e’函数的除外)。

参考资料:

(1)https://www.cnblogs.com/mickole/p/3187409.html

(2)https://man7.org/linux/man-pages/man3/execl.3.html

(3)https://man7.org/linux/man-pages/man2/execve.2.html

linux--exec函数族浅析相关推荐

  1. 12.Linux:exec函数族

    (1)exec函数说明 fork函数是用于创建一个子进程,该子进程几乎是父进程的副本,而有时我们希望子进程去执行另外的程序,exec函数族就提供了一个在进程中启动另一个程序执行的方法.它可以根据指定的 ...

  2. Linux下进程的建立 并附Linux exec函数族

    我们都知道,进程就是正在执行的程序.而在Linux中,可以使用一个进程来创建另外一个进程.这样的话,Linux的进程的组织结构其实有点像Linux目录树,是个层次结构的,可以使用pstree命令来查看 ...

  3. Linux exec函数族

    如果我们使用fork()函数创建一个子进程,则该子进程几乎复制了父进程的全部内容,也就是说,子进程与父进程在执行同一个可执行程序.那么我们能否让子进程不执行父进程正在执行的程序呢? exec函数族提供 ...

  4. Linux——exec函数族原理及特性、execlp和execl函数

    一.exec函数族原理 fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往往要调用一种exec函数以执行另一个程序. 当进程调用一种exec函数时,该进程的用户空间 ...

  5. Linux进程控制——exec函数族

    1.简介 在Linux中,并不存在exec()函数,exec指的是一组函数,一共有6个,分别是: #include <unistd.h> extern char **environ; in ...

  6. 【Linux系统编程】进程替换:exec 函数族

    00. 目录 文章目录 00. 目录 01. exec函数族 02. 参考示例 2.1 execl函数示例 2.2 execv函数示例 2.3 execlp() 或 execvp()函数示例 2.4 ...

  7. Linux系统编程--3(exec 函数族,僵尸进程和孤儿进程,wait和wait_pid回收子进程)

    exec 函数族 fork 创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支) ,子进程往往要调用一种 exec 函数以执行另一个程序.当进程调用一种 exec 函数时,该进程的用户 ...

  8. 【Linux系统编程学习】Linux进程控制原语(fork、exec函数族、wait)

    此为牛客Linux C++和黑马Linux系统编程课程笔记. 1. fork函数 1.1 fork创建单个子进程 #include<unistd.h> pid_t fork(void); ...

  9. Linux进程实践(3) --进程终止与exec函数族

    进程的几种终止方式 (1)正常退出 从main函数返回[return] 调用exit 调用_exit/_Exit (2)异常退出 调用abort   产生SIGABOUT信号 由信号终止  Ctrl+ ...

  10. Linux多任务编程(三)---exec函数族及其基础实验

    exec函数族 函数族说明 fork() 函数用于创建一个新的子进程,该子进程几乎复制了父进程的全部内容,但是,这个新创建的子进程如何执行呢?exec 函数族就提供了一个在进程中启动另一个程序执行的方 ...

最新文章

  1. 还在为论文发愁?ACL组委会手把手教你论文投稿小技巧 | ACL 2017
  2. Micron Flash芯片识别心得
  3. Leetcode 189. 旋转数组 (每日一题 20210909)
  4. mysql数据的引用_MySQL数据库入门:mysql操作和程序引用
  5. 蓝牙模块音频BLE数据数传串口AT指令的使用方法
  6. intellij 快捷键_IntelliJ中的键盘快捷键
  7. c#设置开机自动启动程序本篇文章来源于:
  8. Linux的网络管理命令使用总结
  9. DXUT框架剖析(2)
  10. CoffeeScript、TypeScript 、 JavaScript 之间
  11. 服务器测试文档格式,服务器测试文档格式
  12. python HTTP请求过程
  13. 更新ADT20后无法创建Android项目
  14. JavaScript 打开新页面
  15. ubuntu安装中文输入法fcitx
  16. c语言求余运算作用,C语言中的整数除法和求余运算
  17. 我用php构建了魔兽世界服务器,只为证明php是世界上最好的语言
  18. 无法安装NET Framework3.5错误代码0x800F081F
  19. Java Web安全之代码审计
  20. 《地球概论》(第3版)笔记 第四章 地球运动的地理意义

热门文章

  1. 重装jdk后运行java程序出现Error: could not open `C:\Program Files\Java\jre68\lib\amd64\jvm.cfg'的解决办法
  2. vb怎么判断整数_VB数学函数大全
  3. 论述计算机与外设的访问控制方法,试论述计算机与外设访问控制的方法有多少种各有什么优缺点...
  4. java中取系统时间_JAVA中获取当前系统时间(示例代码)
  5. linux替换指定行指定列的内容,linux – sed替换特定行号的特定列号值
  6. windows下使用命令行将employees.sql导入mysql
  7. 笔记本windows7设置WIFI教程(超详细)
  8. sql server datetime取年月_快速定位数据库性能问题,RDS推出慢SQL统计分析
  9. linux漏洞知乎_Linux本地内核提权漏洞(CVE-2019-13272)
  10. 使用JAVA加jxl jar操作EXECL