本文共 1934 字,大约阅读时间需要 6 分钟。
我们最近在学习Linux的文件描述符分配规则时,接触到了缓冲区这一概念。今天,我们将深入探讨这一关键机制的工作原理以及如何实现一个简单的FILE*接口。
缓冲区是操作系统用于临时存储数据的内存区域。它的主要目的是解决I/O操作效率低下的问题。想象一下,系统面对大量向文件输入输出的操作,如果每次都直接将数据送往文件,操作系统的负载会变得极大。而设置一个缓冲区,等到数据积累到一定量后才一次性将其传输到文件中,这样可以显著提升系统性能。
其实,缓冲区的核心作用就是提高效率。通过减少直接操作I/O的频率,缓冲区帮助系统避免了过多的I/O操作,对整体性能产生了积极影响。
##缓冲区的刷新机制
缓冲区的刷新方式主要有三种:
除此之外,还有一些特殊情况会触发缓冲区刷新:
fflush函数强制刷新缓冲区。让我带你看一个有趣的现象:
// C语言接口fprintf(stdout,"C->fprintf:hello My Love\n");printf("%s","C->printf:hello My Love\n");const char* s = "C->fputs:hello My Love\n";fputs(s,stdout);const char* s1 = "system call:hello My Love\n";write(1,s1,strlen(s1));fork(); // 创建子进程 当我们将输出重定向到log.txt时,发现C语言接口的输出被重复了两次,而系统调用的输出只被打印了一次。这是为什么呢?
这背后隐藏着一个重要的概念:C语言为我们提供了一个用户缓冲区。通常情况下,缓冲区的刷新方式是基于我们提供的这个缓冲区(用户缓冲区)来进行的。
在探讨缓冲区时,用户级和内核级缓冲区是两个需要区分的概念。
用户级缓冲区:
read、write)进行操作。内核缓冲区:
read、write等系统调用的数据传递。基于上述机制,我们可以尝试实现一个简单的FILE接口。FILE是C语言中用于表示文件或其他I/O设备的指针,通过它可以进行读写操作。
#include#include #include #include #include int mainOrDefault(int argc, char **argv) { int fd; struct Winsize ws; // 打开指定的设备文件 if (argc >= 2) { fd = open(*argv, O_RDWR | O_NDLCK); if (-1) { fprintf(stderr, "Could not open device %s\n", *argv); return -1; } } else { fd = 1; // 标准输出 } // 获取终端窗口大小 ws.size = sizeof(Winsize); ioctl(fd, TIOGWINSZ, &ws); while(1) { sleep(1); printf("Written: %d bytes\n", ws.write_pointer); } return 0;}
在本例中:
open系统调用打开指定设备文件或标准输出。ioctl函数获取终端窗口大小。通过这个过程,我们可以直观地看到用户缓冲区在I/O操作中的重要作用。
转载地址:http://ekzfk.baihongyu.com/