Search code examples
csystems-programmingdup2

when using different file descripter, why is the result different? (system programming)


I am studying about file descripter and realized that if I use dup2() function, the result will be different.

The first snippet ...

int main(void){
    char buf1[BUFSIZ] = "I am low\n";

    printf("i am high\n");
    write(1, buf1, strlen(buf1));
    write(1, buf1, strlen(buf1));
    write(1, buf1, strlen(buf1));

    return 0;
}

... produces the following result:

i am high
i am low 
i am low
i am low

But the second snippet ...

int main(void){
    int fd = open("dupout",O_CREAT | O_WRONLY, 0655);
    char buf1[BUFSIZ] = "I am low\n";
    dup2(fd, 1);

    printf("i am high\n");
    write(1, buf1, strlen(buf1));
    write(1, buf1, strlen(buf1));
    write(1, buf1, strlen(buf1));
    close(fd);

    return 0;
}

... produces the following content in dupout:

i am low 
i am low
i am low
i am high

Why do the results differ?


Solution

  • explain:

    IO buffer have three types full buffer, line buffer and no buffer.

    First example:

    Default, stdout is line buffer, means when the buffer is fulled or when meet \n, buffer will flush.

    int main(void){
        char buf1[BUFSIZ] = "I am low\n";
        printf("i am high\n");
        write(1, buf1, strlen(buf1));
        write(1, buf1, strlen(buf1));
        write(1, buf1, strlen(buf1));
        return 0;
    }
    

    Output :

    i am high
    I am low
    I am low
    I am low
    

    But when we change it to :

    int main(void){
        char buf1[BUFSIZ] = "I am low\n";
        printf("i am high");   // no '\n'
        write(1, buf1, strlen(buf1));
        write(1, buf1, strlen(buf1));
        write(1, buf1, strlen(buf1));
        return 0;
    }
    

    Output:

    I am low
    I am low
    I am low
    i am high
    

    continue : change to :

    int main(void){
        char buf1[BUFSIZ] = "I am low\n";
        printf("i am high"); // no '\n'
        fflush(stdout);// flush
        write(1, buf1, strlen(buf1));
        write(1, buf1, strlen(buf1));
        write(1, buf1, strlen(buf1));
        return 0;
    }
    

    Output:

    i am highI am low
    I am low
    I am low
    

    Second example:

    Default, file IO is full buffer, means when the buffer is fulled, buffer will flush.

    int main(void){
        int fd = open("dupout",O_CREAT | O_WRONLY, 0655);
        char buf1[BUFSIZ] = "I am low\n";
        dup2(fd, 1);
    
        printf("i am high\n");
        write(1, buf1, strlen(buf1));
        write(1, buf1, strlen(buf1));
        write(1, buf1, strlen(buf1));
        close(fd);
    
        return 0;
    }
    

    Output:

    I am low
    I am low
    I am low
    i am high
    

    But when we change it to :

    int main(void){
        int fd = open("dupout",O_CREAT | O_WRONLY, 0655);
        char buf1[BUFSIZ] = "I am low\n";
        dup2(fd, 1);
    
        printf("i am high\n");
        fflush(stdout);
        write(1, buf1, strlen(buf1));
        write(1, buf1, strlen(buf1));
        write(1, buf1, strlen(buf1));
        close(fd);
    
        return 0;
    }
    

    Output:

    i am high
    I am low
    I am low
    I am low
    

              old
    

    Because of IO buffer. If you add setvbuf(stdout, NULL, _IONBF, 0); before printf, result is right. The line means set no IO buffer.

    The following is all code:

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <string.h>
    #include <unistd.h>
    
    int main(void){
        int fd = open("dupout",O_CREAT | O_WRONLY, 0655);
        char buf1[BUFSIZ] = "I am low\n";
        dup2(fd, 1);
    
        setvbuf(stdout, NULL, _IONBF, 0);
        printf("i am high\n");
        write(1, buf1, strlen(buf1));
        write(1, buf1, strlen(buf1));
        write(1, buf1, strlen(buf1));
        close(fd);
    
        return 0;
    }