块设备层分析3

块设备层保序操作分析 8.POSTFLUSH request的完成同5,6步,最后进入到blk_ordered_complete_seq(),blk_ordered_cur_seq(q)当前的步骤为QUEUE_ORDSEQ_DONE,整个保序过程完毕,调用__blk_end_request(q->orig_bar_rq)对原始保序请求做完成的回调.A:通用块层可以提交一个带保序标签(BIO_RW_BARRIER)的BIO到IO请求队列,块设备层可以保证在保序BIO之前提交的BIO都先于BIO执行且抵达存储介质; 阅读详情

以上均是IDE总线上设备的通用接口,直到do_request开始才执行特定设备的驱动,如CD,HD, floppy等IDE设备。我们来看一下ide-disk:

1、 首先是设备的初始化操作。

IDE设备接口

static ide_driver_t idedisk_driver = {

       .gen_driver = {

              .owner           = THIS_MODULE,

              .name             = "ide-disk",

              .bus        = &ide_bus_type,

       },

       .probe                   = ide_disk_probe,

       .remove                 = ide_disk_remove,

       .shutdown             = ide_device_shutdown,

       .version          = IDEDISK_VERSION,

       .media                   = ide_disk,

       .supports_dsc_overlap   = 0,

       .do_request            = ide_do_rw_disk,

       .end_request          = ide_end_request,

       .error                    = __ide_error,

       .abort                    = __ide_abort,

       .proc                     = idedisk_proc,

};

static struct block_device_operations idedisk_ops = {

       .owner           = THIS_MODULE,

       .open             = idedisk_open,

       .release    = idedisk_release,

       .ioctl              = idedisk_ioctl,

       .getgeo           = idedisk_getgeo,

       .media_changed     = idedisk_media_changed,

       .revalidate_disk= idedisk_revalidate_disk

};

//设备注册

static int __init idedisk_init(void)

{

       return driver_register(&idedisk_driver.gen_driver);

}

//这个probe函数是在设备注册时由驱动模型去执行

static int ide_disk_probe(ide_drive_t *drive)

{

       struct ide_disk_obj *idkp;

       struct gendisk *g;

       idkp = kzalloc(sizeof(*idkp), GFP_KERNEL);

      

//分配一个gendisk结构

g = alloc_disk_node(1 << PARTN_BITS,

                     hwif_to_node(drive->hwif));

       ide_init_disk(g, drive);

       //用上面的结构注册设备

       ide_register_subdriver(drive, &idedisk_driver);

       kref_init(&idkp->kref);

       //一些初始化操作

       idkp->drive = drive;

       idkp->driver = &idedisk_driver;

       idkp->disk = g;

       g->private_data = &idkp->driver;

       drive->driver_data = idkp;

       idedisk_setup(drive);

       g->minors = 1 << PARTN_BITS;

       g->driverfs_dev = &drive->gendev;

       g->flags = drive->removable ? GENHD_FL_REMOVABLE : 0;

       set_capacity(g, idedisk_capacity(drive));

       g->fops = &idedisk_ops;

       add_disk(g); //插入设备,至此,该设备可用

       return 0;

}

2、 处理IDE总线发来的请求

由上可以看到,IDE总线驱动调用设备的do_request()去处理这个请求,我们在上面的注册中可以看到。在ide-disk里,它是ide_do_rw_disk():

/*

* 268435455 == 137439 MB or 28bit limit

* 320173056 == 163929 MB or 48bit addressing

* 1073741822 == 549756 MB or 48bit addressing fake drive

*/

static ide_startstop_t ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector_t block)

{

       ide_hwif_t *hwif = HWIF(drive);

……

       if (hwif->rw_disk)

       hwif->rw_disk(drive, rq);

       return __ide_do_rw_disk(drive, rq, block);

}

//以下就是特定硬盘设备的驱动了,因为我们只关心块设备驱动编程的框架,所以就不深入进去了。

/*

* __ide_do_rw_disk() issues READ and WRITE commands to a disk,

* using LBA if supported, or CHS otherwise, to address sectors.

*/

static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq, sector_t block)

