2

我正在用 C 编写一个 shell,但我无法理解execvp(filepath,argv).

如果键入的用户想要ls -a在他们的当前目录中运行......比方说......在所述目录中运行的and/home/user1会是什么?filepathargvls

filepath执行命令的目录/home/user1还是命令的位置?/bin/ls

4

2 回答 2

5

to的filepath参数execvp()可以采用两种形式之一——它包含斜线或不包含斜线。

带斜线

filepath参数指定可执行文件的路径名,可以是绝对名称(以斜杠开头)或相对名称(不以斜杠开头,但包含斜杠)。该execvp()函数不对参数进行任何更改,并且假设该文件存在并且是可执行的,则执行(或不执行)程序。

没有斜线

参数指定一个“filepath简单”名称,例如ls. 然后,该excevp()函数试图执行一个程序,该程序的名称ls$PATH环境变量中列出的目录之一中找到。pinexecvp()用于“路径”,如路径查找。

应用理论

如果用户键入ls -a一个 shell,执行它的正常方法是创建一个字符指针数组,相当于:

char *argv[] = { "ls", "-a", 0 };

execvp(argv[0], argv);

现在execvp()将执行基于路径的分析,并尝试ls从 中列出的目录之一执行$PATH

如果用户键入/bin/ls -a一个 shell,那么执行它的正常方法是创建一个字符指针数组,相当于:

char *argv[] = { "/bin/ls", "-a", 0 };

execvp(argv[0], argv);

现在execvp()将执行指定的绝对路径名,因为那是用户请求的(而不是,说,/usr/bin/ls/usr/local/bin/ls)。

请注意,处理实际上是相同的——您将命令行拆分为单词;每个单词都成为以空指针结尾的字符指针数组的一个元素,您将第一个单词execvp()作为“文件路径”参数传递,整个数组作为第二个参数传递。

显然,shell 可以缓存实际可执行文件的位置,而许多 shell 都可以,因此execvp()不必尝试查找程序(并且 shell 不调用execvp()但通常execv()使用可执行文件的绝对路径名调用. 但这不是必需的;这是一种优化。

还要注意,没有什么可以阻止你做的:

char *argv[] = { "/honky/tonk/toys", "-a", 0 };
execvp("ls", argv);

现在argv[0]应该是"/honky/tonk/toys"而不是ls,因为它是ls运行的可执行文件。您在其中找到的/proc内容取决于/proc您的系统(例如 Mac OS X 不支持它),但二进制文件的符号链接应该是指向/bin/ls. 在 Linux 上,您很容易发现ps报告二进制名称 ( ls),即使/proc/PID/cmdline包含原始参数 (so argv[0]is /honky/tonk/toys)。这是否好取决于您的观点,但世界上不是Linux。

于 2013-10-06T05:05:57.857 回答
1

要在当前目录中运行 /bin/ls -a,您需要:

与C 程序启动时argv传入的相同,除了终止,路径与.main()NULLargv[0]

char* argv[] = { "/bin/ls", "-a", NULL };
execvp(argv[0], argv);
于 2013-10-06T04:19:25.533 回答