execvp如何运行命令?

as3*_*unt 21 c unix file

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

char* arg[] = {"ls", "-l", NULL};
execvp(arg[0],arg);
Run Code Online (Sandbox Code Playgroud)

我想知道我跑的时候在这里发生了什么execvp.在手册页中,它表示execvp用新的图像替换过程图像的图像.但是在这里我运行的命令不是可执行文件.

具体来说,有一个命令特别需要输入,例如cat.如果我有一个文本文件text.txt,其中包含cat所需的文件名,并且我将stdin重定向到文件的文件流,那么输出execle("cat","cat",NULL)execvp("cat", arg)(显然arg存储"cat"NULL)会导致控制台中的输出为cat /filename将?我的直觉是我必须读取文件并可能解析它以将参数存储在arg中.但是我想确定一下.

提前致谢!

Mic*_*kis 19

这是execvp电话中发生的事情:

  1. PATH如果适用,您的libc实现将搜索要执行的文件.类UNIX系统中的大多数(如果不是全部)命令都是可执行文件.如果不是,会发生什么?试试吧.看看glibc是如何做到的.
  2. 通常,如果找到可执行文件,execve则会进行调用.部分execve可以在libc中实现,也可以是系统调用(如在Linux中).
  3. Linux通过为它分配内存,打开它,调度它以执行,初始化内存结构,从提供的参数设置其参数和环境来准备execvp程序,找到适合加载二进制文件的处理程序,并设置当前任务(execvp调用者)没有执行.你可以在这里找到它的实现.

上述所有步骤均符合POSIX设定的要求,相关手册页中对此进行了描述.


Sav*_*btz 12

关于你的问题:

在手册页中,它表示execvp用新的图像替换过程图像的图像.但是在这里我运行的命令不是可执行文件.

很久以前shell非常有限,几乎所有的UNIX命令都是独立的可执行文件.现在,主要是出于速度目的,UNIX命令的一些子集在shell本身内部实现,这些命令被调用builtins.您可以通过以下type命令检查shell中实现的内置命令:

? ~/ type echo
echo is a shell builtin
Run Code Online (Sandbox Code Playgroud)

(可以在manshell的页面中找到包含描述的内置列表的完整列表,例如man bash-builtinsman builtin.)

但是仍然大多数命令仍然具有可执行文件:

? ~/ whereis echo
/bin/echo
Run Code Online (Sandbox Code Playgroud)

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

char* arg[] = {"ls", "-l", NULL};
execvp(arg[0],arg);
Run Code Online (Sandbox Code Playgroud)

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


我的直觉是我必须读取文件并可能解析它以将参数存储在arg中.

的确,你有.但你也可以使用一些内核函数来代表"shebang":
不要将文件名放在单独的文件中,而是将所谓的shebang添加为你想要cat的文件的第一行:

#!/bin/cat
Run Code Online (Sandbox Code Playgroud)

并添加chmod +x它.然后你可以将它作为可执行文件运行(通过任何exec函数或shell):

? ~/tmp/ printf '#!/bin/cat\nTEST\n' > cat_me
? ~/tmp/ chmod +x cat_me
? ~/tmp/ ./cat_me 
#!/bin/cat
TEST
Run Code Online (Sandbox Code Playgroud)

因为它有一个缺点shebang就是用文件打印自己,但是在内核中这样做很有趣=)

BTW.您描述的问题是否如此常见,以至于有一个特殊的可执行文件xargs(在非常简化的解释中)执行通过stdin传递的参数列表上的给定程序.有关更多信息,请咨询man xargs.


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

           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    |
+----------+----------+----------+----------+--------+---------+--------+
Run Code Online (Sandbox Code Playgroud)

所以在你的情况下execvp需要filename,argv(v)和environ(e).然后它尝试通过将filename(在您的情况下cat)附加到每个路径组件来"猜测"路径名(也称为完整路径),PATH直到找到具有可执行文件的路径filename.

关于Whats在幕后发生的更多信息exec(包括继承内容)可以在W.Richard Stevens和Stephen A. Rago又名APUE2 的UNIX环境(第2版)的高级编程中找到.
如果您对UNIX内部感兴趣,您应该阅读它.