我正在用 C 编写一个 shell,但我无法理解execvp(filepath,argv)
.
如果键入的用户想要ls -a
在他们的当前目录中运行......比方说......在所述目录中运行的and/home/user1
会是什么?filepath
argv
ls
是filepath
执行命令的目录/home/user1
还是命令的位置?/bin/ls
to的filepath
参数execvp()
可以采用两种形式之一——它包含斜线或不包含斜线。
该filepath
参数指定可执行文件的路径名,可以是绝对名称(以斜杠开头)或相对名称(不以斜杠开头,但包含斜杠)。该execvp()
函数不对参数进行任何更改,并且假设该文件存在并且是可执行的,则执行(或不执行)程序。
参数指定一个“filepath
简单”名称,例如ls
. 然后,该excevp()
函数试图执行一个程序,该程序的名称ls
在$PATH
环境变量中列出的目录之一中找到。p
inexecvp()
用于“路径”,如路径查找。
如果用户键入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。
要在当前目录中运行 /bin/ls -a,您需要:
与C 程序启动时argv
传入的相同,除了终止,路径与.main()
NULL
argv[0]
char* argv[] = { "/bin/ls", "-a", NULL };
execvp(argv[0], argv);