我有一个项目是在 linux 操作系统上用 C++ 编写一个 shell,它可以运行终端可以运行的命令的子集,如 cd
、ls
等。
我的问题是,如果我使用类似 execl("bin/ls","ls")
的东西,它如何知道从哪里执行 ls
。它会默认只从运行程序的目录运行 ls
吗?如果是这样,我该如何更改它的运行位置,就像我运行 cd foo
然后再次运行 ls 一样。
是的,我正在制作一个受限版本的 bash。
这是我到目前为止运行 ls 的结果。
int quash::ls(字符串路径)
{
pid_t child = 0;
child = fork();
if (child < 0)
{
fprintf( stderr, "process failed to fork\n" );
return 1;
}
if (child == 0)
{
wait(NULL);
}
else
{
execlp("/bin/ls", "ls");
}
return 0;
}
将执行clp()"/bin/ls","ls");打印任何内容还是我必须添加其他内容?
最佳答案
总结
如果您调用 execl("bin/ls", "ls")
那么系统将尝试在名为 的目录中查找名为
在当前工作目录中。这几乎肯定不是您想做的。您可能想要:ls
的文件bin
execlp("ls", "ls);
或
execl("/bin/ls", "ls");
尽管也有可能这些都不是您真正想要的。
更多详情
有许多不同的函数可以用来用新的进程镜像替换当前运行的进程;这些至少包括以下内容:
execl, execv
execle, execve
execlp, execvp
包含 l 的版本是可变的;它们采用以 NULL 结尾的 const char*
参数列表,这些参数定义了应该传递给新可执行文件的 argv
vector 。包含 v 的版本采用单个 char*const[]
参数,它是以 NULL 结尾的字符串数组,用于构造 argv
vector 。
以 e
结尾的版本有一个额外的参数,它是一个 char *const[]
用于构造新的可执行文件的环境变量。其他版本使用现有的环境变量集合。
以 p
结尾的版本以两种方式不同地处理第一个参数:
如果第一个参数不包含 /,则使用(当前)
PATH
环境变量来查找正确的目录。PATH
变量应该是由 : 分隔的目录路径列表,以及文件名(即execlp
的第一个参数或execvp
)在每个目录中依次查找。如果第一个参数确实包含/,那么它的处理方式与其他exec
变体相同:第一个参数必须是实际的可执行文件的路径,通常是绝对路径(即以 / 开头的路径),但也可以是相对路径,在这种情况下,它将被视为相对于当前工作目录。此外,如果找到一个文件但它未被识别为可执行二进制文件,它将被视为一个 shell 脚本,通过传递给默认 shell(通常是
/bin/sh
).在这种情况下,非p
exec
版本只会返回一个错误。 (这与 Posix 未指定的“shebang”执行不同,但通常由系统图像加载程序执行,因此它可以与任何exec
变体一起工作。)
对于 shell 解释器,v 版本要方便得多。不幸的是,没有同时提供 e 和 p 选项的版本(尽管 GNU C 库 glibc
确实提供了一个,execvpe
) 因为没有这种可能性,就无法使用当前的 PATH
变量进行自动路径查找;仅使用新的 PATH
变量。
引用资料:
Posix 定义:http://pubs.opengroup.org/onlinepubs/9699919799/functions/execl.html
execve
的 Linux 联机帮助页(在glibc
中,所有其他exec
变体最终调用execve
): http://linux.die.net/man/2/execve其余
exec
变体的 Linux 联机帮助页:http://linux.die.net/man/3/exec
关于c++ - 编写 shell - 如何确定不同 exec 调用的可执行路径和文件名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22569944/