Linux进程全解8——exec 族函数

来源:互联网 发布:淘宝手机流量互刷 编辑:程序博客网 时间:2024/06/02 06:38

以下内容源于朱有鹏《物联网大讲堂》的课程学习整理,如有侵权,请告知删除。


1、为什么需要exec函数?

(1)fork子进程是为了执行新程序

  • fork创建子进程后,子进程和父进程同时被OS调度执行;
  • 因此子进程可以独立地执行一个程序,这个程序宏观上将会和父进程程序同时进行。

(2)可以直接在子进程的if(){ }中写入新程序的代码

  • 但是这样不够灵活,因为我们只能把子进程程序的源代码贴过来执行(必须知道源代码,而且源代码太长了也不好控制);
  • 譬如说我们希望子进程来执行ls -la 命令就不行了(因为没有源代码,只有编译好的可执行程序)。

(3)使用exec族运行新的可执行程序

  • exec族函数可以直接把一个编译好的可执行程序直接加载运行。

(4)有了exec族函数后,典型的父子进程程序如下

  • 首先项目是一个多进程项目;
  • (子进程需要运行的)程序被单独编写、单独编译连接成一个可执行程序(叫hello);
  • 主程序为父进程,fork创建子进程后,在子进程中使用exec来执行hello;
  • 这样就达到了父子进程分别运行不同程序,但(宏观上)同时运行的效果。


2、exec族的6个函数介绍

(1)execl和execv

  • 这两个函数是最基本的exec,都可以用来执行一个程序,区别是传参的格式不同。
  • execl是把参数列表(本质上是多个字符串,必须以NULL结尾)依次排列而成(l其实就是list的缩写)。
  • execv是把参数列表事先放入一个字符串数组中,再把这个字符串数组传给execv函数。

(2)execlp和execvp

  • 这两个函数在上面2个基础上加了p
  • 上面2个执行程序时必须指定可执行程序的全路径(如果exec没有找到path对应的文件则直接报错)。
  • 这里加了p的两个函数,传递的可以是file,也可以是path,只不过兼容了file。
  • 这两个函数会首先去找file,如果找到则执行执行,如果没找到则会去环境变量PATH所指定的目录下去找,如果找到则执行,如果没找到则报错。

(3)execle和execvpe

  • 这两个函数较基本exec来说加了e,函数的参数列表中也多了一个字符串数组envp形参;
  • e表示environment(环境变量),和基本版本的exec的区别在于,执行可执行程序时会多传一个环境变量的字符串数组给待执行的程序。

3、execl和execv实战

(1)使用execl运行ls -l -a

(2)使用execv运行ls

(3)使用execl运行自己写的程序


4、execlp和execvp实战

  • 不加p时需要全部路径+文件名,如果找不到就报错了。
  • 加了p之后会到PATH所指定的路径下去找一下。

5、execle和execvpe实战

(1)main函数的原型其实不止是int main(int argc, char **argv),而可以是

  • int main(int argc, char **argv, char **env)第三个参数是一个字符串数组,内容是环境变量。

#include <stdio.h>// env就是我们给main函数额外传递的环境变量字符串数组int main(int argc, char **argv, char **env){int i = 0;printf("argc = %d.\n", argc);while (NULL != argv[i]){printf("argv[%d] = %s\n", i, argv[i]);i++;}i = 0;while (NULL != env[i]){printf("env[%d] = %s\n", i, env[i]);i++;}return 0;}

(2)如果用户在执行这个程序时没有传递第三个参数,则程序会自动从父进程继承一份环境变量(默认的,最早来源于OS中的环境变量);

  • 如果使用execlp或者execvpe去传递一个envp数组,则程序中的实际环境变量是我们传递的这一份(取代了默认的从父进程继承来的那一份)


#include <stdio.h>#include <unistd.h>#include <sys/types.h>  #include <sys/wait.h>#include <stdlib.h>int main(void){pid_t pid = -1;pid_t ret = -1;int status = -1;pid = fork();if (pid > 0){// 父进程printf("parent, 子进程id = %d.\n", pid);}else if (pid == 0){// 子进程//execl("/bin/ls", "ls", "-l", "-a", NULL);// ls -l -a//char * const arg[] = {"ls", "-l", "-a", NULL};//execv("/bin/ls", arg);//execl("hello", "aaa", "bbb", NULL);//char * const arg[] = {"aaa", "bbb", NULL};//execv("hello", arg);//execlp("ls", "ls", "-l", "-a", NULL);char * const envp[] = {"AA=aaaa", "XX=abcd", NULL};execle("hello", "hello", "-l", "-a", NULL, envp);return 0;}else{perror("fork");return -1;}return 0;}


原创粉丝点击