- 论坛徽章:
- 0
|
我这里只有2.4.32,和你的2.4.0看来不一样,我这里是这样的。
struct file_operations def_blk_fops = {
open: blkdev_open,
release: blkdev_close,
llseek: block_llseek,
read: generic_file_read,
write: generic_file_write,
mmap: generic_file_mmap,
fsync: block_fsync,
ioctl: blkdev_ioctl,
};
而且普通文件和块设备文件的inode->i_mapping->a_ops->readpage分别为
static int ext2_readpage(struct file *file, struct page *page)
{
return block_read_full_page(page,ext2_get_block);
}
static int blkdev_readpage(struct file * file, struct page * page)
{
return block_read_full_page(page, blkdev_get_block);
}
区别只在于ext2_get_block和blkdev_get_block
这两个都是个函数,主要的功能就是对于给定的(inode, 文件的逻辑块号),转换为(设备号,磁盘的物理块号)。我们暂时假定磁盘没有分区,没有引导块,buffer_head->block就是物理块号。
对于blkdev_readpage,它的参数实际只使用了 struct page * page。
调用时,这个page已经设置了正确的(块设备文件inode->i_mapping , index),加入了hash,lru,address space->clean,既已经加入了页缓存。
而block_read_full_page只保证的是:page有与其相关的8个buffer_head(假设一页8块),还没有buffer_head就分配,而且这8个buffer_head->b_this_page要正确的设置;
但是并不保证这8个buffer_head链入了块缓存的hash表,不会把他们加入块缓存。既这8个buffer_head所对应的页只存在于页缓存中。
但是,如果这个页是个读块设备文件得来的页,虽然目前它只在于页缓存,但是变化发生在读取目标块的时候, getblk()------->grow_buffers()函数中。
一旦搜索块缓存没找到目标块,那么就会grow_buffers,而grow_buffers调用grow_dev_page,这个grow_dev_page捣鬼,它把块号换算成相应页号,按照 (块设备的inode->i_mapping, 块号>>3)搜索了页缓存,如果在页缓存中找到了目标页,那么就把目标页的8个buffer_head加入了块缓存的hash表,既把这个缓存页的内容分成8块,并把他们加入了块缓存。
所以,从块设备inode读上来的缓存页,基本可以肯定,与它相关联的8个buffer_head,迟早会被加入到块 hash表中。因此,属于块设备inode的缓存页,这些缓存页,就是块缓存。
块设备inode的页缓存,与设备层的块缓存达到了统一,不会引发不一致的问题。
但是普通文件完全不同,普通文件inode的缓存页永远不会对应上块缓存。而且磁盘上的同一页甚至可能会有(普通文件inode->i_mapping , index) 和 (块设备inode->i_mapping , index)两个唯一标识这个页的值,既可能会在页缓存中有两个副本???????????
虽然这绝对不可能。
[ 本帖最后由 motalelf 于 2006-7-17 17:21 编辑 ] |
|