首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >execvp如何运行命令?

execvp如何运行命令?
EN

Stack Overflow用户
提问于 2013-01-13 15:03:22
回答 4查看 45.3K关注 0票数 21

我知道execvp可以用于执行简单的命令,如下所示:

代码语言:javascript
复制
char* arg[] = {"ls", "-l", NULL};
execvp(arg[0],arg);

我想知道当我运行execvp时这里发生了什么。在手册页中,它说execvp用新的进程映像替换了进程映像。然而,在这里我运行的是命令,而不是可执行文件。

具体地说,假设有一个命令特别需要输入,例如cat。如果我有一个文本文件text.txt,其中包含cat期望的文件名,并且我将标准输入重定向到该文件的文件流,那么execle("cat","cat",NULL)execvp("cat", arg) (显然是arg存储"cat"NULL的位置)的输出是否会像cat /filename那样在控制台中产生输出?我的直觉是,我必须读取文件,并可能对其进行解析以将参数存储在arg中。不过,我想确认一下。

提前感谢!

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-01-13 15:56:10

下面是在execvp调用中发生的事情:

如果适用,

  1. 您的libc实现将在PATH中搜索要执行的文件。类UNIX系统中的大多数(如果不是全部)命令都是可执行的。如果不是,会发生什么?试试看。看看how glibc does it.
  2. Typically,如果找到了可执行文件,就会调用execveexecve的某些部分可以在libc中实现,也可以是系统调用(如Linux)。
  3. Linux通过为程序分配内存、打开程序、安排执行、初始化内存结构、根据提供给execvp调用的参数设置参数和环境、找到适合加载二进制文件的处理程序,并将当前任务( execvp调用者)设置为不执行来准备程序。你可以找到它的实现here.

以上所有步骤都符合相关manual pages中描述的POSIX设置的要求。

票数 20
EN

Stack Overflow用户

发布于 2013-01-14 07:10:18

关于你的问题:

在手册页中说,execvp用新的进程映像替换了进程映像。然而,在这里我运行的是命令,而不是可执行文件。

很久很久以前,shell非常有限,几乎所有的UNIX命令都是独立的可执行文件。现在,主要是为了提高速度,UNIX命令的一些子集是在shell内部实现的,这些命令称为builtins。您可以通过type命令检查shell中实现的任何命令是否为内置命令:

代码语言:javascript
复制
λ ~/ type echo
echo is a shell builtin

(内置的完整列表和描述可以在shell的man页面中找到,例如man bash-builtinsman builtin。)

但大多数命令仍然有其对应的可执行文件:

代码语言:javascript
复制
λ ~/ whereis echo
/bin/echo

因此,在您运行时的特定情况下:

代码语言:javascript
复制
char* arg[] = {"ls", "-l", NULL};
execvp(arg[0],arg);

您实际上是在用(最有可能的) /bin/ls的地址空间替换当前进程的地址空间。

我的直觉是,我必须读取文件,并且可能会解析它,以便将参数存储在

中。

你确实有你。但是你也可以使用一些内核中的函数来实现"shebang":

不是将文件名放在单独的文件中,而是添加所谓的shebang作为要进行cat的文件的第一行:

代码语言:javascript
复制
#!/bin/cat

并将chmod +x添加到其中。然后,您可以将其作为可执行文件运行(通过任何exec函数或shell):

代码语言:javascript
复制
λ ~/tmp/ printf '#!/bin/cat\nTEST\n' > cat_me
λ ~/tmp/ chmod +x cat_me
λ ~/tmp/ ./cat_me 
#!/bin/cat
TEST

当然,它有一个缺点,那就是用文件打印内核本身,但在- shebang =)中打印还是很有趣的。

顺便说一句。您所描述的问题非常普遍,以至于有一个名为xargs的特殊可执行文件(在非常简单的解释中),它执行通过标准输入传递的参数列表上的给定程序。有关更多信息,请咨询man xargs

为了便于记忆exec-family,我经常使用下表:

代码语言:javascript
复制
           Figure 8.14. Differences among the six exec functions
+----------+----------+----------+----------+--------+---------+--------+
| Function | pathname | filename | agr list | argv[] | environ | envp[] |
+----------+----------+----------+----------+--------+---------+--------+
|  execl   |    *     |          |     *    |        |    *    |        |
+----------+----------+----------+----------+--------+---------+--------+
|  execlp  |          |    *     |     *    |        |    *    |        |
+----------+----------+----------+----------+--------+---------+--------+
|  execle  |    *     |          |     *    |        |         |   *    |
+----------+----------+----------+----------+--------+---------+--------+
|  execv   |    *     |          |          |    *   |    *    |        |
+----------+----------+----------+----------+--------+---------+--------+
|  execvp  |          |    *     |          |    *   |    *    |        |
+----------+----------+----------+----------+--------+---------+--------+
|  execve  |    *     |          |          |    *   |         |   *    |
+----------+----------+----------+----------+--------+---------+--------+
|  letter  |          |    p     |     l    |    v   |         |   e    |
+----------+----------+----------+----------+--------+---------+--------+

因此,在您的示例中,execvp采用文件名、argv(v)和environ(e)。然后,它尝试通过将filename (在您的例子中为cat)附加到PATH中的每个路径组件来“猜测”路径名(也称为完整路径),直到它找到具有可执行文件filename的路径。

更多关于exec内部情况的信息(包括继承内容)可以在Advanced Programming in the UNIX Environment (2nd Edition) by W. Richard Stevens and Stephen A. Rago,也就是APUE2中找到。

如果您对UNIX内部原理感兴趣,那么您可能应该阅读它。

票数 12
EN

Stack Overflow用户

发布于 2013-01-13 15:21:52

"ls“不仅仅是一个命令,它实际上是一个程序(大多数命令都是)。当你像那样运行execvp时,它会破坏你的整个程序,它的内存,它的堆栈,它的堆,等等。在概念上“清除它”,并将它赋予"ls“,这样它就可以将它用于自己的堆栈、堆等。

简而言之,execvp将销毁您的程序,并将其替换为另一个程序,在本例中为"ls“。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14301407

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档