{

       ide_hwif_t *hwif    = HWIF(drive);

       unsigned int dma    = drive->using_dma;

       u8 lba48         = (drive->addressing == 1) ? 1 : 0;

       task_ioreg_t command   = WIN_NOP;

       ata_nsector_t         nsectors;

       nsectors.all            = (u16) rq->nr_sectors;

       if (hwif->no_lba48_dma && lba48 && dma) {

              if (block + rq->nr_sectors > 1ULL << 28)

                     dma = 0;

              else

                     lba48 = 0;

       }

       if (drive->select.b.lba) {

              if (lba48) {

                     ……

              } else {

              ……

              }

       } else {

              ……

       }

       if (dma) {

              ……

              /* fallback to PIO */

              ide_init_sg_cmd(drive, rq);

       }

       if (rq_data_dir(rq) == READ) {

              if (drive->mult_count) {

                     hwif->data_phase = TASKFILE_MULTI_IN;

                     command = lba48 ? WIN_MULTREAD_EXT : WIN_MULTREAD;

              } else {

                     hwif->data_phase = TASKFILE_IN;

                     command = lba48 ? WIN_READ_EXT : WIN_READ;

              }

              ide_execute_command(drive, command, &task_in_intr, WAIT_CMD, NULL);

              return ide_started;

       } else {

       ……

              return pre_task_out_intr(drive, rq);

       }

}

3、 块设备驱动小结

我们由上看到, 块设备驱动编程的主要工作包括分配并初始化一个gendisk结构,分配并初始化一个请求队列,请求处理函数的编写(request_fn),还有中断的处理等等。但具体到不同的设备,实现又有一些出入,我们在上面看到的IDE设备,它大部分工作都是在IDE总线级上实现了,它做了许多繁琐但必要的工作,并向下层特定设备提供统一的接口,这样就大大简化了块设备驱动的编写过程。

       有兴趣可以参考一下内核ramdisk的实现。

MBR-LBA48位资料 操作系统基础,可以编译成bin文件,直接写入MBR,也可以作为写入MBR的工具 立即下载

相关推荐

QuickFix Java 讲解(一)概述、下载方法,和协议内容

本系列力求手把手教你怎样利用QuickFix Java 搭建自己的 FIX 协议收法平台,以及其中的注意事项。 所有源码的地址(免费): https://github.com/zongzhec/QuickFixPractise 1. 什么是FIX,QuickFix,Quick Java? 1.1. 什么是FIX 官网以及其他翻译自官网的帖子都太官方了,这里我们设想一个情景: 你是一个交易员,现在客户打电话来让你下个单买点股票。你啪啪啪的在你的机器上熟练地输入了下单指令。系统显示:成...

4573

操作系统真相还原_第3章:8086汇编硬件交互

笔记

dc12499574的博客 1245

网易CodeWave智能生成应用实战:5分钟搞定库存管理系统(附详细配置截图)

本文详细介绍了如何利用网易CodeWave智能生成应用在5分钟内快速构建定制化库存管理系统。通过自然语言描述需求,无需编程即可生成包含产品管理、库存预警等核心功能的应用,并支持字段微调、业务流程注入等深度优化。文章附有详细配置截图,帮助用户高效实现数字化转型。

julia4scientist的博客 886

【FAQ】存储基础知识 - 磁盘寻址(CHS寻址方式、LBA寻址方式)

【FAQ】存储基础知识 - 磁盘寻址       1、磁盘寻址 1.1、磁盘驱动器 维基百科网址:http://en.wikipedia.org/wiki/Hard_disk_drive 磁盘物理结构图如下:                         磁盘逻辑组成图如下:   1.2、什么是CHS(cylinder head sector) 维基百

haiross的专栏 2万+

使用python对创芯科技CANalyst-II分析仪进行二次开发(详细教程)

使用python对创芯科技CANalyst-II分析仪进行二次开发

ningqingzy的博客 1万+

海康威视Web3.0插件实战:快速部署摄像头实时预览方案

本文详细介绍了海康威视Web3.0插件的实战应用,包括快速部署摄像头实时预览方案的完整流程。从插件下载安装到摄像头连接配置,再到浏览器兼容性解决方案,帮助开发者和IT人员高效实现网页端监控功能。特别针对预览功能调优和多摄像头管理等高级应用提供了实用技巧。

weixin_29266679的博客 346

【读书笔记】从实模式到保护模式

用电表示数据寄存器的作用:具有记忆功能的器件。锁存可以通过下面的开关控制,平时开关为空,按下开关之后,将输入锁存起来。锁存之后右面灯泡就就不会变化了,除非再次按下锁存开关。下面的开关是关着的,有间隙,是上下按的。带有寄存器的加法机如何工作:每次输入/数字后存入寄存器,而不是多组线进行输入。再入加减乘除就是多了其他控制开关,上面的加减乘除是每个开关,其他控制的地方也可以用一组01值来表示各类操作。

努力充实,远方可期 1550

灰度图像采集显示

