2014-12-09 4 views
0

Я пытаюсь понять, как работают трубы, и это довольно запутанно, когда я читал этот код в своем учебнике. В строкеЗакрытие трубы и дублирование трубы

dup(fd2[0]); close(fd2[0]); 

почему мы дублируя fd2[0], а затем закрыть его сразу после мы его дублировал?

#include <stdio.h> 
#include <time.h> 
#include <sys/types.h> 
#include <unistd.h> 

int main() { 
    struct timespec ts1, ts2; 
    pid_t newpid; 
    int fd1[2], fd2[2]; 
    char m0[] = "\nabout to fork....\n"; 
    char m1[] = "message from parent to child\n"; 
    char m2[] = "message from child to parent\n"; 
    char m3[] = "\ndone....\n"; 
    char rbuf1[256]; 
    char rbuf2[256]; 
    int cn1, cn2; 
    ts1.tv_sec=(time_t)1; 
    ts1.tv_nsec=(long)1; 
    ts2.tv_sec=(time_t)1; 
    ts2.tv_nsec=(long)1; 
    if ((pipe(fd1)==-1)) printf("error\n"); 
    if ((pipe(fd2)==-1)) printf("error\n"); 
    printf("fd1 %d %d fd2 %d %d\n", fd1[0], fd1[1], fd2[0], fd2[1]); 

    if ((newpid=fork()) ==-1) { 
    printf("failed to fork\n\n"); 
    return 0; 
    } 

    if (newpid > 0) { // parent *************** 
    close(fd1[1]); close(fd2[0]); // closing 4 and 5 
    dup(fd2[1]); close(fd2[1]); // taking 4 in place of 6 
    write(4, m1, sizeof(m1)); // parent_to_child messg 
    usleep(10000); 
    cn1=read(3, rbuf1, 256); 
    write(1, rbuf1, cn1); 
    } else { // child *************** 
    close(fd1[0]); close(fd2[1]); // closing 3 and 6 
    dup(fd2[0]); close(fd2[0]); // taking 3 in place of 5 
    write(4, m2, sizeof(m2)); // child_to_parent messg 
    usleep(10000); 
    cn2=read(3, rbuf2, 256); 
    write(1, rbuf2, cn2); 
    } 
    write(2, m3, sizeof(m3)); 
    return 0; 
} 
+3

Код, который у вас есть, кажется, не имеет никакого отношения к вашему вопросу. Я нигде не вижу «дура». – Sentry

+0

Извините, я забыл добавить вторую половину кода в свой вопрос – Learning

+0

, пожалуйста, отформатируйте код. –

ответ

1

Вы не показать нам свой код, однако, от man page из dup()

int dup(int oldfd); 

и

dup() uses the lowest-numbered unused descriptor for the new descriptor. 

Это ясно говорит, dup() возвращает новый дескриптор файла для oldfd , вам необходимо присвоить возвращаемое значение dup(), чтобы получить новый fd. Как только вы получите новый fd, вы можете закрыть старый fd и использовать вновь возвращенный дескриптор для доступа к файлу.

Еще раз подход, который обычно используется, чтобы закрыть известный файловый дескриптор и после этого вызова dup(), который присвоит недавно закрытой fd как новый fd. [Пример: STDIN_FILENO]

+0

Значит ли это, когда я назову close (fd), он закроет старый fd и никогда новый fd? – Learning

+0

@Удаление да, если вы поставляете старый 'fd' для' close() '. возвращаемое значение даст вам новый 'fd'. –

0

Обычная последовательность должна иметь другие close вызова перед dup вызовом, или присвоить результат dup и использовать его.

Первый вариант является наиболее распространенным, например, чтобы использовать трубу для чтения конца как новый STDIN_FILENO вы можете сделать

close(STDIN_FILENO); // Close the current standard input descriptor 
dup(pipefds[0]);  // Duplicate the pipe read-end, which will become our new standard input 
close(pipefds[0);  // Close the old pipe descriptor, to save descriptor resources 

Это будет работать, потому что dup выберет низкий доступного дескриптора, который после первый вызов close будет STDIN_FILENNO (дескриптор 0).

И dup делает именно то, что он souds как он дублирует дескриптор, поэтому после вызова dup вы будете иметь два дескриптора, ссылающийся на тот же «файл», и может свободно закрыть один из них.

Предлагаю вам прочитать the dup(2) manual page.