我正在用 C 编写一个 shell,但我无法理解execvp(filepath,argv).
如果键入的用户想要ls -a在他们的当前目录中运行......比方说......在所述目录中运行的and/home/user1会是什么?filepathargvls
是filepath执行命令的目录/home/user1还是命令的位置?/bin/ls
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。
要在当前目录中运行 /bin/ls -a,您需要:
与C 程序启动时argv传入的相同,除了终止,路径与.main()NULLargv[0]
char* argv[] = { "/bin/ls", "-a", NULL };
execvp(argv[0], argv);