文章目录

  • 前言
  • 一、什么是块设备?
  • 二、使用梳理
    • 1.使用请求队列
      • 1.1 初始化
      • 1.2 队列请求处理函数
    • 2.不使用请求队列
      • 2.1 初始化
      • 2.2 制造请求函数
  • 运行验证

前言

@和原子哥一起学习Linux

开发环境:I.MX6Ull开发板

参考书籍:
《【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.6.pdf》
《linux设备驱动开发详解-基于最新的linux4.0内核》

个人学习笔记,欢迎讨论

一、什么是块设备?

块设备驱动其实就是存储设备驱动,块设备只能以块为单位进行读写访问。

二、使用梳理

linux 内核使用 gendisk 来描述一个磁盘设备, 使用request_queue、 request 和 bio去读写数据,每个磁盘(gendisk)都要分配一个 request_queue。

内核将对块设备的读写都发送到请求队列 request_queue 中, request_queue 中是大量的request(请求结构体),而 request 又包含了 bio, bio 保存了读写相关数据。



对于机械硬盘而言,将那些杂乱的访问按照一定的顺序进行排列可以有效提高磁盘性能, linux 里面针对不同的存储设备实现了不同的 I/O 调度算法。
1)机械硬盘这样的存储设备,需要 I/O 调度器来优化数据读写过程,需要使用请求队列读写设备
2)对于 EMMC、 SD 卡这样的非机械设备,可以进行完全随机访问,所以就不需要复杂的 I/O 调度器,不需要请求队列

1.使用请求队列

1.1 初始化

省略错误 。。。

 //申请内存ramdisk.ramdiskbuf = kzalloc(RAMDISK_SIZE, GFP_KERNEL);。。。//初始化自旋锁,后面用spin_lock_init(&ramdisk.lock);//注册块设备ramdisk.major = register_blkdev(0, RAMDISKNAME);。。。//申请设备gendisk,申请3个分区ramdisk.gendisk = alloc_disk(RAMDISK_MINOR);。。。//分配初始化请求队列ramdisk.queue = blk_init_queue(do_ramdisk_request, &ramdisk.lock);。。。//注册diskramdisk.gendisk->major = ramdisk.major;ramdisk.gendisk->first_minor = 0; //起始设备号ramdisk.gendisk->fops = &ramdisk_fops;ramdisk.gendisk->queue = ramdisk.queue;sprintf(ramdisk.gendisk->disk_name, RAMDISKNAME);//使用 set_capacity 函数设置本块设备容量大小set_capacity(ramdisk.gendisk, RAMDISK_SIZE/512);//将 gendisk 添加到内核中,也就是向内核添加一个磁盘设备。add_disk(ramdisk.gendisk);return 0;

1.2 队列请求处理函数

static void ramdisk_transfer(struct request *req)
{unsigned long start = blk_rq_pos(req) << 9; //扇区地址转字节地址unsigned long len  = blk_rq_cur_bytes(req);//使用 bio_data 函数获取请求中 bio 保存的数据void *buffer = bio_data(req->bio);if (rq_data_dir(req) == READ)memcpy(buffer, (char *)ramdisk.ramdiskbuf + start, len);elsememcpy((char *)ramdisk.ramdiskbuf + start, buffer, len);
}static void do_ramdisk_request(struct request_queue *q)
{struct request *req;int err = 0;//循环处理队列req = blk_fetch_request(q);while (req != NULL) {ramdisk_transfer(req);//* 判断是否为最后一个请求,如果不是的话就获取下一个请求if (!__blk_end_request_cur(req, err))req = blk_fetch_request(q);}
}

2.不使用请求队列

2.1 初始化

省略错误 。。。

 //申请内存ramdisk.ramdiskbuf = kzalloc(RAMDISK_SIZE, GFP_KERNEL);。。。//注册设备ramdisk.major = register_blkdev(0, RAMDISKNAME);。。。//申请设备gendisk,申请3个分区ramdisk.gendisk = alloc_disk(RAMDISK_MINOR);。。。

//分配初始化请求队列
ramdisk.queue = blk_alloc_queue(GFP_KERNEL);

。。。
//设置制造请求
blk_queue_make_request(ramdisk.queue, ramdisk_make_request_fn);

 //注册diskramdisk.gendisk->major = ramdisk.major;ramdisk.gendisk->first_minor = 0; //起始设备号ramdisk.gendisk->fops = &ramdisk_fops;ramdisk.gendisk->queue = ramdisk.queue;sprintf(ramdisk.gendisk->disk_name, RAMDISKNAME);//使用 set_capacity 函数设置本块设备容量大小set_capacity(ramdisk.gendisk, RAMDISK_SIZE/512);//将 gendisk 添加到内核中,也就是向内核添加一个磁盘设备。add_disk(ramdisk.gendisk);return 0;

2.2 制造请求函数

static void ramdisk_make_request_fn(struct request_queue *q, struct bio *bio)
{int offset;struct bio_vec bvec;struct bvec_iter iter;unsigned long len = 0;offset = bio->bi_iter.bi_sector << 9; //获取设备偏移地址bio_for_each_segment(bvec, bio, iter) {char *ptr = page_address(bvec.bv_page) + bvec.bv_offset;len = bvec.bv_len;if (bio_data_dir(bio) == READ)memcpy(ptr, (char *)ramdisk.ramdiskbuf + offset, len);else if(bio_data_dir(bio) == WRITE) /* 写数据 */memcpy((char *)ramdisk.ramdiskbuf + offset, ptr, len);offset += len;    }set_bit(BIO_UPTODATE, &bio->bi_flags);bio_endio(bio, 0);return;
}

