使用不同的文件描述符时,为什么结果不同? (系统编程)

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

我正在研究文件描述符并意识到如果我使用 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

为什么结果不同?

解释:

IO缓冲区有full bufferline bufferno buffer三种类型。

第一个例子:

默认,stdoutline buffer,意思是当buffer满了或者遇到\n,buffer会刷新。

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 IOfull 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

由于 IO 缓冲区。如果在 printf 之前添加 setvbuf(stdout, NULL, _IONBF, 0);,结果是正确的。该行表示不设置 IO 缓冲区。

以下全部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;
}