exec、execvp、execl、execv之间的区别是什么?

11

我正在编写一个代表Linux的新shell的代码。其中一个我想支持的命令是运行一个进程,例如如果我得到以下行:

command [arguments]

那么我想将command作为一个进程运行,直到运行该进程结束。

为了做到这一点,我知道需要使用 fork() 来获取子进程并获取其PID,我的问题是我不知道以下命令之间的区别:

execexecvpexeclexecv等,我不知道应该使用哪个以及为什么要使用它。

我的当前代码如下:

void External_Process(char *arguments[MAX_ARG], char* command)
{
    int pID;
    switch(pID = fork())
    {
    case -1:
        perror("fork failed");
        break;
    case 0 :
        setpgrp();

        //execv(command, arguments);
        //execvp(command, arguments);
        //execl("/bin/bash", "/bin/bash","-c",command,NULL);

        printf("smash error: > bad command %s\n" , command);
        exit(-1) ;

        break;

    default:
        return ;
    }
}

谢谢您!

3个回答

21

摘要:在您的情况下,我建议使用execvp

要了解exec*函数之间的区别,您应该阅读文档:
https://linux.die.net/man/3/exec
https://linux.die.net/man/2/execve

execl*execv*之间的区别是参数传递。 execl*需要参数列表,而execv*需要参数向量。
如果您在编译时知道所有参数,则参数列表很有用。 在您的情况下,参数将由用户输入,并且您必须在运行时构造参数向量,因此您应该使用其中一个execv*函数。

后缀为p的函数使用PATH环境变量查找程序(例如"ls"),否则您必须指定完整路径(绝对路径或相对于当前目录的路径,例如"/bin/ls")。使用PATH是Shell通常执行的操作,因此这似乎是您的正确选择。

后缀为e的函数允许为进程指定环境。 在您的情况下,为了简单起见,我不建议使用此选项。

因此,这导致结论:execvp

当然,你也可以使用system(而不是fork/exec*/wait*),就像vladxjohn的答案中提到的那样。但是在这种情况下,你只能使用一个shell来解释你的命令,而不能实现基本的shell。


0

尝试阅读手册:https://linux.die.net/man/3/execv

摘要:

描述 exec()函数族用新的进程映像替换当前进程映像。本手册页中描述的函数是execve(2)的前端。(有关替换当前进程映像的详细信息,请参见execve(2)的手册页。)

这些函数的初始参数是要执行的文件的名称。

在execl()、execlp()和execle()函数中的const char *arg和后续省略号可以被视为arg0、arg1、...、argn。它们一起描述了一个指向可执行程序中可用的参数列表的一个或多个指针的以空字符结尾的字符串列表。按照惯例,第一个参数应该指向与正在执行的文件相关联的文件名。参数列表必须以NULL指针终止,并且由于这些是变参函数,因此必须将此指针强制转换为(char *) NULL。

execv()、execvp() 和 execvpe() 函数提供了一个指向表示新程序可用的参数列表的空字符结尾字符串指针数组。按照惯例,第一个参数应该指向正在执行的文件的文件名。指针数组必须以 NULL 指针结尾。

execle() 和 execvpe() 函数允许调用者通过 envp 参数指定执行程序的环境。envp 参数是一个指向空字符结尾字符串的指针数组,并且必须以 NULL 指针结尾。其他函数从调用进程中的外部变量 environ 获取新进程映像的环境。

execlp() 和 execvp() 的特殊语义

如果指定的文件名不包含斜杠 (/) 字符,则 execlp()、execvp() 和 execvpe() 函数会复制 shell 在搜索可执行文件时的操作。在 PATH 环境变量指定的以冒号分隔的目录路径名列表中查找文件。如果未定义此变量,则路径列表默认为当前目录,后跟 confstr(_CS_PATH) 返回的目录列表。(此 confstr(3) 调用通常返回值 "/bin:/usr/bin"。)


-2
在C语言中,您可以使用“system”命令。这将执行您输入的函数参数。
以下是一个示例:
system("ls -l");

如果你想获取输出,你可以将其重定向到其他源。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接