运行验证

加载模块
fdisk -l //查看磁盘信息
mkfs.vfat /dev/ramdisk//格式化/dev/ramdisk
mount /dev/ramdisk /tmp//挂载后就可以访问了

linux-块设备简单总结相关推荐

  1. [转]linux 块设备驱动

    转自 linux块设备IO栈 http://www.sysnote.org/2015/08/06/linux-io-stack/ linux块设备IO流程 驱动 https://www.cnblogs ...

  2. Linux块设备驱动总结

    <Linux设备驱动程序>第十六章 块设备驱动程序读书笔记 简介 一个块设备驱动程序主要通过传输固定大小的随机数据来访问设备 Linux内核视块设备为与字符设备相异的基本设备类型 Linu ...

  3. [转]Linux块设备加速缓存bcache和dm-cache:使用SSD来加速服务器

    dm-cache 与 bcache 在 LSFMM 2013 峰会上,Mike Snitzer, Kent Overstreet, Alasdair Kergon, 和 Darrick Wong 共同 ...

  4. Linux块设备驱动-MTD子系统

    Linux块设备驱动 块设备驱动 块设备驱动的引入 1. 简单字符驱动程序思想 2. 块设备驱动程序思想 块设备驱动框架 1. 层次框架 2. 分析ll_rw_block 块设备驱动程序编写 1.分配 ...

  5. 有点意思!Linux 块设备处理模型,基础【簇、柱面、存储的计算】

    http://blog.csdn.net/zplove003/article/details/7020557 簇:簇是指可分配的用来保存文件的最小磁盘空间,扇区是磁盘最小的物理存储单元,但由于操作系统 ...

  6. Linux块设备概念和列出块设备命令学习

    Linux块设备 一种具有一定结构的随机存取设备,对这种设备的读写是按块进行的,他使用缓冲区来存放暂时的数据,待条件成熟后,从缓存一次性写入设备或者从设备一次性读到缓冲区.可以随机访问,块设备的访问位 ...

  7. linux块设备驱动(一)——块设备概念介绍

    linux块设备驱动(一)--块设备概念介绍 本文来源于: 1. http://blog.csdn.net/jianchi88/article/details/7212370 2. http://bl ...

  8. linux 块设备驱动(二)——块设备数据结构

    linux 块设备驱动(二)--块设备数据结构 本文来源于: 1. http://www.cnblogs.com/dyllove98/archive/2013/07/01/3165567.html 块 ...

  9. linux 块设备驱动 (三)块设备驱动开发

    linux 块设备驱动 (三)块设备驱动开发 一: 块设备驱动注册与注销 块设备驱动中的第1个工作通常是注册它们自己到内核,完成这个任务的函数是 register_blkdev(),其原型为: int ...

  10. linux内存加速硬盘缓存,linux块设备加速缓存之bcache

    linux块设备加速缓存之bcache 什么是bcache 转载请注明出处:http://blog.csdn.net/liumangxiong bcache是linux内核块层cache.它使用类似S ...

最新文章

  1. WritePrivateProfileString、GetPrivateProfileString 读写配置文件
  2. 楼燚(yì)航的blog URL
  3. java 项目初始化一个定时任务_elastic-job 分布式定时任务框架 在 SpringBoot 中如何使用(一)初始化任务并定时执行...
  4. Docker 部署ELK 日志分析
  5. 简单讨论火车票系统后面的架构设计
  6. MUI - 解决bug: iphone页面保存时popPicker自动弹出来
  7. Android开源框架Afinal第一篇——揭开圣女的面纱
  8. jquery基础选择器和层次选择器
  9. on_mouse OpenCV 获得矩形区域
  10. web访问linux创建目录权限设置,centos7下新建一个用户并限制访问目录
  11. hasChildNodes()
  12. ZIGBEE 工程内区分终端与协调器
  13. python可以开发软件_python可以开发软件吗
  14. 大陆人怎么去香港银行开户?
  15. Google 百度 图标收藏
  16. RX的使用一:RXjava初级入门
  17. msysgit+apache安装说明
  18. 汽车产业链SCP分析框架-湖北
  19. 武汉智慧工地管理系统能帮助建筑施工提升质量吗?
  20. “寻梦之路 阿里之行”北城大数据学院学生代表团赴北京阿里中心参观...

热门文章

  1. AI一分钟|快播王欣出狱,与姚劲波、何小鹏一起畅谈人工智能、区块链
  2. 重庆-新加坡国际电竞嘉年华落幕“文旅+”助推建设国际旅游目的地
  3. 20131012-Actel公司申请License的方法
  4. 基于单片机的车内滞留儿童预警系统设计
  5. 怎样测量地图上曲线的长度_怎样从地图上估算出一条铁路的长度?找一张地图,计算从北京到广州铁路线的长度。...
  6. Hadoop实战问题记录
  7. C++ L1-034. 点赞
  8. NLP系列——(7)卷积神经网络
  9. 无忧考吧java的题库准吗,无忧考吧题库_无忧考吧从业题库难度和真正考试难度一样吗_淘题吧...
  10. 专访趋势科技:全面解析APT攻击过程