使用execve运行位于PATH环境变量中的可执行文件

5

我正在用C语言编写一个简单的shell。为了执行一个命令,shell需要创建一个子进程,然后使用exec函数来运行该命令。

我正在使用execve函数,如下所示:

execve(argList[0],argList,envList);

这里的argList和envList是char*(string)数组,具有以下值(例如):

argList={"ls",NULL}
envList={"/bin",NULL}

我认为由于ls在/bin目录中作为可执行文件存在,所需的exec应该与ls具有相同的效果(当然是在LINUX系统上)。

然而,execve命令无法执行环境变量中存在的可执行文件。

对于在当前工作目录中运行的可执行文件,它可以完美地工作。

我错在哪里了?


结论:我错误地将环境视为完全不同的东西。[抱歉:)] 环境数组负责为子进程设置环境。
因此,正如Jim指出的那样,正确的程序是以以下格式设置环境变量:

envList = { "HOME=/root", PATH="/bin:/sbin", NULL }

这里所解释的那样,进一步地,为了使用execve(而不是execvp)来实现上述结果,正如Nemo所解释的那样,我们可以始终对PATH中的目录进行重复调用。如果文件不存在,execve将失败。

2个回答

6

execve 不会搜索 PATH。您需要使用 execlp 或类似的函数。请参见POSIX 参考文献以获取详细信息。

在 Linux 上,您可能需要使用 execvpe,但这是非标准的。

(此外,这些函数都不是标准 C 的一部分。您应该为您的问题添加一个特定于平台的标签,如 "posix" 或 "linux"。)


谢谢你的答案。我已经尝试使用execlp,并且它确实有效。然而,为了理解起见,我还想尝试使用execve来完成相同的操作。因此,我首先使用getenv("PATH")获取了环境变量,并将路径分割成多个目录,并将其存储在envList数组中。据我所知,这个命令应该会查找每个PATH目录,并在其中任何一个目录中找到可执行文件时运行它。 注意:我怀疑这可能与execve的第一个参数是文件名而不是路径有关。但我还不确定。 - Saurabh Agarwal
1
如果您手动将PATH的每个元素添加到文件名的前面,然后一遍又一遍地尝试execve,那应该可以解决问题... execve使用完整的文件名作为第一个参数。如果文件名不以/开头,则会相对于当前工作目录进行查找;execve不会搜索PATH - Nemo
1
@SaurabhAgarwal envlist并不像那样工作...它为execed程序提供环境字符串。 - Jim Balter

3
envList={"/bin",NULL}

这是不正确的。 envList 提供了 exec 程序的环境字符串;它不是搜索列表或路径列表。一个正确的 envList 更像是这样的:

envList = { "HOME=/root", "PATH=/bin:/sbin", NULL }

我不明白这怎么能成为被接受的答案。对于envList的建议更改对于execve查找和执行程序没有任何作用。 - Ted Lyngmo
@TedLyngmo 嗯,没有这样的能力。请注意,标题中没有问题 - 标题指的是实际上无法做到的事情。唯一的问题是“我错在哪里了?”...答案部分在这个答案中,在Nemo的答案中,在那个答案下Nemo和我发表的评论中,在OP的结论中也有一部分。如果你想把所有这些捆绑成自己的答案,或者编辑这个答案以包括所有这些内容,随意这样做。 - Jim Balter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接