灰度图像采集显示 在FPGA内部,采集到的视频数据线通过一个FIFO,将原本与25MHZ时钟同步的数据流转换到FPGA内部50MHZ的时钟。接着将这个数据再送入写DDR3缓存的异步FIFO中,这个FIFO中的数据一旦达到一定数量,就会被写入DDR3中。于此同时,使用另一异步FIFO缓存从DDR3读出的图像数据;LCD驱动模块不断地发出读图像数据请求给到这个FIFO,从中读取图像数据并送给VGA显示器进行实时图像的显示。 ...

小柚子的博客 484

关于硬盘读写

这是所发的第一篇blog,是在学习操作系统时的一个问题,内容本是写给一个老师的问题,但最终没收到回复,在此留下,以提示自己思考,若阁下有解决思路,还请一定告知,谢谢!问题大概是这样,我写了段操作系统的引导代码,试图引导操作系统,而引导操作系统的必要一步就是读取pbr,然后跳转到pbr的代码上,而问题就出在读硬盘上,读硬盘可以通过int13中断(测试成功),但此法不能读...

weixin_34019144的博客 207

Altium Designer(AD24/25)PCB编辑的几种方法介绍

本文介绍了Altium Designer(AD24/25)软件中PCB编辑的四种操作方法:1)通过菜单栏"Place→Component"激活;2)点击工具栏元器件图标;3)右键快捷菜单选择;4)快捷键P+C组合操作。建议初学者先通过菜单栏和快捷菜单熟悉操作,熟练后转为工具栏和快捷键以提高效率。文章配有操作示意图,帮助用户快速掌握PCB元器件放置技巧。

fydar的博客 941

基于STM32L4XX 、HAL库的TMC2209-LA-T步进电机驱动器驱动程序应用设计

/ R/W=0 表示写。uint32_t gconf_value = (0 << 0) // I_scale_analog: 禁用,使用UART控制电流。uint32_t ihold_irun = (8 << 0) // 保持电流 8/31 最大值。

PP_Cottage的博客 449

Linux Kernel 3.10内核源码分析--块设备层request plug/unplug机制

一、基本原理 Linux块设备层使用了plug/unplug(蓄流/泄流)的机制来提升IO吞吐量。基本原理为:当IO请求提交时,不知直接提交给底层驱动,而是先将其放入一个队列中(相当于水池),待一定时机或周期后再将该队列中的请求统一下发。将请求放入队列的过程即plug(蓄流)过程,统一下发请求的过程即为unplug(泄流)过程。每个请求在队列中等待的时间不会太长,通常在ms级别。 如此设计,可

omnispace的博客 1946

分布式优化 (Distributed Optimization) 算法详解及案例分析

分布式优化是一种将优化问题分解为多个子问题并在多个计算节点上并行求解的方法。其目标是通过分布式计算资源高效地求解大规模优化问题。

闲人编程的博客 2708

linux sd卡驱动分析

原文地址:linux sd卡驱动分析 作者:shark888 linux sd卡驱动分析 (2012-01-30 16:48)转载 标签:  linux  class  normal  color  Linux  分类: 驱动系列 基于S3C2410的SD卡linux驱动工作原理  Linux MMC/SD/SDIO体系结构 linux sd卡驱动分析

Hens007的专栏 9638

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

戏说文件系统之ext3【上】

今天我们简单聊一哈ext3文件系统。ext3作为ext2的增强版,和ext2使用的superblock、inode、group descriptor等数据结构几乎一模一样,所以ext3前向兼容ext2。在不用备份ext2文件系统数据的情况下,可以用: tune2fs –j /dev/hdName 在不用卸载分区的状态下直接将ext2文件系统转换成ext3文件...

weixin_30895603的博客 176

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

基于S3C2410的SD卡linux驱动工作原理

Linux MMC/SD/SDIO体系结构 linux sd卡驱动分析                  基于S3C2410的SD卡linux驱动工作原理  我在讲嵌入式Linux驱动开发班的时候,发现不少学员对SD卡驱动这块比较感兴趣,课下来找我探讨。而在很多技术论坛,也有不少人问这方面的问题,所以就想写一

bingqingsuimeng的专栏 1828

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

基于S3C2410的SD卡linux驱动工作原理(二)

序:我在讲嵌入式Linux驱动开发班的时候,发现不少学员对SD卡驱动这块比较感兴趣,课下来找我探讨。而在很多技术论坛,也有不少人问这方面的问题,所以就想写一下这方面的内容,希望对大家的学习能有所帮助。 前几天写了篇“基于S3C2410的SD卡linux驱动工作原理(一)”,说了下脱离操作系统如何在S3C2410上实现SD卡的读写。了解了脱离操作系统的工作原理后,现在可以思考linux是如何管理管...

