为什么 execlp 不允许我使用管道?

Why doesn't execlp allow me to use a pipe?

#include <stdio.h>
#include <unistd.h>
main()
{
    execlp("ls" , "ls", "-l", "|" , "sort", NULL);    
}

怎么了?请帮忙。

如果我这样写:execlp("ls" , "ls", "-l", NULL); 然后结果会显示在屏幕上,如果我尝试这个 execlp("ls" , "ls", "-l", "|" , "sort", NULL); 屏幕会显示错误消息 无法访问

为什么?有人有什么主意吗?为什么当我执行命令 execlp?

时不允许我使用管道 (|)

管道是一种 shell 结构。 execlp() 不受 shell 解析;它将参数直接传递给命名命令。要获得 shell 功能,您需要明确启动 shell 进程。

execl("/bin/sh", "/bin/sh", "-c", "ls -l | sort", NULL);

在这种情况下,最好指定 shell /bin/sh 的绝对路径,这意味着您可以使用 execl 而不是 execlp

哎呀,你弄糊涂了。 exec... 系列函数允许执行一个程序 替换 调用程序。因此,您的程序只需执行 ls 命令,并以 "-l""|""sort" 作为参数。

这是它交互给出的内容:

$ ls "-l" "|" "sort"
ls: sort: No such file or directory
ls: |: No such file or directory

在另一端,然后你在shell中正常执行ls -l | sort| 被shell[=42解释=].还有 shell :

  • 作为第一个命令启动 ls -l
  • 作为第二个命令启动 sort
  • 第一个命令的输出连接到第二个命令的输入。

您可以在 forkpipeexeclp 的帮助下明确地做到这一点,但是您必须准备管道,并明确地 fork 以拥有 2 个进程.

或者,您可以让 shell 来完成这项工作:

execlp("/bin/sh" , "sh", "-c", "ls -l | sort", NULL);

有一种简单的方法可以做到这一点。它涉及使用函数 popen:

#include <stdio.h>
#include <unistd.h>

int main() {

    FILE* out  = popen("ls -l | sort", "w");

    pclose(out);

    return 0;  
}

但是它可能不是您想要的,因为它不使用 exec。

当你在shell

中写入如下命令
ls -l | sort

执行了两个程序:lssort

管道符(|)表示第一个的输出应该重定向到第二个的标准输入。此管道由您的 shell 解释。它不是您命令的参数。

execlp 将您的程序名称及其参数作为参数。

所以当你写

execlp("ls" , "ls", "-l", "|" , "sort", NULL);

没有任何意义,因为 |sort 不是 ls 的参数。

你想要的是 shell 为你做的事:

  1. 声明一个pipe
  2. 创建一个分支,将 stdout 重定向到管道(使用 dup)并执行 ls:

    execlp("ls" , "ls", "-l", NULL);
    
  3. 创建一个分支,将管道重定向到标准输入并执行 sort:

    execlp("sort" , "sort", NULL);
    
  4. 关闭管道,等待,等等