为了提高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. 禁用ubuntu的触摸板和独显

    #!/bin/bash #This is a vgaoff & touchpadoff #By spinestars #-2-18#TouchPad & VGA OFF == ];th ...

  2. 发布(Windows)

    发布(Windows) 本篇将在这个系列演示的例子上继续记录Asp.Net Core在Windows上发布的过程. Asp.Net Core在Windows上可以采用两种运行方式.一种是自托管运行,另 ...

  3. Azure上A/D系列虚拟机到DS系列迁移(2)

    11. 该脚本会检测环境,停止虚拟机,拷贝VHD文件,创建磁盘等等,知道出现如下类似画面,他会暂停等待用户操作: 后面这几个步骤非常重要,关系到你后续的创建是否成功: 12. 进入D:\migvm目录 ...

  4. Linux系统编程(8)—— 进程之进程控制函数fork

    fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事. 一个进程调用fork()函数后,系统先 ...

  5. arm linux中添加开机启动

    微处理器:S5PV210操作系统:linux3.0.8 前言:    在产品中,基本上都要屏蔽arm开发板中linux系统的对外通信,只应该通过产品的相关APP做相关操作.    因此需要把该APP添 ...

  6. Best Time to Buy and Sell Stock I II III

    Best Time to Buy and Sell Stock Say you have an array for which the ith element is the price of a gi ...

  7. python中的那些“神器”

    "武林至尊,宝刀屠龙,号令天下,莫敢不从,倚天不出,谁与争锋",这是神器.不过今天要说的python中的"神器"就没有这么厉害了,这里要说的"神器&q ...

  8. 谷歌Cartographer学习(1)-快速安装测试(转载)

    转载自谷歌Cartographer学习(1)-快速安装测试 代码放到个人github上,https://github.com/hitcm/ 如下,需要安装3个软件包,ceres solver.cart ...

  9. java面试题集1

    一:单选题 下列哪一种叙述是正确的(D )A. abstract修饰符可修饰字段.方法和类B. 抽象方法的body部分必须用一对大括号{ }包住C. 声明抽象方法,大括号可有可无D. 声明抽象方法不可 ...

  10. Ffmpeg和SDL如何同步音频

    ong> 同步音頻 现在我们已经有了一个比较像样的播放器.所以让我们看一下还有哪些零碎的东西没处理.上次,我们掩饰了一点同步问题,也就是同步音频到视频而不是其它的同步方式.我们将采用和视频一样的 ...