【问题标题】:Commands like "ls -l" not executing in execl, whereas in execvp it works像“ls -l”这样的命令不在 execl 中执行,而在 execvp 中它可以工作
【发布时间】:2023-03-21 16:17:01
【问题描述】:

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);
}

【问题讨论】:

    标签: c exec


    【解决方案1】:

    使用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);
    

    等等

    如果您不知道需要处理多少个参数,请使用execvp()execv*() 系列的其他成员之一。另请注意,您必须指定命令的路径; execvp() 向下搜索 $PATH,但 execl() 没有。 另请注意,您可以选择作为 argv[0] 传递的值。

    我采用execl() 方法的原因是因为二进制文件的路径可能不同,而execvp() 没有为我提供该功能。

    我不确定你在这里的意思。使用execvp(),您可以指定:

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

    execvp() 将在$PATH 上搜索ls 并执行找到的第一个匹配的程序。第二个将执行/bin/ls,根本不查看$PATH

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

    这两种方法都可以;第二个不会使用基于 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()execvp()execve()execvpe() 的情况下,第二个参数是参数向量,就像main() 函数接收参数向量(或参数向量,因此argv )。这是程序参数的以 null 结尾的列表。如果要执行带有选项-lls 命令,则需要在argv 中指定三个(!)值"ls""-l" 和一个空指针:

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

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

    execl("/bin/ls", "ls", "-l", (char *)0);
    

    如果你有 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*() 函数都可以构建在execve() 之上——这是集合中的基本函数(因此在Linux 手册中被列为execve(2))。

    【讨论】:

    • 令我困惑的是在 execvp(argv[0], argv);为什么我们将整个 argv 作为第二个参数传递?所以假设 argv[0] 是 ls -l,为什么我们必须将整个 argv 作为第二个参数传递?我尝试研究手册页,但对我来说仍然没有意义
    • 如果 argv[0]"ls -l",您会收到错误消息,因为没有名为 ls -l 的程序。
    猜你喜欢
    • 2020-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多