Linux中execlp()函数的工作原理令我困惑,求解。

56

我已经花费了最近的两天时间来理解execlp()系统调用,但是到现在为止我还是一头雾水。让我直入主题吧。

execlpman页面声明该系统调用为int execlp(const char *file, const char *arg, ...);,其中描述为:在execl(),execlp()和execle()函数中的const char arg和随后的省略号可以被视为arg0、arg1,... , argn。

然而,在我们的教材中,我看到这个系统调用是这样调用的:execlp(“/bin/sh”, ..., “ls -l /bin/??”, ...);("..."是供我们作为学生自己找出的)。 然而,这个系统调用甚至与系统调用的man页面声明完全不同。

我非常困惑。感激任何帮助。


因为在手册中它是函数的定义,我猜在你的教科书中它是如何使用它的示例。 - Alexis
你说得对。但是在上面的例子中它究竟想要做什么,以及它如何被使用呢?我觉得谷歌关于execlp()的信息非常匮乏。 - Arman Iqbal
3
你的意思是它“根本不像”声明吗?这些参数是“char *”。 这非常接近“char *”! - William Pursell
2个回答

104

这个原型:

  int execlp(const char *file, const char *arg, ...);

execlp是一个可变参数函数,它需要2个const char *参数。如果有任何其他参数,则这些参数都将传递给我们要运行的程序 - 这些参数也是char *类型的C字符串(最后一个参数必须是NULL指针)。

因此,file参数是要执行的可执行文件的路径名。arg是我们想要在可执行文件中出现为argv [0]的字符串。按照惯例,argv [0]只是可执行文件的文件名,通常设置为与file相同。

现在,"..."是要传递给可执行文件的附加参数。

假设你从命令行/ shell中运行此命令:

$ ls

这将是 execlp("ls", "ls", (char *)NULL);

或者如果你运行

$ ls -l /

这将是execlp("ls", "ls", "-l", "/", (char *)NULL);

现在进行到execlp("/bin/sh", ..., "ls -l /bin/??", ...);

在这里,你要进入shell,即/bin/sh,并给它一个要执行的命令。该命令是"ls -l /bin/??"。你可以从命令行/ shell手动运行它:

 $ ls -l /bin/??

那么,如何运行Shell并告诉它执行命令?您需要打开您的Shell的文档/手册并阅读它。

您想要运行的命令是:

$ /bin/sh -c "ls -l /bin/??"

这将变成

  execlp("/bin/sh","/bin/sh", "-c", "ls -l /bin/??", (char *)NULL);

顺便提一句: /bin/?? 是在进行模式匹配,这个模式匹配是由 shell 完成的,并且它会扩展到所有在 /bin/ 目录下有两个字符的文件。如果你只是简单地执行了

  execlp("ls","ls", "-l", "/bin/??", (char *)NULL);

如果没有一个名为/bin/??的文件,那么也许什么都不会发生,因为没有一种shell可以解释和扩展/bin/??。


你需要特殊的头文件来运行像这样的shell命令吗?我尝试了上面的例子,但是我收到了一堆错误,比如“error: stray ‘\235’ in program”和“error: too few arguments to function ‘execlp’”。我猜测这是因为缺少一个头文件。我使用的函数是这样的:execlp("/bin/sh","/bin/sh", "-c", mystring, (char *)NULL);其中mystring是一个字符串变量,包含我想要execlp()执行的任何bash命令的输入字符串。 - Arman Iqbal
@ArmanIqbal 这里的引号不知怎么变了。但这是C代码,所以将字符串改为用双引号括起来。这些:"此外,阅读execlp的手册,以了解需要包含哪些头文件。 - nos

18

execl的限制在于执行shell命令或任何不在当前工作目录中的脚本时,必须传递命令或脚本的完整路径。

例如:

execl("/bin/ls", "ls", "-la", NULL);

传递可执行文件的完整路径的解决方法是使用函数 execlp ,它会在由PATH指向的目录中搜索文件(execlp的第一个参数):

execlp("ls", "ls", "-la", NULL);

1
如果我只提供目录名称而不是完整文件路径,使用execl(“/ bin”,“ls”,“-la”,NULL)会起作用吗? - pankaj kushwaha
@pankajkushwaha:不,第一个参数必须指向您要执行的可执行文件。 - lihudi
你不一定需要传递完整路径;例如,你可以传递 ../bin/some_command - Keith Thompson

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