我正在用C语言写一个shell,我无法理解execvp(filepath,argv)
所需的文件路径参数。
如果用户输入的内容想要在当前目录中运行ls -a
...请说/home/user1
... filepath
和argv
用于运行ls
{1}}在所说的目录中?
filepath
是/home/user1
执行命令的目录,还是命令的位置/bin/ls
?
答案 0 :(得分:2)
filepath
的{{1}}参数可以采用两种形式之一 - 它包含斜杠或不包含斜杠。
execvp()
参数指定可执行文件的路径名,可以是绝对名称(以斜杠开头)或相对名称(不是以斜杠开头,但包含斜杠)。 filepath
函数不对参数进行任何更改,并且假定文件名称存在且可执行,则执行(或不执行)程序。
execvp()
参数指定了一个“简单”名称,例如filepath
。然后,ls
函数尝试执行在excevp()
环境变量中列出的某个目录中找到名为ls
的程序。 $PATH
中的p
用于“路径”,与路径查找一样。
如果用户将execvp()
键入shell,通常的执行方法是创建一个等效于:
ls -a
char *argv[] = { "ls", "-a", 0 };
execvp(argv[0], argv);
现在将执行基于路径的分析,并尝试从execvp()
中列出的某个目录执行ls
。
如果用户向shell键入$PATH
,那么执行该方法的正常方法是创建一个等效于:
/bin/ls -a
char *argv[] = { "/bin/ls", "-a", 0 };
execvp(argv[0], argv);
现在将执行指定的绝对路径名,因为这是用户请求的内容(而不是execvp()
或/usr/bin/ls
)。
请注意,处理实际上是相同的 - 您将命令行拆分为单词;每个单词都成为一个以空指针终止的字符指针数组的元素,并将第一个单词作为'filepath'参数传递给/usr/local/bin/ls
,将整个数组作为第二个参数传递。
显然,shell可以缓存实际可执行文件的位置,而且很多shell都会这样做,因此execvp()
不需要尝试查找程序(并且shell不会调用{{ 1}}但通常使用可执行文件的绝对路径名调用execvp()
。但这不是必需的;它是一种优化。
请注意,没有什么可以阻止你这样做:
execvp()
现在execv()
应该是char *argv[] = { "/honky/tonk/toys", "-a", 0 };
execvp("ls", argv);
而不是argv[0]
,因为它是运行的"/honky/tonk/toys"
可执行文件。您在ls
中找到的内容取决于您在系统上ls
(例如,Mac OS X不支持它),但二进制文件的符号链接应该是指向/proc
的链接。在Linux上,您很容易发现/proc
报告二进制名称(/bin/ls
),即使ps
包含原始参数(因此ls
为/proc/PID/cmdline
})。这是好还是取决于你的观点,但全世界都不是Linux。
答案 1 :(得分:1)
要在当前目录中运行/ bin / ls -a,您需要:
与C argv
一样,main()
与NULL
相同,除了argv[0]
已终止,且路径与char* argv[] = { "/bin/ls", "-a", NULL };
execvp(argv[0], argv);
相同。
{{1}}