Почему результат отличается при использовании другого описателя файла? (системное программирование)

Я изучаю описатель файлов и понял, что если я использую функцию dup2(), результат будет другим.

Первый фрагмент ...

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;
}

... дает следующий результат:

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

Но второй фрагмент ...

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;
}

... производит следующий контент в dupout:

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

Почему результаты разнятся?

2
0
77
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

объяснять:

Буферы ввода-вывода бывают трех типов: full buffer, line buffer и no buffer.

Первый пример:

По умолчанию stdout - это line buffer, это означает, что когда буфер заполнен или когда встречается \n, буфер будет очищен.

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;
}

Выход :

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

Но когда мы изменим его на:

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;
}

Выход:

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

продолжить: изменить на:

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;
}

Выход:

i am highI am low
I am low
I am low

Второй пример:

По умолчанию file IO - это full buffer, это означает, что когда буфер заполнен, буфер будет очищен.

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;
}

Выход:

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

Но когда мы изменим его на:

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;
}

Выход:

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

          old

Из-за буфера ввода-вывода. Если вы добавите setvbuf(stdout, NULL, _IONBF, 0); перед printf, результат будет правильным. Строка означает, что буфер ввода-вывода не установлен.

Следующее - это все 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;
}

Есть ли у функции write () буфер ввода-вывода? и мне интересно, когда буфер ввода-вывода будет пуст в функции printf ().

whitehat 31.10.2018 14:41

@whitehat буфер ввода-вывода только для стандартного ввода-вывода, например printf, fputs и т. д. write, read - это системный вызов.

Yunbin Liu 31.10.2018 15:07

@whitehat Я добавил подробное объяснение.

Yunbin Liu 01.11.2018 09:12

Спасибо. это было действительно полезно для меня

whitehat 01.11.2018 12:06

Другие вопросы по теме