理解为什么 execvp 在 execv 失败的地方工作

understanding why`execvp` works where `execv` fails

我被要求在 C 中实现一个 'mini-shell'。我决定使用 execv 但它不起作用,当我将它更改为 execvp 时它起作用了!看一下代码(动作在tokExec函数中)

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


void tokExec(char command[128])
{
    // 'strtok' may look innocent, but it modifies the string, so I want a copy of the original command.
    char tokString[128];
    // 'strlen' is the lenghth without the null terminator.
    strncpy(tokString,command,strlen(command)+1);


    char* tokPtr = NULL;
    char tok[] = " ";
    int narg = 0;
    tokPtr = strtok(tokString,tok);
    char *myargs[64];

    while(tokPtr != NULL)
    {
            printf("arg %d is: %s\n",narg,tokPtr);
            myargs[narg] = tokPtr;
            narg = narg + 1;
            tokPtr = strtok(NULL,tok);
    }
    printf("Total number of arguments: %d\n",narg);

    // add the final 'NULL' element.
    myargs[narg] = NULL;

    execvp(myargs[0],myargs);
    printf("error\n");
    exit(1);
}

void normal()
{
    char command[128];
    strcpy(command,"default[=10=]");
    printf("myShellZ > ");
    gets(command);
    while(strcmp(command,"exit") != 0)
    {
            int status;
            pid_t pid;
            if( (pid = fork()) == 0 )
            {
                    tokExec(command);
            }
            wait(&status);
            printf("myShellz > ");
            gets(command);
    }
}

void debug()
{
    // TO DO ....
    int a = 3;
}

// switching between shell modes: normal or debug.
int main(int argc, char* argv[])
{
    if(argc == 1)
            normal();
    else if(strcmp("-debug",argv[1]))
            debug();
    else
            exit(1);

    exit(0);
}

如果 tokExec 末尾的 execvp 我将使用 execv,如果我的输入只有 lspsexecv 很棒,但是如果我向输入添加参数,例如:ls -l myshell.c 或 evev 只是 ls -lps aux 我得到一个 error 输出。

man 几乎没有提及这些功能之间的差异,但它声称:

The execv(), execvp(), and execvpe() functions provide an array of pointers to null-terminated strings that represent the argument list available to the new program. The first argument, by convention, should point to the filename associated with the file being executed. The array of pointers must be terminated by a null pointer.

总之,在这种情况下修复我的程序的 execvexecvp 之间有什么区别?我知道 execv 也适用于 bash 命令,因为如果我输入不带参数的 bash 命令,它就可以工作,并且这两个函数的签名是相同的。感谢您的帮助!

答案在手册页中。如果您阅读引用部分之后的部分,它会讨论不同之处

The execlp(), execvp(), and execvpe() functions duplicate the actions of the shell in searching for an executable file if the specified filename does not contain a slash (/) character. The file is sought in the colon-separated list of directory pathnames specified in the PATH environment variable. If this variable isn't defined, the path list defaults to the current directory followed by the list of directories returned by confstr(_CS_PATH). (This confstr(3) call typically returns the value "/bin:/usr/bin".)