2016-11-20 8 views
0

В настоящее время я пишу программу, которая создает дочерний процесс, используя fork(). Этот дочерний процесс должен выполнить команду оболочки «uniq» с опцией «-d», чтобы она читала из stdin. После команды execute я хочу отправить строки как stdin над каналом для программы «uniq». Поэтому после того, как я отправил одну и ту же строку за друг другом, строка должна быть напечатана на stdout (см. uniq man-страница: https://linux.die.net/man/1/uniq). Но ничего не печатается.Почему дочерний процесс выполняет uniq -d не печатать дубликаты, переданные по протоколу stdin?

Вот мой код до сих пор:

void execute_uniq_process() 
{ 
    //create pipe 
    int pipefd[2]; 
    if(pipe(pipefd)<0) 
    { 
     //error handling 
    } 

    //create argv for command: 
    char *argv[] = {"uniq","-d",(char *)0}; 

    //create child process 
    pid_t pid = fork(); 
    int status; 

    switch(pid) 
    { 
     case -1: 
     //error handling 
     break; 

     case 0: 
      //child process 
      //close writing end in pipe 
      close(pipefd[1]); 

      //duplicate stdin 
      dup2(pipefd[0],STDIN_FILENO); 
      close(pipefd[0]); 

      execvp("uniq",argv); 
      exit(errno); 
     break; 

     default: 
      //parent process 
      //close reading end in pipe 
      close(pipefd[0]); 

      //write all commands to pipe 
      write(pipefd[1],"test1",5); 
      write(pipefd[1],"test1",5); 
      write(pipefd[1],"test2",5); 
      //edited: 
      close(pipefd[1]); 

      //waits till child is finished 
      wait(&status); 

      if(WEXITSTATUS(status) != EXIT_SUCCESS) 
      { 
       //error handling 
      } 
     break; 
    } 
} 

Так что я бы ожидать, что печатается «test1» в оболочке. Я также удивляюсь, как закончить процесс uniq. Я думаю, что может возникнуть проблема с написанием, поэтому мне нужно смоделировать «ввод» после каждой строки, которую я пишу в трубе.

+1

Вы должны закрыть трубку, прежде чем ждать завершения 'uniq', потому что она не будет знать, что у нее есть EOF, пока вы не закроете трубку. И вы не указали ни одной строки на стандартный ввод 'uniq'. Системный вызов 'write()' записывает то, что вы говорите, чтобы писать, и, конечно же, не добавляет никаких новых строк по своему собственному желанию. –

+0

Спасибо. Я отредактировал свой пост и закрыл трубку, прежде чем подождать uniq-процесса. Теперь он завершается. Но до сих пор я не понимаю, почему ничего не написано для stdin uniq. Читаемый конец ребенка был направлен на stdin. И родитель пишет в трубе. Извините за вопрос, я новичок в этой теме. – hiaslosch17

+0

Вы не написали целую строку ввода 'uniq'; в том, что вы пишете, нет новых строк, поэтому нет дублирования ('uniq' видит' test1test1test2' без новой строки). См. Мой ответ. –

ответ

0

Вы должны закрыть трубу перед тем, как дождаться uniq, чтобы закончить, потому что она не будет знать, что у нее есть EOF, пока вы не закроете трубку. И вы не указали ни одну строку на стандартный ввод uniq, потому что в данных, которые были написаны, нет новой строки. Системный вызов write() записывает только то, что вы говорите, чтобы писать; он, конечно, не добавляет никаких новых строк по своему собственному желанию.

Эти изменения, и вся мелочи, приводят к:

#include <errno.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <sys/wait.h> 
#include <unistd.h> 

int main(void) 
{ 
    int pipefd[2]; 
    if (pipe(pipefd) < 0) 
    { 
     fprintf(stderr, "Failed to create pipe\n"); 
     return 1; 
    } 

    char *argv[] = {"uniq", "-d", (char *)0}; 

    pid_t pid = fork(); 

    switch (pid) 
    { 
    case -1: 
     fprintf(stderr, "Failed to fork\n"); 
     return 1; 

    case 0: 
     close(pipefd[1]); 
     dup2(pipefd[0], STDIN_FILENO); 
     close(pipefd[0]); 
     execvp(argv[0], argv); 
     fprintf(stderr, "Failed to exec %s\n", argv[0]); 
     exit(errno); 

    default: 
     close(pipefd[0]); 
     write(pipefd[1], "test1\n", 6); 
     write(pipefd[1], "test1\n", 6); 
     write(pipefd[1], "test2\n", 6); 
     close(pipefd[1]); 
     int status; 
     int corpse = wait(&status); 

     if (WEXITSTATUS(status) != EXIT_SUCCESS) 
     { 
      fprintf(stderr, "Child (%s) exited (PID %d, status 0x%.4X)\n", argv[0], corpse, status); 
     } 
     break; 
    } 
    return 0; 
} 

Это выводит test1 при запуске.