一次重定向引起的异步IO

最近在用dup/dup2做IO重定向的时候,由于缓冲区的问题出现了一次异步IO,导致无法正常输出正确的结果。
先贴出代码:

/* 
 * 从文件里面读出1000个随机数,进行排序,再写到另一个文件中(使用dup/dup2)
 *  
 */

#include 
#include 
#include 
#include 
#include 
#include 
#include 

typedef char STR[32];

void quick(int *a, int i, int j);

int main(void)
{
    int fd, fd2;
    int save_fd, save_fd2;
    int i;

    if ((fd = open("data.txt", O_RDONLY)) < 0) {
        perror("open data.txt");
        exit(1);
    }

    if ((fd2 = open("sort_w.txt", O_RDWR|O_CREAT, 0644)) < 0) {
        perror("open sort_w.txt");
        exit(1);
    }

    save_fd = dup(STDIN_FILENO);
    save_fd2 = dup(STDOUT_FILENO);

    dup2(fd, STDIN_FILENO);
    dup2(fd2, STDOUT_FILENO);
 close(fd);
    close(fd2);

    STR *st = malloc(sizeof(STR) * 1000);
    memset(st, 0, sizeof(STR)*1000);

    int buf[1000] = {0};

    for (i = 0; i < 1000; i++)
        scanf("%s", st[i]);

    for (i = 0; i < 1000; i++)
        buf[i] = atoi(st[i]);

    quick(buf, 0, 999);

    char tmp[128] ={0};
    for (i = 0; i < 1000; i++) {
        memset(tmp, 0, 128);
        sprintf(tmp, "%d\n", buf[i]);

        /* error */
    //  printf("%s", tmp);             // apue 标准输出关联到一个文件的时候,变成全缓冲的。
        write(STDOUT_FILENO, tmp, strlen(tmp));
    }

    dup2(save_fd, STDIN_FILENO);
    dup2(save_fd2, STDOUT_FILENO);
    close(save_fd);
    close(save_fd2);

    free(st);
    return 0;
}


void quick(int *a, int i, int j)
{
    int m, n, temp;
    int k;
    m = i;
    n = j;
    k = a[(i + j) / 2]; /*选取的参照*/
    do {
        while (a[m]>k&&m/* 从左到右找比k大的元素*/
        while (a[n]i) n--; /* 从右到左找比k小的元素*/
        if (m <= n) { /*若找到且满足条件,则交换*/
            temp = a[m];
            a[m] = a[n];
            a[n] = temp;
            m++;
            n--;
        }
    } while (m <= n);
    if (m/*运用递归*/
    if (n>i) quick(a, i, n);
}

问题出在注释的printf那一行,用write一切正常运行,用printf的时候出现如下结果。

forker@L:homework$ ./a.out 
5
30094
29970
29882
29858
29769
29733
29690
29679
29673
29573
29434
29353
29309
29308
29269
29257
28751
28420
...
173

再来看看排序后生成的文件中:

673 30641
674 30637
675 30629
676 30628
677 30451
678 30401
679 30373
680 30364
681 30320
682 30199
683 3013

对比可以看出来,用printf在文件中写入了683行,并且没有写完,应该是30135,之后的数据打印到终端上。
后来,查阅资料Apue中说:
标准IO在关联到终端的时候是行缓冲的,在重将标准IO重定向到一个文件之后,这个时候就变成了全缓冲的。可以看到在第一次缓冲区满了的时候,IO例程进行刷新缓冲区,于是写入了文件。之后再将剩下的数据写到缓冲区,这个时候缓冲区并没有满,也就没有立刻刷新。接下来,标准IO又关联到终端,在进程终止之前,开始刷新缓冲区,于是剩下的数据被打印到终端上。
一次重定向引起的异步IO_第1张图片

你可能感兴趣的:(Linux网络编程,异步io,缓冲区)