2015-11-19 2 views
4

Может кто-нибудь объяснить мне, почему у моего вывода есть дубликаты в нем из команды ls. Нормальная работа ls -l | sort не дает мне дублированный результат, так что может быть проблемой?Дублирование выходных труб

По сути, я пытаюсь передать вывод из одной команды и ввести ее в другую команду. Программа работает до сих пор, но на выходе отображаются повторяющиеся данные. Кроме того, и объяснение того, почему я должен был бы сделать закрытие после dup2 было бы действительно полезно :)

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


// function declarations 
void executeLs(int data_pipe[]); 
void executeSort(int data_pipe[]); 

int main(){ 

     int data_pipe[2]; // array storing the file descriptors 
     int childls_pid; // ls child process 
     int childSort_pid; // sort child process 
     int rc; // return vaue of the pipe 
     int child_status1; 
     int child_status2; 

     rc = pipe(data_pipe); 
     if(rc == -1){ 
      perror("pipe"); 
      exit(1); 
     } 


     childls_pid = fork(); 
     childSort_pid = fork(); 

     // Ls Child process 
     switch(childls_pid) { 
     case -1: 
       perror("fork childLs Error"); 
       exit(1); 
     case 0: 
       // inside of child process 
       executeLs(data_pipe); 
       exit(0); 
     default: 
      break; 
     } 

     // Sort child process 
     switch(childSort_pid) { 
     case -1: 
       perror("fork childSort Error"); 
       exit(1); 
     case 0: 
       executeSort(data_pipe); 
       exit(0); 
     default: 
       wait(&child_status2); 
     } 
     return 0; 
} 
void executeLs(int data_pipe[]){ 

    // Closes the read file descriptor 
    close(data_pipe[0]); 

    dup2(data_pipe[1], STDOUT_FILENO); 

    // confused as to why this is necessary 
    close(data_pipe[1]); 

    execlp("ls", "ls", "-1", NULL); 
} 
void executeSort(int data_pipe[]){ 

    // close the write file descriptor 
    close(data_pipe[1]); 

    dup2(data_pipe[0], STDIN_FILENO); 
    close(data_pipe[0]); 
    execlp("sort","sort", NULL); 
} 
+0

Вам нужно закрыть трубу FDs в родительском после того, как вы разветвите детей. – Barmar

+0

Разве это не то, что я делаю внутри своей основной функции? Подожди, позволь мне понять это прямо. Если я закрываю свои трубы внутри моей дочерней процессии, это не закрывает функцию pipe внутри моего родительского процесса? – Xavier

+0

Вы должны всегда вызывать '_exit' (не' exit') после неудачного 'exec' *. 'exit' сбрасывает буферы stdio. Если вы 'exec'ing, у вас текущий процесс, есть копия буферов stdio, которые никогда не предназначались для очистки. – PSkocik

ответ

2

Причина заключается в том, что вы разветвление больше процессов, чем вы рассчитывали. Когда вы делаете:

childls_pid = fork(); 
    childSort_pid = fork(); 

вы делаете как в оригинальном родительском процессе и процессе, созданный первым fork() второго fork(). Таким образом, теперь у вас есть следующий процесс: дерево

parent 
    childls 
     childSort 
    childSort 

В обоих childls и childls->childSort, childls_pid является 0, поэтому они оба выполнить условие case 0:, который работает executeLs().

Вам нужно переместить второй fork в код, который работает только в исходном родителе. Вы можете просто перенести его после первого switch.

Причина, по которой вам нужно закрыть трубу FD, состоит в том, что труба на самом деле не закрыта, пока все процессы, открывающие ее, не закрывают ее. Если у дочернего процесса есть конец записи его трубы, он будет держать его от чтения EOF на трубе.

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

// function declarations 
void executeLs(int data_pipe[]); 
void executeSort(int data_pipe[]); 

int main(){ 

    int data_pipe[2]; // array storing the file descriptors 
    int childls_pid; // ls child process 
    int childSort_pid; // sort child process 
    int rc; // return vaue of the pipe 
    int child_status1; 
    int child_status2; 

    rc = pipe(data_pipe); 
    if(rc == -1){ 
     perror("pipe"); 
     exit(1); 
    } 

    childls_pid = fork(); 

    // Ls Child process 
    switch(childls_pid) { 
    case -1: 
     perror("fork childLs Error"); 
     exit(1); 
    case 0: 
     // inside of child process 
     executeLs(data_pipe); 
     exit(0); 
    default: 
     break; 
    } 

    childSort_pid = fork(); 

    // Sort child process 
    switch(childSort_pid) { 
    case -1: 
     perror("fork childSort Error"); 
     exit(1); 
    case 0: 
     executeSort(data_pipe); 
     exit(0); 
    default: 
     wait(&child_status2); 
    } 
    return 0; 
} 

void executeLs(int data_pipe[]){ 

    // Closes the read file descriptor 
    close(data_pipe[0]); 

    dup2(data_pipe[1], STDOUT_FILENO); 

    // confused as to why this is necessary 
    close(data_pipe[1]); 

    execlp("ls", "ls", "-1", NULL); 
} 

void executeSort(int data_pipe[]){ 

    // close the write file descriptor 
    close(data_pipe[1]); 

    dup2(data_pipe[0], STDIN_FILENO); 
    close(data_pipe[0]); 
    execlp("sort","sort", NULL); 
} 
+0

Ничего себе, спасибо миллион, вы многое прояснили для меня! Я просто изучаю все это сегодня. – Xavier

Смежные вопросы