exec函数族 等

一、exec 函数族

1.1 函数原型

 

在 Linux 中,并不存在 exec() 函数,exec 指的是一组/簇函数,一共有 6 个: 

#include <unistd.h>

int execl (const char *path, const char *arg0, ...);

int execlp (const char *file, const char *arg0, ...);

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

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

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

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

  

注1:exec 族函数执行成功后,此函数后面的代码就执行不到了!! 但只会影响当前进场,而不会影响系统。

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

注3:函数名称中的子母涵义:

  l (list):参数地址列表,必须以空指针结尾 ---- NULL是设立的哨兵,必须手动加。

  v (vector):存有各参数地址的指针数组的地址。

  p (path):按 PATH 环境变量指定的目录搜索可执行文件  ---- 带此字母的函数可以直接使用“文件名”,其他的则必须使用“路径名”。

  e (environment):存有环境变量字符串地址的指针数组的地址 ---- 无后缀e时,子进程使用当前程序的环境。

 

 

1.2 返回值

一旦调用成功即执行新的程序,即:成功无返回;失败会设置errno并返回:-1,然后从原程序的调用点接着往下执行。

故而,可以直接在 exec 族函数后, 直接调用 perror() 或者 exit(),不需要 if 判断。

最常见的错误:
  errno = ENOENT,找不到文件或路径;
  errno = EFAULT,数组 argv 和 envp 忘记用NULL结束;
  errno = EACCES,没有对要执行文件的运行权限。

 

 

1.3 使用参数示例

(1)execl

execl("./a.out", "./a.out", NULL);

execl("/bin/ls", "ls", "-l", NULL);

注1:第一个参数是文件路径,第二个参数是argv[0],之后是传给argv[0]的参数,没有了就哨兵NULL。

注2:execl 执行的是自己的文件;若要用 execl 执行系统的文件,必须写成绝对路径。

 

(2)execlp

//错误写法: execlp ("ls","-l","-h",NULL);
execlp ("ls","ls","-l","-d","-h",NULL); 

注1:第一个参数 file 必须是文件名;最后一个参数必须用空指针(NULL)作结束。

首先,从PATH 环境变量所指的目录中查找符合参数 file 的文件名,找到后便执行该文件;然后,将第二个以后的参数当做该文件的argv[0], argv[1], …。

注2:execlp 执行的是系统的文件

 

(3)execvp

char * argv[] = {"ls", "-l", "-h", NULL};

execvp("ls", argv);

 

 

 

 

二、system 函数

2.1 函数原型

#include <stdlib.h>

int system(const char * command);

 

 

 

 

 

三、popen 函数

3.1 函数原型

#include <stdio.h>

FILE *popen(const char * command, ocnst char * type);

参数:

  comand 为执行命令,

  type 为操作类型,只能是读和写的 一种,一般为 “r” 和 “w”, 返回值是一个文件类型指针

示例:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int main()
{
  char data[1024] = {0};
  FILE *fp;
  fp = popen("ps", "r");
  int n_read = fread(data, 1, 1024, fp);
  printf("read %d bytes, data=%s\n",n_read, data);
  return 0;

}

 

 

 

 

四、 查看时间示例

#include <stdio.h>

#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>


int main()
{
  printf("before execl:\n");

  // 方法1:使用 exec 函数族
  if ( execl ("/bin/date", "date", NULL) == -1) {
    printf("execl failed!\n");
    perror("why");
  }

  // 方法2: 使用 system 函数

  if ( system("date") == -1 ){

    printf("execl failed!\n");
  }

  printf("after execl\n");
  return 0;
}

 

 

 

 

参考列表:
[1]  Linux系统编程——进程替换:exec 函数族
[2]  Linux——exec函数族原理及特性、execlp和execl函数

[3]  Linux系统编程之exec函数簇的使用:剖析exec函数簇的实现原理、参数解释和用法技巧

[4]  【Linux】进程控制(exec函数族)的理解和使用

posted on 2023-11-20 17:35  hellcworld  阅读(2)  评论(0)    收藏  举报

导航