我需要创建两个子进程.一个孩子需要运行命令"ls -al"并将其输出重定向到下一个子进程的输入,然后该进程将对其输入数据运行命令"sort -r -n -k 5".最后,父进程需要读取(已经排序的数据)并将其显示在终端中.终端中的最终结果(执行程序时)应该与我直接在shell中输入以下命令相同:"ls -al | sort -r -n -k 5".为此,我需要使用以下方法:pipe(),fork(),execlp().
我的程序编译,但我没有得到所需的输出到终端.我不知道出了什么问题.这是代码:
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int main()
{
int fd[2];
pid_t ls_pid, sort_pid;
char buff[1000];
/* create the pipe */
if (pipe(fd) == -1) {
fprintf(stderr, "Pipe failed");
return 1;
}
/* create child 2 first */
sort_pid = fork();
if (sort_pid < 0) { // error creating Child 2 process
fprintf(stderr, "\nChild 2 Fork failed");
return 1;
}
else if(sort_pid > 0) { // parent process
wait(NULL); // wait for children termination
/* create child 1 */
ls_pid = fork();
if (ls_pid < 0) { // error creating Child 1 process
fprintf(stderr, "\nChild 1 Fork failed");
return 1;
}
else if (ls_pid == 0) { // child 1 process
close(1); // close stdout
dup2(fd[1], 1); // make stdout same as fd[1]
close(fd[0]); // we don't need this end of pipe
execlp("bin/ls", "ls", "-al", NULL);// executes ls command
}
wait(NULL);
read(fd[0], buff, 1000); // parent reads data
printf(buff); // parent prints data to terminal
}
else if (sort_pid == 0) { // child 2 process
close(0); // close stdin
dup2(fd[0], 0); // make stdin same as fd[0]
close(fd[1]); // we don't need this end of pipe
execlp("bin/sort", "sort", "-r", "-n", "-k", "5", NULL); // executes sort operation
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
小智 3
您的父进程wait用于在创建 ls 进程之前完成排序进程。
排序过程需要读取其输入才能完成。它的输入来自 ls,直到wait. 僵局。
您需要创建两个进程,然后wait为它们创建两个进程。
另外,您的文件描述符操作不太正确。在这对调用中:
close(0);
dup2(fd[0], 0);
Run Code Online (Sandbox Code Playgroud)
close 是多余的,因为 dup2 会自动关闭现有的 fd 0(如果有)。您应该在 dup2 之后执行一个操作close(fd[0]),这样您只有一个文件描述符绑定到管道的那一端。如果你想真正健壮,你应该fd[0]==0已经测试凋零,在这种情况下跳过 dup2 并关闭。
将所有这些也应用到另一个 dup2 上。
然后是父进程保持管道打开的问题。我想说,在将父级管道传递给子级之后,您应该关闭父级管道的两端,但是在最后一个之后,read您会发现很奇怪......我不确定为什么会出现这种情况。如果管道运行正确,之后管道将为空,因此不会有任何内容可读取。无论如何,您肯定需要在父级中关闭,否则排序过程将无法完成,因为管道不会指示 EOF,直到所有编写器都关闭。fd[0]waitls|sortfd[1]
奇怪的read是 a之后printf可能会崩溃,因为读取缓冲区不会被'\0'终止。
使用的要点execlp是它会$PATH为您进行查找,因此您不必指定/bin/. 我的第一次测试运行失败了,因为我的排序是在/usr/bin/. 为什么在不必要时硬编码路径?