为了提高Linux块设备读写的效率,Unix会在内存中建立块高速缓存,块高速缓存存储了系统最近读的数据块和刚刚写入的数据块,也就是说IO访问其实是和块高速缓存打交道的(直接IO除外),块高速缓存会适时同步脏的数据页面(如果是同步模式则立刻同步),也就是常说的Unix延迟写,这样会极大提高系统读写的效率。有人或许问,数据不直接写在设备上的话断电的话数据丢失怎么办,只能说,对不起,没办法。

下面介绍三个重要的内核读函数。

(1)__find_get_block().函数__find_get_block()的参数有:block_device描述符地址bdev,块号block和块大小size。函数返回页高速缓存中的块缓冲区对应的缓冲区首部的地址;如果不存在指定的块,就返回NULL.

(2)__getblk().__getblk()其与__find_get_block()接收相同的参数,并返回与缓冲区对应的缓冲区首部的地址。与__find_get_block()不同的是,如果块不存在,__getblk()会分配块设备缓冲区页并返回将要描述块的缓冲区首部的指针。注意,__getblk()返回的块缓冲区不必存有有效数据(因为还没读磁盘)。

struct buffer_head * __getblk(struct block_device *bdev, sector_t block, int size)

{

……

      __find_get_block(bdev, block, size);

……

grow_buffers()

……

}

grow_buffers()这个函数就是将分配的缓冲区加入块高速缓存中,参数与__find_get_block相同。grow_buffers()调用流程如下:grow_buffers---->grow_dev_page--->find_or_create_page在块高速缓存中搜索需要的页,如果需要,就把新的页插入高速缓存--->add_to_page_cache_lru将块缓存加入lru链表--->add_to_page_cache将块缓存加入块高速缓存中.

(3) __bread(). __bread()的参数也与前两个相同,返回与缓冲区对应的缓冲区首部的地址,与__getblk()不同的是,__bread()会从读取相应的磁盘块,并将其填充到缓冲区。

struct buffer_head * __bread(struct block_device *bdev, sector_t block, int size)

{

……

      __getblk(bdev, block, size);

……

__bread_slow(bh);

}

__bread_slow()函数调用submit_bh()函数填充块缓存bh.

从三个函数可以看出来,它们的关系是递进的,第一个函数只负责在块高速缓存中查找,第二个则多了一个分配高速缓存块的操作,最后多了一个从磁盘中读取相应块并填充缓存块的操作。

参考资料:《深入理解linux内核》

Linux中的读函数与块高速缓存的更多相关文章

  1. 深入解析Linux中的fork函数

    1.定义 #include <unistd.h> #include<sys/types.h> pid_t fork( void ); pid_t 是一个宏定义,其实质是int, ...

  2. 如何测试Linux 中的wait函数能不能等待子进程的子进程?

    #include <stdio.h> #include <stdlib.h> int main() { pid_t pid = fork(); switch(pid) { : ...

  3. [fork]Linux中的fork函数详解

    ---------------------------------------------------------------------------------------------------- ...

  4. 关于linux中的system函数

    Linux下使用system()函数一定要谨慎 https://blog.csdn.net/senen_wakk/article/details/51496322 system()正确应用 https ...

  5. Unix/Linux中的fork函数

    fork函数介绍 一个现有进程可以调用fork函数创建一个新进程.该函数定义如下: #include <unistd.h> pid_t fork(void); // 返回:若成功则在子进程 ...

  6. Linux中的入口函数main

    main()函数,想必大家都不陌生了,从刚开始写程序的时候,大家便开始写main(),我们都知道main是程序的入口.那main作为一个函数,又是谁调用的它,它是怎么被调用的,返回给谁,返回的又是什么 ...

  7. 练习一下linux中的list函数。

    所有的list函数见 include/linux/list.h 自己从 include/linux/list.h 拷贝了一些函数到自己的list.c中, 然后练习了一下. 没有别的目的,就是想熟练一下 ...

  8. linux中内核延时函数 (转)

    第一类延时函数原型是:(忙等) void ndelay(unsigned long nsecs); void udelay(unsigned long usecs); void mdelay(unsi ...

  9. linux中字符串转换函数 simple_strtoul【转】

    转自:http://blog.csdn.net/tommy_wxie/article/details/7480087 Linux内核中提供的一些字符串转换函数: lib/vsprintf.c [htm ...

随机推荐

  1. project euler 19: Counting Sundays

    import datetime count = 0 for y in range(1901,2001): for m in range(1,13): if datetime.datetime(y,m, ...

  2. linux----ulimit 限制

    ulimit -a 显示当前用户的各种限制. ulimit -n 的数值表示每个进程可以打开的文件数目. 一般情况下, ulimit -n 的数值是1024. 当进程打开的文件数目超过此限制时,该进程 ...

  3. BZOJ 2535 Plane 航空管制2

    http://www.lydsy.com/JudgeOnline/problem.php?id=2535 思路:对于1,我们只需要每个点比前驱大就可以了,然后满足尽量优. 对于第二问,我们先求出这个点 ...

  4. 国际化标签 <fmt:bundle>&<fmt:message>的使用

    国际化标签 <fmt:bundle>&<fmt:message>的使用 Message.properties文件: name=www.gis520.com #info= ...

  5. LeeCode-Merge Sorted Array

    Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array. Note:Yo ...

  6. HDU1232 畅通工程 (并查集模板题)

    畅通工程 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

  7. 今日成长笔记2016-11-18 - 关于java开发

    好久没有写今日成长笔记了,要记得上一次写笔记还是2016-09-05,今天心血来潮,写一写最近发生在自己身上的事情,以后我要坚持每天写日记.我承认自己身上的确或多或少的存在不足,现在把它们抛出来,并记 ...

  8. PHP 表单验证 - 完成表单实例

    ------------------------------------------------------------------------------------------- 本节展示如何在用 ...

  9. jquery实现仿商品星级评价

    一,HTML部分 <div id="rating-star">     <a href="#">0</a>     < ...

  10. Bitmap工具类

    一直在使用的一个Bitmap工具类 处理Bitmap和ImageView对象,实现了下面功能: 1.saveBitmap: 把Bitmap对象持久存储到SD卡或手机内存. 2.getViewBitma ...