在计算机虚拟内存的概念中,页、内存页或者虚拟页是指内存中的一段固定长度的块,这个内存块在物理地址和虚拟内存地址上都是连续的。一个页通常是以下操作的最小单元:
- 操作系统为程序分配空间;
- 内存和外存传输,比如说硬盘。
一般来说,系统中页的大小是规定好的,比如说4096B,也即4KB。
cache page size就是内存页的最小分配单元,默认8KB,应用于R/W cache。如果I/O < 8KB,那么一个page可能会服务多个I/O,从而优化了cache page的使用。
- 如果应用环境是Mixed I/O,建议不要更改。
- 如果应用环境主要是【顺序,大I/O】,将page size 改成16KB能增加性能
- 如果应用环境主要是【随机,小I/O】,比如OLTP 4KB,那么改成4KB能优化cache page的使用率。
总的来说,是否要改page size,需要在方案设计期间就确定应用程序的主要I/O大小,进而匹配存储的cache page size,实现优化。如果不确定,8KB是一个最佳实践值。
在内存页中,有一种叫专门用途的页面叫“缓冲区页”。专门用来放块缓冲区。而每个块缓存区由两部分组成,缓冲区首部(用数据结构buffer_head表示)及真正的缓冲区内容(即所存储的数据,这些数据就放在刚刚说到的缓冲区页中)。在缓冲区首部中,有一个指向数据的指针和一个缓冲区长度的字段。当一个块被调入到内存中,它要被存储在一个缓冲区中。每个缓冲区与一个块对应,它相当于磁盘块在内存中的表示。而文件在内存中由file结构体表示,而磁盘块在内存中是由缓冲区来进行表示的。由于内核处理块时需要一些信息,如块属于哪个设备与块对应于哪个缓冲区。所以每个缓冲区都有一个缓冲区描述符,称为buffer_head. 它包含了内核操作缓冲区所需要的全部信息。
块=缓冲区=1/4 缓冲区页=1/4 Page。
struct buffer_head {
unsigned long b_state; /* buffer state bitmap (see above) 缓冲区的状态标志*/
/*circular list of page's buffers 页面中缓冲区(一般一个页面会有多个块组成,一个页面中的块是以一 个循环链表组成在一起的,该字段指向下一个缓冲区首部的地址。)*/
struct buffer_head *b_this_page;
/* the page this bh is mapped to *存储缓冲区的页面/(指向拥有该块的页面的页面描述符)*/
struct page *b_page;
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_private; /* reserved for b_end_io *I/O完成的方法*/
struct list_head b_assoc_buffers; /* associated with another mapping */
/*mapping this buffer is associated with *缓冲区对应的映射,即address_space*/
struct address_space *b_assoc_map;
atomic_t b_count; /*users using this buffer_head *表示缓冲区的使用计数*/
}
buffer_head中有两个字段表示块的磁盘地址:
b_bdev 表示包含该块的块设备(通常是磁盘或者分区)
b_blocknr存放逻辑块号,也就是块在磁盘或分区中的编号
b_data 字段表示块缓冲区数据在缓冲区页中的位置。
b_state存放缓冲区的状态,例如BH_uptodate(缓冲区包含有效数据时候被置位),Bh_Dirty(缓冲区脏就置位),BH_New(如果相应的块刚被分配而还没被访问过就置位)。
只要内核必须单独访问一个块,就要涉及存放块缓冲区中的缓冲区页,并检查相应的buffer_head
一个应用实例:如果虚拟文件系统要读1024个字节的inode 块,内核并不是只分配一个单独的缓冲区,而是必须分配一整个页,从而存放4个缓冲区(假设页大小4k),这些缓冲区将存放块设备上相邻的四块数据。其中包含所有的inode块
他们之间的关系如下:(假定一个块是1K ,一个页是4K )
在一个缓冲页内所有块缓冲区大小必须相同,因此,在80X86体系结构上,根据块的小大,一个缓冲区页(page)可以包括1~8个缓冲区。如果一个页作为缓冲区页使用,那么与它的块缓冲区相关的所有缓冲区首部都被收集在一个单向循环链表中。page的private字段指向页中第一个块的buffer_head,每个buffer_head存放在b_this_page字段中,该字段是指向链表中的下一个缓冲区首部的指针。此外,每个buffer_head还把page的地址存放在b_page字段中,整个图如上所示。
mmap 系统调用
mmap系统调用是将硬盘文件映射到用内存中,其实就是将page cache中的页直接映射到用户进程地址空间中,从而进程可以直接访问自身地址空间的虚拟地址来访问page cache中的页,从而省去了内核空间到用户空间的copy。
查看系统参数
tune2fs命令允许系统管理员调整“ext2/ext3”文件系统中的可该参数。
需要注意到系统可能有多个盘多个文件系统,可通过df命令查看
数值单位是字节
$sudo /sbin/tune2fs -l /dev/sda1|grep "Block size"
$getconf PAGESIZE
文件操作数据流
如图: