叉子和管道,我做错了什么?
forks and pipes, what am I doing wrong?
我正在尝试了解管道和重定向。为此,我正在做一些小程序来习惯相关的系统调用。在这一个上,我尝试在文件 pipe4.c 上启动 cat,并将其输出通过管道传输到我之后启动的 grep。它不起作用,我不明白结果,
我虽然逻辑很好,但我显然用叉子遗漏了一些东西。我做错了什么?
代码如下:
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#define BUFF_SIZE 4092
//redirecting the output of a program ('cat' here)
//to the stdin of another program ('grep' here)
void err_handler(char *msg)
{
perror(msg);
exit(EXIT_FAILURE);
}
int main(void)
{
//creating a pipe to communicate between the child processes
int p[2];
if (pipe(p) < 0)
err_handler("pipe error: ");
/*
** forking for cat
*/
pid_t cat_pid;
if ((cat_pid = fork()) < 0)
err_handler("fork error: ");
if (cat_pid)
close(p[1]);
if (!cat_pid) {
printf("===CAT===\n");
dup2(p[1], STDOUT_FILENO);
close(p[0]);
close(p[1]);
execl("/bin/cat", "cat", "pipe4.c", NULL);
exit(EXIT_SUCCESS);
}
/*
** forking for grep
*/
pid_t grep_pid;
if ((grep_pid = fork()) < 0)
err_handler("fork_error: ");
if (grep_pid)
wait(&grep_pid);
if (!grep_pid) {
printf("===GREP===\n");
dup2(p[0], STDIN_FILENO);
close(p[0]);
close(p[1]);
execl("/bin/grep", "grep", "\"err_handler\"", NULL);
exit(EXIT_SUCCESS);
}
return 0;
}
我只在我的终端上看到这个:
> pom@parrot ~/dev/19/syscall> sudo ./a.out
> ===GREP===
> ===CAT===
> ===GREP===
每次执行时,这些行的打印顺序都会改变。
我期望的显然是我的 pipe4.c 文件中包含 "err_handler" 的所有行,就像我直接在 shell:
中做的一样
> pom@parrot ~/dev/19/syscall> cat pipe4.c | grep "err_handler"
> void err_handler(char *msg) err_handler("pipe error: ");
> err_handler("fork error: "); err_handler("creat error: ");
> err_handler("read error: ");
> err_handler("write error:");
有(我认为!)3 个主要问题。
1) 您没有正确使用等待。我建议改用 waitpid。
2) 至少在我的系统上,/bin/grep 不存在。它是 /usr/bin/grep。但是由于您在 exec
失败时返回 EXIT_SUCCESS,因此您没有看到错误。您应该将 execl (...); exit(EXIT_SUCCESS)
替换为 execl(...); perror("execl"); exit(EXIT_FAILURE);
3) 您正在搜索字面引号。就好像你 运行:
grep '"err_handler"'
也就是说,当你生成 grep 时,execl 的参数应该是 "err_handler"
,而不是 "\"err_handler\""
我正在尝试了解管道和重定向。为此,我正在做一些小程序来习惯相关的系统调用。在这一个上,我尝试在文件 pipe4.c 上启动 cat,并将其输出通过管道传输到我之后启动的 grep。它不起作用,我不明白结果, 我虽然逻辑很好,但我显然用叉子遗漏了一些东西。我做错了什么?
代码如下:
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#define BUFF_SIZE 4092
//redirecting the output of a program ('cat' here)
//to the stdin of another program ('grep' here)
void err_handler(char *msg)
{
perror(msg);
exit(EXIT_FAILURE);
}
int main(void)
{
//creating a pipe to communicate between the child processes
int p[2];
if (pipe(p) < 0)
err_handler("pipe error: ");
/*
** forking for cat
*/
pid_t cat_pid;
if ((cat_pid = fork()) < 0)
err_handler("fork error: ");
if (cat_pid)
close(p[1]);
if (!cat_pid) {
printf("===CAT===\n");
dup2(p[1], STDOUT_FILENO);
close(p[0]);
close(p[1]);
execl("/bin/cat", "cat", "pipe4.c", NULL);
exit(EXIT_SUCCESS);
}
/*
** forking for grep
*/
pid_t grep_pid;
if ((grep_pid = fork()) < 0)
err_handler("fork_error: ");
if (grep_pid)
wait(&grep_pid);
if (!grep_pid) {
printf("===GREP===\n");
dup2(p[0], STDIN_FILENO);
close(p[0]);
close(p[1]);
execl("/bin/grep", "grep", "\"err_handler\"", NULL);
exit(EXIT_SUCCESS);
}
return 0;
}
我只在我的终端上看到这个:
> pom@parrot ~/dev/19/syscall> sudo ./a.out
> ===GREP===
> ===CAT===
> ===GREP===
每次执行时,这些行的打印顺序都会改变。 我期望的显然是我的 pipe4.c 文件中包含 "err_handler" 的所有行,就像我直接在 shell:
中做的一样> pom@parrot ~/dev/19/syscall> cat pipe4.c | grep "err_handler"
> void err_handler(char *msg) err_handler("pipe error: ");
> err_handler("fork error: "); err_handler("creat error: ");
> err_handler("read error: ");
> err_handler("write error:");
有(我认为!)3 个主要问题。
1) 您没有正确使用等待。我建议改用 waitpid。
2) 至少在我的系统上,/bin/grep 不存在。它是 /usr/bin/grep。但是由于您在 exec
失败时返回 EXIT_SUCCESS,因此您没有看到错误。您应该将 execl (...); exit(EXIT_SUCCESS)
替换为 execl(...); perror("execl"); exit(EXIT_FAILURE);
3) 您正在搜索字面引号。就好像你 运行:
grep '"err_handler"'
也就是说,当你生成 grep 时,execl 的参数应该是 "err_handler"
,而不是 "\"err_handler\""