코드는 읽기 또는 쓰기 작업을 수행하지 않습니다. 그냥 배관 (배관을 정렬)됩니다.
두 개의 파이프와 두 개의 자식을 만듭니다. 첫 번째 자식은 cat
명령을 실행합니다. 두 번째는 grep
명령이고 부모는 wc
프로그램을 실행합니다. 프로그램의 경로 이름이 없으므로 코드는 execvp()
을 사용합니다.
조금 더 리팩토링에 대한 작업을 조심스럽게 파이프 처리와
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
static void err_exit(const char *fmt, ...);
static void exec_head(char **args, int *p1, int *p2);
static void exec_tail(char **args, int *p1, int *p2);
static void exec_middle(char **args, int *p1, int *p2);
static void exec_cmd(char **args, int *p1, int *p2);
int main(void)
{
char *cmd1[] = { "cat", "file1.txt", 0 };
char *cmd2[] = { "grep", "keyword", 0 };
char *cmd3[] = { "wc", 0 };
int pipe12[2];
int pipe23[2];
pid_t pid1;
pid_t pid2;
if (pipe(pipe12) != 0 || pipe(pipe23) != 0)
err_exit("Failed to create pipes");
if ((pid1 = fork()) < 0)
err_exit("Failed to fork (child1)");
else if (pid1 == 0)
exec_head(cmd1, pipe12, pipe23);
else if ((pid2 = fork()) < 0)
err_exit("Failed to fork (child2):");
else if (pid2 == 0)
exec_middle(cmd2, pipe12, pipe23);
else
exec_tail(cmd3, pipe12, pipe23);
/*NOTREACHED*/
return(-1);
}
/* Execute head process in pipeline */
/* Close both pipes in p2; connect write end of pipe p1 to stdout */
static void exec_head(char **args, int *p1, int *p2)
{
if (dup2(p1[1], 1) < 0)
err_exit("Failed to duplicate file descriptor to stdout (%s)", args[0]);
exec_cmd(args, p1, p2);
/*NOTREACHED*/
}
/* Execute tail process in pipeline */
/* Close both pipes in p1; connect read end of p2 to standard input */
static void exec_tail(char **args, int *p1, int *p2)
{
if (dup2(p2[0], 0) < 0)
err_exit("Failed to duplicate file descriptor to stdin (%s)", args[0]);
exec_cmd(args, p1, p2);
/*NOTREACHED*/
}
/* Execute middle command in pipeline */
/* Connect read end of p1 to stdin; connect write end of p2 to stdout */
static void exec_middle(char **args, int *p1, int *p2)
{
if (dup2(p1[0], 0) < 0)
err_exit("Failed to duplicate file descriptor to stdin (%s)", args[0]);
if (dup2(p2[1], 1) < 0)
err_exit("Failed to duplicate file descriptor to stdout (%s)", args[0]);
exec_cmd(args, p1, p2);
/*NOTREACHED*/
}
/* Close all descriptors for pipes p1, p2 and exec command */
static void exec_cmd(char **args, int *p1, int *p2)
{
close(p1[0]);
close(p1[1]);
close(p2[0]);
close(p2[1]);
execvp(args[0], args);
err_exit("Failed to execute %s", args[0]);
/*NOTREACHED*/
}
static void err_exit(const char *fmt, ...)
{
int errnum = errno;
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
if (errnum != 0)
fprintf(stderr, ":%d: %s", errnum, strerror(errnum));
putc('\n', stderr);
exit(EXIT_FAILURE);
}
, 당신은 (표준 입력되기 위해 기술자를 지정하거나 -1 혼자 표준 입력 남겨 두어야 경우 exec_head()
, exec_tail()
및 exec_middle()
기능을 제거 할 수, 기술자를 지정 또는 stdout을 홀로 두어야하는 경우 -1), 단일 배열 4를 사용하고 그에 따라 pipe()
시스템 호출에 대한 호출을 수정하여 파이프 처리를 간소화 할 수 있습니다. 그러면 코드는 아마도 dup2()
의 두 번째 인수에 대해 0과 1 대신에 STDIN_FILENO
과 STDOUT_FILENO
을 사용해야합니다. 파이프의 읽기 및 쓰기 끝에 대한 상수는 정의되어 있지 않습니다 (여기서는 enum { PIPE_READ, PIPE_WRITE };
이 유용 할 수 있습니다).
stdin에서'write'가 아닌'read'를 원합니다. – GWW
@GWW해야합니까? 하지만 그 안에 * 쓰고 싶지 않아? 출력을 보면 * 입력 *을 쓰는 것으로 가정하면 ... * – TrewTzu
프로세스 1 (예 : cat)에서 stdout에 쓰고 싶을 때 처리 중입니다. stdin에서 읽고 stdout에 쓰고 싶은 grep 2 개 (grep), 그리고 stdin에서 읽고 stdout에 쓰고 싶은 프로세스 3 (wc) – GWW