【问题标题】:Execvp(argv[1], argv), returning no such file or directoryExecvp(argv[1], argv),不返回这样的文件或目录
【发布时间】:2019-09-22 21:47:50
【问题描述】:

我正在编写一个 C 程序,它接受参数 char *argv[] 来决定运行哪个 exec()。我有execlp(argv[1], argv[1], NULL) 可以正常工作。由于某种原因execvp(argv[1], argv) 找不到要运行的“ls”命令。我真正需要的是,如果我有多个参数,不包括调用./filexec,我可以运行exec(),它将采用char* argv[],而不包括文件路径。我了解到execvp() 有能力做到这一点。

我在 ssh linux 服务器上运行它。

int main(int argc, char *argv[])
{
pid_t pid;

        /* fork a child process */
        pid = fork();

        if (pid < 0) {/* error occured */
                fprintf(stderr, "Fork Failed");
                return 1;
        }
        else if (pid == 0) {/* child process */
                //pass the right thing to the right exec?

                if (argc == 1)
                {
                        printf("CHILD started. No arguments provided. Terminating child.\n");
                }

                if (argc == 2)
                {
                        printf("CHILD started. One argument provided.      Calling execlp().\n");
                        execlp(argv[1],argv[1],NULL);
                }

                if (argc  >= 3)
                {
                        printf("CHILD started. More than one argument provided. Calling execvp().\n");
                        argv[argc++] = NULL;
                        execvp(argv[1],argv);
                }



        }
        else {/* parent process */
                /* parent will wait for the child to complete */
                printf("PARENT started, now waiting for processID#%u\n", getpid());
                wait(NULL);
                printf("PARENT resumed. Child exit code of 0. Now terminating parent.\n");
        }

        return 0;
}

我希望给./a.out ls -l 打电话给execvp() 给予:

total XXX
info ---------filename
info ---------filename

等等

【问题讨论】:

    标签: c linux exec execvp


    【解决方案1】:

    请记住,argv[0] 是“程序的名称”,因此当您的程序被调用时,它将类似于 ./a.out。那么argv[1] 是你的程序的第一个参数,也就是你想要exec 的程序的名称,argv 的其余部分是传递给该程序的其余参数。

    因此,您要传递给您要执行的程序的argv 数组从argv[1] 开始。或者,更准确地说,您要提供的程序的argv 指针execargv + 1

    显然,您在调用 execlp 时发现了这一点,因为您指定了两次 argv[1],一次是 exec 的程序名称,一次是 argv 数组中的第一个(也是唯一的)元素传递给那个程序。你只需要对execvp的调用做同样的事情;你需要execvp(argv[1], argv + 1),而不是execvp(argv[1], argv)

    您收到的错误消息来自ls 实用程序本身。您已经使用execvp 调用了ls,并将整个argv 数组传递给它。换句话说,你告诉它它的名字是./a.out(这可能有点令人困惑,因为大多数实用程序都使用它们被赋予的程序名称来创建错误消息),并且你已经提供了它ls -l作为命令行参数。这实际上与命令行相同:

    ls ls -l
    

    如果您尝试一下,很可能会告诉您文件ls 不存在。 (除非你碰巧在当前目录中有一个名为ls 的文件。)

    顺便说一句:

    argv[argc++] = NULL;
    

    完全没有必要。 argv[argc] 已经保证为 NULL,并且您不需要变量 argc(如果您有变量,您可能需要它少一,而不是多一)。

    【讨论】:

    • 我能问一下为什么 argv + 1 有效吗?这是否只是移动从 argv[1] 开始的索引?跳过 ./a.out?
    • @cameronPrestera:这将是回到您的 C 编程教科书并查找指针算法的好时机。理解指针算法非常非常重要。
    • 据我了解,只要你有一个指针数组,执行 ++ 或 + 1 就会移动到数组中的下一个指针。我明白这一点,我想我的问题是“execvp 是否将 ./a.out 作为第一个参数?”,我可以看到这会导致错误。
    • @cameron:如果你提供argv 作为execvp 的参数,那么它认为参数就是这样。 argv 中的第一件事是 argv[0],这正是 execvp 将传递给它运行的程序的内容。
    猜你喜欢
    • 2016-03-06
    • 2016-02-16
    • 2017-02-10
    • 1970-01-01
    • 2013-03-31
    • 2021-03-10
    • 2012-05-28
    • 1970-01-01
    相关资源
    最近更新 更多