exec 函数族

简介: exec 函数族

进程的创建中介绍了 fork() 函数用于创建一个新的进程,新进程被称为子进程。该子进程几乎复制了父进程的全部内容。通过在子进程执行代码区,添加任务代码,可以让子进程完成其他的任务。而在 Linux 中,有另外一种函数接口,提供了在一个进程中执行另一个进程的方法,可以将其称之为 exec 函数族。他可以根据制定的文件名或目录名找到可执行文件,并用它来取代当前进程的数据段、代码段和堆栈段。在执行完之后,当前进程除进程号外,其他内容都被替换了。这里的可执行文件既可以是二进制文件,也可以是 Linux 下任何可执行的文件脚本。


Linux 中使用 exec 函数族主要有两种情况:

  1. 当进程不能在系统中发挥更多的作用时,就可以调用exec函数族中的任一一个函数取代当前进程完成后续的工作。
  2. 如果一个进程想执行另一个程序,那么它可以调用fork()函数新建一个进程,然后调用exec函数族中的任意一个函数,这样看起来就像通过执行应用程序而产生一个新进程(这种情况非常普遍)


exec 函数族原型如下:

#include <unistd.h>
extern char **environ;
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ..., char *const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execve(const char *file, char *const argv[], char *const envp[]);点击复制复制失败已复制


6 个函数在函数名和使用语法的规则上都有细微的区别,参数区别如下表所示:

函数 第一个参数 第二个参数 第三个参数 第四个参数
execl path 路径名 *arg ... 附件参数 \
execp file 文件名 *arg ... 附件参数 \
exece path 路径名 *arg ... 附件参数 *envp[]
execv path 路径名 *argv[] \ \
execp file 文件名 *argv[] \ \
execv file 文件名 *argv[] \ *envp[]


函数第一个参数有两种传参方式:第一种为路径名,即指定文件名时,需要指定文件名所在路径;第二种为文件名,即只需要指定要执行的二进制文件名或 Linux 下可执行的脚本文件文件名。第三个参数的第二个与第三个参数用来进行列举式传参,都可以传入需要的字符串;后三个函数将第二个参数和第三个参数合并将所有参数通过一个指针数组进行传递。第四个参数用来指定当前进程所使用的环境变量


execl()函数测试

#include <stdio.h>
#include <unistd.h>
int main(int argc, const char *argv[]) {
  if (execl("/bin/ls", "ls", "./file", NULL) < 0) {
    perror("execl error");
    return -1;
  }
  return 0;
}
点击复制复制失败已复制


示例中,第一个参数指定可执行文件的路径名;第二个参数为列举式传参,本次传入两个字符串 "ls""./file" ,其中 "./file" 为当前目录下的 file 目录;第三个附件参数传递为 NULL


运行结果如下所示:

$ gcc main.c && ./a.out 
1.txt  2.txt  3.txt点击复制复制失败已复制


源码文件结构如下所示:

.
├── file
│   ├── 1.txt
│   ├── 2.txt
│   └── 3.txt
└── main.c点击复制复制失败已复制


由此可以看出,此时运行 a.out 产生新进程为 "ls" ,并查看 file 目录下所有的文件。功能与 Shell 命令 "ls + 目录名" 一样。如果代码将 "./file" 参数去掉,则此时新进程将查看当前目录下所有的文件;也可添加参数 "-l" ,查看更详细的内容,如下所示:

#include <stdio.h>
#include <unistd.h>
int main(int argc, const char *argv[]) {
  if (execl("/bin/ls", "ls", "-l", "./file", NULL) < 0) {
    perror("execl error");
    return -1;
  }
  return 0;
}
点击复制复制失败已复制


编译运行,结果如下:

$ gcc main.c && ./a.out 
总用量 0
-rw-rw-r-- 1 iric iric 0 9月  26 19:37 1.txt
-rw-rw-r-- 1 iric iric 0 9月  26 19:37 2.txt
-rw-rw-r-- 1 iric iric 0 9月  26 19:37 3.txt点击复制复制失败已复制

可以看出第二个参数 char *arg 并非只用于接收一个字符串。


execv()函数测试

下面通过 execv() 函数,展示如何列举式传参,同样也可以将刚才的代码,采用指针数组的形式进行传参,如下所示:

#include <stdio.h>
#include <unistd.h>
int main(int argc, const char *argv[]) {
  char *array[4] = {"ls", "-l", "./file", NULL};
  if (execv("/bin/ls", array) < 0) {
    perror("execv error");
    return -1;
  }
  return 0;
}点击复制复制失败已复制

可以看出将刚才的列举参数,一并放入到指针数组中即可。运行结果和上面一致。

目录
相关文章
|
23天前
|
Linux
linux中wait与waitpid函数使用场景及扩展
linux中wait与waitpid函数使用场景及扩展
|
12月前
|
Shell C++
C++中的exec()函数
exec()函数在C++中是一个进程控制函数,用于创建新进程执行其他程序或命令行指令。exec()函数可以替换当前进程的代码和数据,创建新的进程运行其他程序。exec()函数有多个版本,例如execl、execv、execle、execve等,根据不同的参数类型和个数来使用。
141 0
|
物联网 Linux 开发者
Exec 函数族简介|学习笔记
快速学习 Exec 函数族简介
79 0
Exec 函数族简介|学习笔记
|
程序员 C语言 索引
|
机器学习/深度学习 Unix Windows

热门文章

最新文章