已知的fgets libc函数实现在内部使用了fgetc()
,如何使用具有更大缓冲区或其他方法的read()
来加速该函数?
例如,我阅读了/proc/pid/maps
文件以搜索一些字符串。该文件的格式是已知的,当前我在fgets
的链接中使用read(fd, &c, 1);
实现,而不是getc
。我认为从文件中读取单个字节比读取200个字节要慢。所以我想修改函数以从文件中读取N个字节,然后找到一个换行符。我认为替换1字节读取可以以某种方式加快功能。
答案 0 :(得分:6)
您完全误解了标准I / O功能。甚至fgetc
也被缓冲。使用read
测试实际strace
呼叫的发出。在我的计算机上,阅读/proc/1/maps
:
read(3, "5634f9cf6000-5634f9e44000 r-xp 0"..., 1024) = 1024
read(3, " /lib/x86_64-l"..., 1024) = 1024
read(3, " /lib/x86_64-linux-g"..., 1024) = 1024
read(3, " /lib/x86_64-l"..., 1024) = 1024
read(3, ".0.0\n7feb2b2dc000-7feb2b4db000 -"..., 1024) = 1024
read(3, "0-7feb2b8e7000 r--p 00002000 fd:"..., 1024) = 1024
read(3, "00 rw-p 0001a000 fd:00 145004 "..., 1024) = 1024
read(3, "ux-gnu/liblzma.so.5.2.2\n7feb2c1b"..., 1024) = 1024
read(3, "6_64-linux-gnu/libgcrypt.so.20.2"..., 1024) = 1024
read(3, "000 fd:00 135558 "..., 1024) = 1024
read(3, "--p 0000e000 fd:00 136910 "..., 1024) = 1024
read(3, "001e000 fd:00 131385 "..., 1024) = 1024
read(3, "1.1.0\n7feb2da14000-7feb2da15000 "..., 1024) = 1024
read(3, "0 rw-p 00000000 00:00 0 \n7feb2de"..., 1024) = 1024
read(3, "-237.so\n7feb2e492000-7feb2e69100"..., 1024) = 1024
read(3, " \n7feb2ed15000-7feb2ed36000 rw-p"..., 1024) = 637
read(3, "", 1024) = 0
read
调用尝试读取1024
个字节,而不仅仅是一个字节。
程序是
#include <stdio.h>
int main(void) {
FILE *f = fopen("/proc/1/maps", "r");
while (1) {
char buf[2048];
if (! fgets(buf, 2048, f)) {
break;
}
}
}
如果1024个字节不足以容纳您,则可以使用setvbuf(3)来更改基础缓冲区的大小!
答案 1 :(得分:1)
给您一个提示(但应修改为一次读取多个字节)
...我们拥有函数fgetsR()
,它使用函数read()
而不是fgetc()
。在下面的代码中,有两个功能:
fgets0()
是K&R fgets()
函数fgetsR()
是一个fgets()
函数,它使用read()
而不是fgetc()
。fgetsR函数主要用于读取文件(在命令行中指定)并显示其内容。
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <malloc.h>
char * fgets0(char *dst, int max, FILE *fp);
char * fgetsR(char *dst, int max, FILE *fp);
char * fgets0(char *dst, int max, FILE *fp)
{
int c;
char *p;
/* get max bytes or upto a newline */
for (p = dst, max--; max > 0; max--) {
if ((c = fgetc (fp)) == EOF)
break;
*p++ = c;
if (c == '\n')
break;
}
*p = 0;
if (p == dst || c == EOF)
return NULL;
return (p);
}
char * fgetsR(char *dst, int max, FILE *fp)
{
int c;
char *p,x;
/* get max bytes or upto a newline */
for (p = dst, max--; max > 0; max--) {
if ((c = read(fileno(fp),&x,1)) == EOF || !c)
break;
*p++ = x;
if (x == '\n')
break;
}
*p = 0;
if (p == dst || c == EOF || !c)
return NULL;
return (p);
}
int main(int argc, char *argv[])
{
FILE * f = NULL;
char buffer[1024];
if (argc<2) {
puts("You have to specify a file to read!");
return 1;
}
f=fopen(argv[1],"r");
while(fgetsR(buffer,sizeof(buffer),f)) {
printf("%02X %s",*buffer,buffer);
}
fclose(f);
return 0;
}
我不认为解决方案会更好,更快。上面的main()
需要一些解决方法来控制发生错误时的流程。