开始介绍之前先打一波广告,推广一下我的B站主页,里面会有一些音乐软件才能听的歌曲,以后有时间还可以搞点其他的,现在视频数量较少,音乐当然也是我从youtube搬运来的,没错我就是油管搬运工。我的主页链接如下:欢迎各位支持关注:https://space.bilibili.com/313975164/
分割线---------------------------------------------------------------------
在对文件描述符的数据进行处理的时候,因为要先把数据读取到缓冲区中,再从缓冲区读取出来进行处理,所以缓冲区的大小影响着我们对数据的读取,下面是它的实现原理
首先我们再内存中创建一个缓冲区,缓冲区的大小为1024字节,同时定义两个指针,一个读指针,表示的是可以读取的数据的开始位置,一个写指针表示的是可以写入数据的起始位置,开始的时候两根指针都是指向内存开始的地方,如下图所示:

当有文件描述符监听到事件的发生的时候,比如发生的是读事件,那么就要把文件描述符监听到的事件读取到缓冲区,加入读取的字节的长度为len,那么写指针的位置就要发生变化,如下图所示:

因为缓冲区的大小是固定的大小,而我们通常是一次性将数据全部读取到缓冲区,那么就有可能装不下数据,所以需要临时创建一个缓冲区来缓解,将存不下的放到临时缓冲区,这样就可以一次性将所有的数据读入,这里利用临时缓冲区的技术是一个分散读的技术,即将数据分散读取到内存中不同的位置,分散读的话需要定义一个结构体数组如下所示:
struct iovec{void * iov_base; //表示的是缓冲的地址size_t iov_len; //表示的是缓冲的大小}
生成的结构体数组如下图所示:

如上图所示,当固定的缓冲区想要继续写数据的时候,发现剩余的位置不够写的时候那么就可以先把数据写入到临时缓冲中,再将临时数组的数据读取到固定缓冲区来处理,比如上图所示读指针的位置表示前面的数据已经被读取了,写指针的位置表示如果有数据那么要从这里开始写。那么如何实现动态扩容的呢?
因为数据的处理只能放到固定大小的缓冲中进行处理,即上述的1024字节的缓冲中,那么如果很多数据都读取到这块区域的话,那么肯定是放不下的,我们就可以利用一个临时的缓冲区,把放不下的数据先放到临时的缓冲的位置,等到1024字节大小的内存有剩余的空间的时候我再将临时缓冲区的数据放入到1024的位置进行处理,那么何时1024缓冲中有空闲的位置呢?原理及实现如下图所示:

可以从上图看出,如果我们想要写入数据,那么此时可以利用的空间就是最前面的部分和最后面的部分的位置,但是写入数据一定要连续,所以唯一的办法就是将中间的数据移动到最前面,这样就可以将空闲的区域连接在一起,方便后面的写数据。具体的实现就是将读指针到写指针之间的数据复制到最前面,再更改读指针和写指针的位置,这就是利用一个缓冲实现自动增长的原理,关键部分的代码如下:
这是往缓冲中写入数据:

往缓冲读取数据

动态扩容的实现

以上就是缓冲的自动增长的实现原理,不得不感叹一句c++的强大,写完我都能感受到指针在内存中移动的感觉,这是其他语言比不了的,虽然不能像java,php,python那样学完立马能写很多的实用的软件,动不动就是商城、秒杀系统,但是c++是这些语言的基础呀,底层实现都是靠的c++,总之,c++是世界上最好的语言(不接受反驳,哈哈哈)。




