像"ls -l"这样的命令不在execl中执行,而在execvp中它可以工作

mar*_*iel 2 c exec

execl变体中使用下面的代码ls,但是ls -l不起作用,但是在我的execvp方法lsls-l工作中.我采用这种execl方法的原因是因为二进制文件的路径可能不同而execvp没有提供给我这个功能.理想情况下,我execl也想继续努力ls -l,但现在它不起作用ls -l.我试过阅读手册页,但没有帮助.

void child(int argc, char *argv[MAX_ARGS])
{
        execvp(argv[0], argv);
}


void child(char *argv[], char* path)
{
        execl(path, argv, NULL);
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*ler 12

有了execl(),你必须逐个列出参数; 它只有在您确切知道要提前执行的内容时才有用:

execl("/bin/ls", "ls", "-l", (char *)0);
execl("/bin/sh", "sh", "-c", "ls -l", (char *)0);
execl("/bin/ls", "pink elephants", "-l", (char *)0);
Run Code Online (Sandbox Code Playgroud)

等等.

如果您不知道有多少论据需要处理,请使用execvp()execv*()家族的其他成员.另请注意,您必须指定命令的路径; execvp()向下搜索$PATH,但execl()没有.另请注意,您可以选择传递的值argv[0].

我采用这种execl()方法的原因是因为二进制文件的路径可能不同而execvp()没有提供给我这个功能.

我不确定你的意思.使用execvp(),您可以指定:

char *argv[] = { "ls", "-l", 0 };
execvp(argv[0], argv);
execv("/bin/ls", argv);
Run Code Online (Sandbox Code Playgroud)

execvp()将搜索ls$PATH和执行中发现的第一个程序匹配.第二个将执行/bin/ls而不看$PATH.

char *argv[] = { "/bin/ls", "-l", 0 };

execv(argv[0], argv);
execvp(argv[0], argv);
Run Code Online (Sandbox Code Playgroud)

这些都可以起作用; 第二个不会使用基于PATH的搜索,因为可执行文件名(argv[0])包含斜杠.


令我困惑的是,execvp(argv[0], argv);为什么我们将整个argv作为第二个参数传递?所以假设argv[0]"ls -l",为什么我们必须将整个argv作为第二个参数传递?

假设argv[0]包含"ls -l",你有一个问题.大多数系统没有文件" /bin/ls -l"或" /usr/bin/ls -l"(其中空白是名称的一部分),但这就是您要执行的内容.

这些exec*()函数是执行进程的低级函数.第一个参数指定要运行的程序(通常是二进制文件;有时是一个带有shebang行的脚本,例如#!/bin/sh第一行).在execv()or execvp()execve()or 的情况下execvpe(),第二个参数是参数的向量,就像main()函数接收参数向量(或参数向量,因此argv)一样.这是程序参数的以null结尾的列表.如果要执行ls的选项命令-l,那么你需要在指定argv的三个值(!) "ls","-l"和一个空指针:

char argv[] = { "ls", "-l", 0 };
Run Code Online (Sandbox Code Playgroud)

使用这些execl*()函数,您可以指定要作为第一个参数运行的程序,然后写出参数向量:

execl("/bin/ls", "ls", "-l", (char *)0);
Run Code Online (Sandbox Code Playgroud)

如果你有10个参数,你必须写出10个参数(加上空指针).

exec*()函数中,名称包含:

  • l - 列表格式参数
  • v - 矢量格式参数
  • p - 对程序执行PATH查找(如果给定名称不包含斜杠)
  • e - 也采用环境变量的向量

这些结合起来给出:

  • execl()
  • execv()
  • execlp()
  • execle()
  • execvp()
  • execve()

偶尔有点令人厌烦的是没有execlpe()execvpe()(但请参阅Linux扩展execvpe(3)).对于man 2 exec页面来说,从概要中省略其中的一些内容也是传统的,但在手册页的主体中提到它们 - 传统/遗产可以追溯到1979年至少第7版UNIX™(并且至少延续到RHEL 5 Linux和Mac OS X 10.7.5; man 2 execl页面提到execve()但未在概要部分列出.其他exec*()功能都可以在atop上构建execve()- 这是集合中的基本功能(因此execve(2)在Linux手册中列出).