linux exec函数家族

  1.exec家族一共有六个函数,分别是:

  (1)int execl(const char *path, const char *arg, ......);

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

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

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

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

  (6)int execlp(const char *file, const char *arg, ......);

  其中只有execve是真正意义上的系统调用,其它都是在此基础上经过包装的库函数。

     exec函数族的作用是根据指定的文件名找到可执行文件,并用它来取代调用进程的内容,换句话说,就是在调用进程内部执行一个可执行文件这里的可执行文件既可以是二进制文件,也可以是任何Linux下可执行的脚本文件。

  与一般情况不同,exec函数族的函数执行成功后不会返回,因为调用进程的实体,包括代码段,数据段和堆栈等都已经被新的内容取代,只留下进程ID等一些表面上的信息仍保持原样,颇有些神似"三十六计"中的"金蝉脱壳"。看上去还是旧的躯壳,却已经注入了新的灵魂。只有调用失败了,它们才会返回一个-1,从原程序的调用点接着往下执行。

  

  2.它们之间的区别:

  1)前四个取路径名做为参数,后两个取文件名做为参数,如果文件名中不包含 / 则从PATH环境变量中搜寻可执行文件, 如果找到了一个可执行文件,但是该文件不是连接编辑程序产生的可执行代码文件,则当做shell脚本处理。

  2)前两个和最后一个函数中都包括“ l ”这个字母 ,而另三个都包括“ v ”, " l "代表 list即表 ,而" v "代表 vector即矢量,也是是前三个函数的参数都是以list的形式给出的,但最后要加一个空指针,如果用常数0来表示空指针,则必须将它强行转换成字符指针,否则有可能出错。,而后三个都是以矢量的形式给出,即数组。

  3)与向新程序传递环境变量有关,如第二个和第四个以e结尾的函数,可以向函数传递一个指向环境字符串指针数组的指针。即自个定义各个环境变量,而其它四个则使用进程中的环境变量。

 

  3.实例:

  1)在平时的编程中,如果用到了exec函数族,一定记得要加错误判断语句。先判断execl的返回值,如果出错,可以用perror( )函数打印出错误信息。

  如:if (execl(path,..””(char *)0) < 0)

      {

           perror(“execl error!”);

     }

  如果调用出错,可输出:execl error!: 错误原因   这样可方便查找出错原因

  (2)注意下面书写格式:

  先定义一个指针数组:char *argv[]={ls,-l,(char *)0}

  用execv调用ls:    execv(/bin/ls,argv)

   如果用execvp

  execvp(ls,argv)      //直接写ls就可以了

  注意:

  execl调用shell 时,要在shell脚本中指明使用的shell版本:#/bin/bash。在命令行下执行shell脚本,系统为它自动打开一个shell,在程序中没有shell,在调用shell脚本时,会出错,所以要在shell脚本中先打开shell

  (3)

  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 main(int 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------------
" );
 24     if( execl( "/bin/ls", "ls","-a", NULL ) == -1 )
 25     {
 26       perror( "execl error " );
 27       exit(1);
 28     }
 29   }
 30   
 31   /**
 32    *创建子进程并调用函数execv
 33    *execv中希望接收一个以NULL结尾的字符串数组的指针
 34    */
 35   if( fork() == 0 )
 36   {
 37     // in child 
 38     printf("2------------execv------------
");
 39     if( execv( "/bin/ls",arg) < 0)
 40     {
 41       perror("execv error ");
 42       exit(1);
 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------------
");
 56     if( execlp( "ls", "ls", "-a", NULL ) < 0 )
 57     {
 58       perror( "execlp error " );
 59       exit(1);
 60     }
 61   }
 62   
 63   /**
 64    *创建子里程并调用execvp
 65    *v 望接收到一个以NULL结尾的字符串数组的指针
 66    *p 是一个以NULL结尾的字符串数组指针,函数可以DOS的PATH变量查找子程序文件
 67    */
 68   if( fork() == 0 )
 69   {
 70     printf("4------------execvp------------
");
 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------------
");
 86     if( execle("/bin/ls", "ls", "-a", NULL, NULL) == -1 )
 87     {
 88       perror("execle error ");
 89       exit(1);
 90     }
 91   }
 92   
 93   /**
 94    *创建子进程并调用execve
 95    * v 希望接收到一个以NULL结尾的字符串数组的指针
 96    * e 函数传递指定参数envp,允许改变子进程的环境,无后缀e时,子进程使用当前程序的环境
 97    */
 98   if( fork() == 0 )
 99   {
100     printf("6------------execve-----------
");
101     if( execve( "/bin/ls", arg, NULL ) == 0)
102     {
103       perror("execve error ");
104       exit(1);
105     }
106   }
107   return EXIT_SUCCESS;
108 }

  结果:

 1 1------------execl------------
 2 .  ..  .deps  exec  exec.o  .libs  Makefile
 3 2------------execv------------
 4 .  ..  .deps  exec  exec.o  .libs  Makefile
 5 3------------execlp------------
 6 .  ..  .deps  exec  exec.o  .libs  Makefile
 7 4------------execvp------------
 8 .  ..  .deps  exec  exec.o  .libs  Makefile
 9 5------------execle------------
10 .  ..  .deps  .libs  Makefile  exec  exec.o
11 6------------execve-----------
12 .  ..  .deps  .libs  Makefile  exec  exec.o
13 按回车继续!
原文地址:https://www.cnblogs.com/guochuanrui/p/exec.html