为了提高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. thinkphp3.2之模型(M层)

    最近学习了php框架thinkphp,回头总结了些学习心得知识,希望对大家有帮助 1.模型的概念: 模型(Model)是 ThinkPHP 中一个很重要的概念,粗略的理解模型就是与数据库交互信息进行c ...

  2. Sumblime Text 2 常用插件以及安装方法

    1.直接安装 安装Sublime text 2插件很方便,可以直接下载安装包解压缩到Packages目录(菜单->preferences->packages). 2.使用Package C ...

  3. HTML5 JavaScript 文件上传

    function fileUpload(targetUrl) { // 隐藏表单名称 var inputName = '_fileselect'; // 文件尺寸 this.fileSize = 0; ...

  4. GTW likes math(BC 1001)

    GTW likes math Accepts: 472 Submissions: 2140 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 1 ...

  5. js区分移动设备与PC

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  6. HttpRuntime类

    HttpRuntime在ASP.NET处理请求中负责的是创建HttpContext对象以及调用HttpApplicationFactory创建HttpApplication. 其定义如下: publi ...

  7. Jump Game II 解答

    Question Given an array of non-negative integers, you are initially positioned at the first index of ...

  8. Canvas之动态波浪效果_陈在真Sunny_chen_新浪博客

    Canvas之动态波浪效果_陈在真Sunny_chen_新浪博客 Canvas之动态波浪效果 (2012-04-26 09:04:51) 转载▼

  9. IsDbNull 方法的用法

    本文来自:http://lazhgg.cnblogs.com/archive/2006/02/21/334915.html 在c#中,进行数据库查询时使用IsDbNull 方法判断数据库中字段值是否存 ...

  10. Android应用程序组件Content Provider的共享数据更新通知机制分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6985171 在Android系统中,应用程序组 ...