我想像在 Unix 终端中一样创建自己的管道(只是为了练习)。它应该使应用程序在这样的引号中执行:
管道 "ls -l" "grep" ....
我知道我应该使用 fork()、execl() (exec*) 和 api 来重定向标准输入和标准输出。但是 execl 是否有任何替代方法可以仅使用一个包含应用程序路径和参数的参数来执行带有参数的应用程序?有没有办法不手动解析“ls -l”,而是将它作为一个参数传递给 execl?
如果您只有一个命令行而不是参数向量,请让 shell 为您进行解析:
execl("/bin/sh", "sh", "-c", the_command_line, NULL);
当然,不要让不受信任的远程用户输入此命令行。但是,如果您开始处理不受信任的远程用户输入,您应该尝试按照正常用法而exec[vl]
不是命令行来安排将实际隔离参数列表传递给目标应用程序。
execl()
实际上,只有在编译时知道命令的参数数量时才能真正使用。在 shell 中,您通常会使用execv()
orexecvp()
代替;这些可以处理要执行的命令的任意数量的参数。理论上,您execv()
在给出命令的路径名时使用,而在没有给出命令的路径名时使用execvp()
(它对命令进行基于 PATH 的搜索)。但是,execvp()
处理“给定路径”的情况,所以只需使用execvp()
.
所以,对于你的pipeline
命令,你最终会得到一个孩子,使用相当于:
char *args_1[] = { "ls", "-l", 0 };
execvp(args_1[0], args_1);
另一个孩子最终将使用相当于:
char *args_2[] = { "grep", "pattern", 0 };
execvp(args_2[0], args_2);
当然,除了您将从命令行参数创建这些字符串,而不是通过初始化创建,如图所示。请注意,这grep
需要一个模式来搜索。
你还有管道问题需要解决。确保您关闭了足够多的管道文件描述符。当您dup()
或dup2()
管道连接到标准输入或标准输出时,您将关闭函数中的两个文件描述符pipe()
。