Linux系统调用一定比库函数效率高吗——预读入缓输出机制
2022-02-01 # 学习笔记 # Linux

Linux系统调用一定比库函数效率高吗——预读入缓输出机制

Q:如果一个只读一个字节实现文件拷贝,使用系统函数(read、write)效率高,还是使用对应的标库函数(fgetc、fputc)效率高呢?

实际代码测试

采用系统函数read,write

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

#define N 1

int main(int argc, char* argv[])
{
char buf[N];
int fd_in = open(argv[1], O_RDONLY);
int fd_out = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0775);

if (fd_in == -1 || fd_out == -1)
{
perror("open error");
exit(1);
}

int n;

while ((n = read(fd_in, buf, N)) != 0)
{
if (n < 0)
{
perror("read error");
exit(1);
}
write(fd_out, buf, n);
}


close(fd_in);
close(fd_out);
}

采用库函数fgetc和fputc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{
FILE* fp_in, * fp_out;
int n;

fp_in = fopen(argv[1], "r");
fp_out = fopen(argv[2], "w");
if (fp_in == NULL || fp_out == NULL)
{
perror("fopen error");
exit(1);
}

while ((n = fgetc(fp_in)) != EOF)
{
fputc(n, fp_out);
}

fclose(fp_in);
fclose(fp_out);
}

实际运行结果

第一次为系统函数,第二次为库函数结果,速度有很明显的差别

原因分析

采用库函数时,虽然我们给定的缓冲区只有1个字符的大小。但fputc和fgetc的库函数在调用时会自动创建大小为4K的缓冲区,只有当读满后,才会写入核心中的缓冲区,切换访问权级的次数较少。

而当我们仅采用系统调用的时候,没有了库函数提供的缓冲区,因此只能一个字符一个字符的向核心中的缓冲区内写入,每写入一次都要发生权级切换,性能开销极大。

因此可以通过适当加大缓冲区(4K),或者是直接采用库函数的方式来提高性能