linux高速缓冲管理中的哈希队列、空闲链表以及延迟写和提前读策略

来源:互联网 发布:网络app销售彩票合法吗 编辑:程序博客网 时间:2024/05/21 17:39

       数据缓冲区高速缓冲在内核启动初始化是被划分成1024、2048块大小的双向链表形式而被内核管理的。同时还有一组哈希队列使得内核可以快速找到所需数据的缓冲块是否在高速缓冲中。一个哑节点free_list标记了空闲链表的头,虽然名字是空闲链表,并不代表链表中的节点都是空闲没有有效数据的节点。当内核需要读取磁盘数据时,首先通过哈希队列查找该磁盘块是否已经在缓冲区中,若在可直接返回,否则从空闲链表头部开始遍历,找到空闲的节点,然后将此节点从空闲链表中删除,并且将此节点插入到哈希队列对应桶的头部和空闲链表的尾部。

        而当内核释放一个缓冲区时,此时需要将缓冲区对应的缓冲头从哈希队列和空闲链表中删除,对哈希队列来说直接移走对应的节点即可,而对于空闲链表而言,删除此节点后还需要将此节点插入到链表的头部,也就是说在分配时插入到链表尾,删除时转移链表头部,这一设计完全符合最近最少使用原则,链表的头部是最近使用的最少的节点。

       提前读调用breada算法,当一个进程顺序地读一个文件时,文件子系统根据空间局部性原理可能会预期到对另一个磁盘块的需要,因而异步地请求第二个I/O操作,这样一旦需要用到这部分数据时,主存中已经保存了所需数据,这样可以改善性能。当第二块的I/O操作完成时,磁盘控制器向系统发中断,中断处理程序识别出该I/O是异步的,就使用算法brelse释放掉该缓冲区。

        延迟写意味着内核将缓存区做适当的标记,然后将缓冲区头移出哈希队列和空闲队列,并且插入空闲队列的头部,符合内核最近最少使用原则,当下一个进程把该缓冲区分配给另一个磁盘的数据块时,进程检查到标记后,会把该缓冲区的数据异步写到磁盘上。随后,磁盘控制器中断系统,并使用算法brelse释放该缓冲区。  

        提前读和延迟写磁盘块都是异步I/O操作,内核需要从中断处理程序中调用brelse释放该缓冲区。若是同步I/O,内核失去对缓冲区的控制,则当等待的睡眠进程在操作完成,被唤醒时自己释放缓冲区。

        高速缓冲的使用使得用户进程在调用系统调用read和write进行磁盘读写操作时,需要一次额外的数据拷贝过程。调用write时,会发生系统态的切换,内核把用户进程的数据数据首先拷贝到内核的缓冲区,然后内核再把数据拷贝到磁盘上;调用read时,同样会切换到核心态,内核把磁盘数据首先拷贝到内核高速缓冲区,然后再把数据拷贝到用户进程中。当数据量很大时,过多的拷贝使系统性能下降,但是高速缓冲的益处还是远远超过这个缺点的。


0 0