2011-09-03 2 views
0

저는 Unix 배관 시스템을 모방 한 작은 프로그램을 작성하고 있습니다 (예 : "cat file1.txt | grep keyword | wc").자제 배관 용 stdin에 쓰기

dup2()과 파이프를 사용하여 stdout에서 프로그램의 출력을 수집 할 수는 있지만 다음 프로세스로 피드하는 방법을 찾지 못합니다.

write(stdin, buffer, buffer_size); 

하지만 나를 위해 작동하지 않습니다 :

은 처음 엔 나는 그냥 같은, 단순한 생각했다. stdout에 대해서는 많은 정보가 있지만 stdin에 대해서는 그렇지 않습니다.

도움이 될 것입니다.

+0

stdin에서'write'가 아닌'read'를 원합니다. – GWW

+0

@GWW해야합니까? 하지만 그 안에 * 쓰고 싶지 않아? 출력을 보면 * 입력 *을 쓰는 것으로 가정하면 ... * – TrewTzu

+0

프로세스 1 (예 : cat)에서 stdout에 쓰고 싶을 때 처리 중입니다. stdin에서 읽고 stdout에 쓰고 싶은 grep 2 개 (grep), 그리고 stdin에서 읽고 stdout에 쓰고 싶은 프로세스 3 (wc) – GWW

답변

1

코드는 읽기 또는 쓰기 작업을 수행하지 않습니다. 그냥 배관 (배관을 정렬)됩니다.

두 개의 파이프와 두 개의 자식을 만듭니다. 첫 번째 자식은 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_FILENOSTDOUT_FILENO을 사용해야합니다. 파이프의 읽기 및 쓰기 끝에 대한 상수는 정의되어 있지 않습니다 (여기서는 enum { PIPE_READ, PIPE_WRITE };이 유용 할 수 있습니다).

2

귀하의 질문을 이해하기 때문에 귀하의 프로그램에서 cat file1.txt | grep keyword | wc 명령을 실행하고 싶다는 뜻입니다.

pipe()으로 프로그램 사이에 파이프를 설정하여이 작업을 수행 할 수 있습니다. 실행하려는 각 프로그램에 대해 몇 번. 다른 분기 된 프로세스에서 stdinstdout을 생성 된 파이프의 올바른 끝으로 설정하십시오. 모든 설정이 완료되면 exec()으로 전화하여 cat, grepwc과 같은 다른 프로그램을 올바른 매개 변수로 실행할 수 있습니다.

최종 출력을 얻으려면 프로그램이 wc 프로그램 이후에 파이프에서 읽는 것 이상일 수 있습니다.