我正在尝试用c语言重现这个命令:
ls | wc > output.txt为此,我编写了以下程序:
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
int main()
{
pid_t lsFork, wcFork;
int tube[2];
pipe(tube);
lsFork = fork();
if(lsFork == 0) // ls command
{
close(tube[0]);
dup2(tube[1], STDOUT_FILENO);
close(tube[1]);
if(execl("/usr/bin/ls", "ls", NULL) == -1)
perror("Cannot execute ls");
}
else
{
wcFork = fork();
if(wcFork == 0) // wc command
{
sleep(1);
int file = open("output.txt", O_WRONLY | O_CREAT);
if(file == -1)
perror("Cannot open output.txt");
close(tube[1]);
dup2(tube[0], STDIN_FILENO);
close(tube[0]);
dup2(file, STDOUT_FILENO);
close(file);
/*char buffer[BUFSIZ];
read(STDIN_FILENO, buffer, BUFSIZ);
write(STDOUT_FILENO, buffer, BUFSIZ);*/
if(execl("/usr/bin/wc", "wc", NULL) == -1)
perror("Cannot execute wc");
close(STDOUT_FILENO);
}
else // parent
{
int status;
waitpid(lsFork, &status, 0);
waitpid(wcFork, &status, 0);
}
}
return EXIT_SUCCESS;
}但是,程序不会退出。根据htop的说法,wc命令阻塞了程序。为了理解这种行为,我写了一段代码( execl()之前的代码行注释),我不明白这是怎么回事,而不是execl()。我是不是在调用这个函数的时候忘记了什么?
发布于 2015-12-16 09:49:21
父进程仍然有打开的管道,所以wc正在等待,以防父进程决定写入内容( wc需要对其进行计数)。
同时关闭父管道中管道的两端:
else // parent
{
int status;
close(tube[0]); // <---
close(tube[1]); // <---
waitpid(lsFork, &status, 0);
waitpid(wcFork, &status, 0);
}发布于 2015-12-16 15:08:29
不要在你能轻易做到的时候把事情复杂化。尝试下面更简单的代码&看看您是否能理解任何东西。
int main(){
int tube[2];
int fID;
pipe(tube);
if (fork() == 0){
// this is the child process
close(tube[0]); // reading end of the pipe
dup2(tube[1], 1); // stdout ---> pipe writing end
execlp("ls", "ls", NULL);
}else{
if (fork() == 0){
//umask(0022);
fID = open("sample.txt", O_WRONLY | O_CREAT, 0644);
close(tube[1]); // writing end of the pipe
dup2(tube[0], 0); // stdin ----> pipe reading end
dup2(fID, 1);
execlp("wc", "wc", NULL);
}
}
return 0;
}注意如果代码的目的仅仅是实现上面提到的管道,那么你不需要实现任何等待机制。操作系统将自动杀死所有僵尸子进程。此外,execlp("wc", "wc", NULL);会自动阻止程序结束。因此它不会提前退出。
发布于 2015-12-16 09:41:10
您还需要关闭父进程中管道的写入端。
https://stackoverflow.com/questions/34302259
复制相似问题