1、页缓存、块缓存的结构P762P766 Embedded System Lab 2014页缓存、块缓存的结构Linux运用一个功能广泛的缓冲和缓存框架来提高系统的速度 内核为块设备提供了两种通用的缓存方案:1)页缓存,针对以页为单位的所有操作,并考虑了特定体系结构上的页长度。一个主要的例子是内存映射技术。因为其他类型的文件访问也是基于内核中的这一技术实现的。所以页缓存实际上负责了块设备的大部分缓存工作。2)块缓存,以块为操作单位。在进行I/O操作时,存取的单位是设备的各个块,而不是整个内存页。尽管页长度对所有文件系统都是相同的,但块长度取决于特定的文件系统或其设置。因而,块缓存必须能够处理不同长
2、度的块。页缓存的结构 机制:若在缓存命中,这可以快速操作;否者从底层块设备中读取所需的页,页被读入内存后,页将被插入缓存中,然后进行后续操作。内核与缓存交互:在不同位置加入flags linux采用基数树来管理页缓存中包含的页页缓存的结构顶点数据结构struct radix_tree_root unsigned intheight;gfp_tgfp_mask;/构建树的数据结构实例的内存域分配信息struct radix_tree_node*rnode;/指向下一个节点;页缓存的结构struct radix_tree_node unsigned intheight;/*Height from
3、the bottom*/unsigned intcount;/数组中已经占用的数目struct rcu_head rcu_head;/用于RCU机制对基数树进行无锁查询void *slotsRADIX_TREE_MAP_SIZE;/指向其他结点或元素 unsigned long tagsRADIX_TREE_MAX_TAGSRADIX_TREE_TAG_LONGS;/tag标志,RCU机制:read-copy-update,第五章P284内核内核radix-tree.c页缓存的结构脏数据:定义:页内容与后备存储器中的数据不同机制:某个节点标记成脏数据,其父节点也会标记,往上类推;内核从上往下判
4、断,不用遍历所有的,加速回写:几个内核守护进程在后台运行,称为pdflush,两种运行模式:周期性激活,不考虑页缓存当前情况,扫描缓存中的页,将超出一定时间没有与底层块设备同步的页写回。如果缓存中修改的项短时间内被修改很多,则激活pdflush 系统调用,用户或程序通知内核写回所有未同步数据页缓存的结构 节省时间:修改文件或其他按页缓存的对象时,只会修改页的一部分,而非全部。内存将缓存中的页划分为较小的单位,成为缓冲区,同步缓冲区节省时间。页缓存的结构 “地址空间地址空间”抽象抽象:内层中的页与特定的块设备关联 获得缓存页的列表获得缓存页的列表:每个地址空间都有一个宿主,一般为一个文件的ino
5、de,因为现有的inode都关联到超级块,所以内核只要扫描所有超级块并跟随相关的inode,就可以获得缓存页的列表块缓存的结构 来自于底层块设备的块缓存在内存的缓冲区中,可以加速读写操作。与内存页相比,块不仅比较小(大多数情况下),而且长度可变的,依赖于使用的块设备(或文件系统)缓存主要是页:随着日渐倾向于使用基于页操作实现的通用文件存取方法,块缓存作为中枢系统缓存的重要性已经逐渐失去。主要的缓存任务现在由页缓存承担。另外,基于块的I/O的标准数据结构,现在已经不再是缓冲区,而是struct bio结构。缓冲区用作小型的数据传输,一般设计的数据量是与块长度可比拟的。文件系统在处理元数据时,通常
6、会使用此类方法。而裸数据的传输则按页进行,而缓冲区的实现也基于也缓存。块缓存的结构块缓存在结构上由两个部分组成:1)缓冲头(buffer head)包含了与缓冲区状态相关的所有管理数据,包括快号、块长度、访问计数器等。这些数据不是直接存储在缓冲头之后,而是存储在物理内存的一个独立区域中,由缓冲头结构中的一个对应的指针表示。2)有用数据保存在专门分配的页中,这些页也可能同时存在于页缓存中。块缓存的结构struct buffer_head unsigned long b_state;/*buffer state bitmap(see above)后面数据结构*/struct buffer_head
7、*b_this_page;/*circular list of pages buffers */struct page*b_page;/*the page this bh is mapped to*/sector_t b_blocknr;/*start block number*/size_t b_size;/*size of mapping*/char*b_data;/*pointer to data within the page*/struct block_device*b_bdev;bh_end_io_t*b_end_io;/*I/O completion*/void*b_privat
8、e;/*reserved for b_end_io*/struct list_head b_assoc_buffers;/*associated with another mapping*/struct address_space*b_assoc_map;/*mapping this buffer is associated with*/atomic_t b_count;/*users using this buffer_head*/;/在buffer_head.h中enum bh_state_bits BH_Uptodate,/*Contains valid data*/BH_Dirty,/
9、*Is dirty*/BH_Lock,/*Is locked*/BH_Req,/*Has been submitted for I/O*/BH_Uptodate_Lock,/*Used by the first bh in a page,to serialise *IO completion of other buffers in the page */BH_Mapped,/*Has a disk mapping*/BH_New,/*Disk mapping was newly created by get_block*/BH_Async_Read,/*Is under end_buffer_
10、async_read I/O*/BH_Async_Write,/*Is under end_buffer_async_write I/O*/BH_Delay,/*Buffer is not yet allocated on disk*/BH_Boundary,/*Block is followed by a discontiguity*/BH_Write_EIO,/*I/O error on write*/BH_Ordered,/*ordered write*/BH_Eopnotsupp,/*operation not supported(barrier)*/BH_Unwritten,/*Bu
11、ffer is allocated on disk but not written*/BH_PrivateStart,/*not a state bit,but the first bit available*for private allocation by other entities*/;块缓存的结构 alloc_buffer_head生成一个新的缓冲头 free_buffer_head销毁一个显存的缓冲头。cteate_empty_buffers函数关联page和buffer_head结构之间的关联 block_read_full_page从缓冲区中读取整页 block_wirte_f
12、ull_page函数将整页写入到缓冲区块缓存的结构每页可以保存的最大缓冲区个数:#define MAX_BUF_PER_PAGE(PAGE_CACHE_SIZE/512)/每个缓冲区512个字节如果缓冲区在页缓存上,则数据共享,不需要显示同步;但如果访问块设备时使用的是块,读取文件系统的超级块,就是一个实例,该块缓存的运作独立于页缓存。块缓存的结构缓冲头管理:长度恒定的数组,LRU方式管理(最近最少使用)当缓冲头从数组中掉出时,内核会将相关的缓冲区删除,释放内存。free-m:查看内存情况,单位为MB。total内存总数used已经使用的内存数(我的程序使用内存数量+系统缓存使用的内数量)fr
13、ee空闲的物理内存数(是真正的空闲,未被任何程序占用)shared多个进程共享的内存总额buffers磁盘缓存(BufferCache)的大小(可提高系统I/O调用的性能)cached磁盘缓存(PageCache)的大小(可提高系统I/O调用的性能)-buffers/cache表示已被我们的程序使用的内存数,计算方法:used-buffers-cached+buffers/cache表示还可已被我使用的内存数,计算方法:free+buffers+cached操作系统目前可用内存总量=free+buffers+cached,上图是1155M调整/proc/sys/vm/drop_caches来释
14、放内存使用:echo 1 /proc/sys/vm/drop_caches echo 2 /proc/sys/vm/drop_caches echo 3 /proc/sys/vm/drop_caches有关/proc/sys/vm/drop_caches的用法在下面进行了说明:/proc/sys/vm/drop_caches(since Linux 2.6.16)Writing to this the kernel to drop clean caches,dentries and inodes from memory,causing that memory to become free.To
15、 free pagecache,use echo 1 /proc/sys/vm/drop_caches;to free dentries and inodes,use echo 2 /proc/sys/vm/drop_caches;to free pagecache,dentries and inodes,use echo 3 /proc/sys/vm/drop_caches.Because this is a non-destructive operation and dirty objects are not freeable,the user should run sync first Sync:sync 命令将所有未写的系统缓冲区写到磁盘中参考页缓存:块缓存:实践:“Stay Hungry,Stay Foolish.”by Steve Jobs Thanks