mmdev 110

linux-2.6.22.6内核nand flash框架分析

总结:块设备和字符设备这两类存储类驱动最终都会用到nand_scan_tail里面构造的mtd_info信息,最终的的读写函数都会定位到mtd_info的具体函数,不过块设备更复杂,分层更多,它主要分为硬件层、nand协议层和块设备层,硬件层知道怎样发命令,需要构造nand_chip结构体,协议层知道要发什么来操作。主要构造mtd_info结构体,块设备层使用mtd_info信息,并用电梯调度算法进行优化。

qq_34429554的博客 329

linux日志型文件系统,Linux日志型文件系统的研究及其性能优化

摘要:Linux支持众多文件系统,从日志型文件系统到集群文件系统和加密文件系统。其中,作为Linux固有的文件系统,EXT2文件系统是最广泛采用的非日志型文件系统。但在日常使用中,断电故障或系统崩溃这样不可预测的事件可能导致文件系统处于不一致状态,为克服这一问题而采用的自动进行的一致性检查e2fsck将对整个磁盘进行全面彻底地检查和修复,并能有效地修复因断电或崩溃等异常带来的不一致问题,保证了文件...

weixin_39991222的博客 202

Linux 2.6.20 SD/MMC卡驱动架构与实现解析

SD/MMC卡驱动是Linux存储子系统的核心组件,采用分层架构设计实现硬件抽象与协议栈分离。从块设备层、核心协议层到主机控制器驱动层,每层通过标准接口交互,这种设计提升了代码复用率和跨平台兼容性。在嵌入式开发中,理解MMC总线注册、卡检测机制和DMA传输优化等关键技术,对存储设备驱动开发至关重要。以S3C2440平台为例,驱动初始化涉及工作队列创建、中断注册和时钟配置等关键步骤,而mmc_rescan()函数则实现了卡识别与初始化的完整流程。通过分析struct mmc_host等核心数据结构,开发者可以

weixin_42522374的博客 314

Linux 块设备层中的Multi-queue分析

目前,百万甚至千万级别的IOPS数据访问量已成为一个大趋势,并且当前的SSD展现着越来越高效的性能表现。在这种趋势下linux的块设备层渐渐成为了整体系统性能提升的主要瓶颈。本文主要讨论的是在多核系统下,如何利用Multi-queue减小块设备层对整体性能的影响。 传统的块设备层针对于千/万级别的IOPS数据访问量是有所余力的,但是面对与日俱增的大数据访问,特别是在底层SSD提供更高速的访问性能...

yedushu的博客 3455

RPO与RTO视角下的CDP技术实现:从定时备份到IO级连续捕获的演进分析

企业灾备与数据保护技术实战,涵盖CDP持续保护、数据库备份、异地容灾架构等核心技术。

2601_96373668的博客 353

Linux块设备层架构与性能优化解析

块设备是Linux存储子系统的核心组件,负责将文件系统的抽象I/O请求转化为具体的存储设备操作。其核心架构包括通用块层、I/O调度层和设备映射层,通过多队列(blk-mq)机制和智能调度算法(如CFQ、Deadline)实现高性能存储访问。在现代SSD和NVMe设备场景下,NOOP和Kyber调度器能显著提升IOPS和降低延迟。开发实践中需关注request_queue和bio等关键数据结构,通过blktrace等工具进行性能分析和优化。这些技术广泛应用于云计算存储、数据库系统等高性能场景,是理解Linux

weixin_29232507的博客 277

Linux文件系统概述:硬盘驱动>通用块设备层>文件系统>虚拟文件系统(VFS)

目录 一.概述 1. 硬盘驱动 2. 通用块设备层 General Block Device Layer 3. 文件系统 4. 虚拟文件系统(VFS) 二.存储介质 闪存(Flash Memory) 外存 内存 1. 基于FLASH的文件系统 (1) jffs2 (2) yaffs:Yet Another Flash File System (3) Cramfs:Compressed ROM File System (4) Romfs 2. 基于RAM的文件系统 (1) Ra

RToax 3203

Multi-queue 架构分析

Linux上传统的块设备层(Block Layer)和IO调度器(如cfq)主要是针对HDD(hard disk drivers)设计的。我们知道,HDD设备的随机IO性能很差,吞吐量大...

内核工匠 4950
上一篇: 块设备层分析2
下一篇: RamDisk块设备驱动实例开发讲解
xp_super
博客等级 码龄14年 10粉丝 17原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值