标准c库函数与Linux下系统函数库 区别 (即带不带缓冲区的学习)

时间:2021-03-06 08:35:31

我们都知道,C语言在UNIX/Linux系统下有一套系统调用(系统函数),比如文件操作open()、close()、write()、read()等,而标准C语言的库函数中也有一套对文件的操作函数fopen()、fclose()、fwrite()、fread()等.。那么同样是对文件的操作函数,标C与UC有什么区别呢?是标C效率高还是UC效率高呢?今天就让我们来一探究竟。

程序作用:将0~999999这1000000个整型数据写入文件。

1、标准C实现大量数据写入文件:

/*文件名test1.c*/
#include<stdio.h>
#include<stdlib.h>

#define MAX 1000000

int main (void)
{
    FILE * fp = fopen("test1.txt","w");
    if(fp == NULL){
        perror("fopen test1.txt");
        exit(EXIT_FAILURE);
    }

    int i;
    for(i = 0; i < MAX; i++){
        fwrite(&i, sizeof(int), 1, fp);/*我们采用fwrite一个一个写入文件*/
    }

    fclose(fp);
    return 0;
}
/*gcc -o test1 test1.c编译*/

写入文件的效率测试结果:

标准c库函数与Linux下系统函数库   区别     (即带不带缓冲区的学习)

2、Linux系统函数实现大量数据写入文件:

/*文件名test2.c*/
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>

#define MAX 1000000

int main (void)
{
    int fd = open("test2.txt",O_RDWR|O_TRUNC|O_CREAT,0666);
    /*O_RDWR可读可写,O_CREAT没有则新建,O_TRUNC覆盖写入(原有内容小清空),O_APPEND追加写入(原有内容不清空)*/
    if(fd == -1){
        perror("open test2.txt");
        exit(EXIT_FAILURE);
    }

    int i;
    for(i = 0; i < MAX; i++){
        write(fd, &i, sizeof(int));
    }
    close(fd);
    return 0;
}
/*gcc -o test2 test2.c编译*/

写入效率测试结果: 

标准c库函数与Linux下系统函数库   区别     (即带不带缓冲区的学习)

我们发现系统函数的使用并没有使程序运行速率(写入速率)变快而是变慢了几十倍,而且在测试中,我们可以看见增加的时间基本都是在sys(系统层面)中增加的。这是因为,系统函数在用户层没有缓冲区,在内核层有缓冲区,但是缓冲区很小,所以大量数据在写入文件时,频繁刷新缓冲区降低了写入速率。所以系统函数(如write)需要加自定义缓冲区以提高速率,而标准C函数(如fwrite)不用自己设置缓冲区,如果系统函数用自定义缓冲区其效率比标C要好,不定义缓冲区则效率很低,但是缓冲区大小要合适,否则物极必反(即使有缓冲区,从缓冲区向文件中写也是一个一个写入的)。

3、Linux系统函数实现大量数据写入文件修改:

/*文件名test3.c*/
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>

#define MAX 1000000
#define BUF_SIZE 500
/*缓冲区大小,合适为宜,多少为合适需要自己测试,但是不同大小的缓冲区影响肯定是不同的*/
int main (void)
{
    int fd = open("test3.txt",O_RDWR|O_TRUNC|O_CREAT,0666);
    if(fd == -1){
        perror("open test3.txt");
        exit(EXIT_FAILURE);
    }

    int i;
    int buffer[BUF_SIZE] = {0};
    for(i = 0; i < MAX; i++){
        buffer[i%BUF_SIZE] = i;
        if(i%BUF_SIZE == BUF_SIZE-1)
            write(fd, buffer, sizeof(buffer));/*当缓冲区写满时向文件中写一次(刷新一次缓冲区)*/
    }

    close(fd);
    return 0;
}
/*gcc -o test3 test3.c编译*/

写入效率测试结果:

标准c库函数与Linux下系统函数库   区别     (即带不带缓冲区的学习)

加入自定义缓冲区后的测试发现,其效率比不加自定缓冲区要快100多倍,比标C写入速率也要快好几倍。如果缓冲区大小合适,其效率会提升更大。那么当我们将BUF_SZIE改为更大的值(BUF_SZIE=50000),重新编译之后,测试结果如下:

标准c库函数与Linux下系统函数库   区别     (即带不带缓冲区的学习)

该效率由提高了,所以选择一个合适的缓冲区尤为重要。