文章插图

文章插图

文章插图
只有符合指定类型的设备 , 才会触发对应的驱动程序 。
三、主体代码描述linux驱动子系统 , 一般包含下面几个内容:
- 子系统初始化:驱动bus的建立 , 子设备驱动的挂载 。
- 外设扫描:对于scsi而言就是把device侧的所有lun扫描出来 。
- 通路建立:建立子设备驱动和device之间的连接 , 对于scsi而言就是公版外设驱动和lundevice之间的通路 。Scsi子系统是借助block通用块设备层完成这部分工作 。
- 休眠唤醒:对于scsi而言 , 休眠过程是lun->target->host , 唤醒过程是反过来 。这个决定了host是爷爷辈设备 , targe是父设备 , lun是子设备 , 所有的公版驱动都是子设备驱动 。

文章插图
(1) Scsi_init_queue:这个函数主要是创建scsi cmd和sense cache用到的slab内存 , 这样后续scsi cmd和sense都可以在slab中申请内存 , 加快内存申请速度 。
(2)Scsi_init_procfs:这个是创建一个/proc/scsi/scsi的文件节点
这个节点会显示当前系统注册了哪些scsi设备 , 包括这些设备的channel编号,id编号 lun编号等信息 。
这些信息都是实时变化的;如果有写入动作 , 也会触发子系统的scan动作 。

文章插图
(3) Scsi_init_devinfo这个函数创建了/proc/scsi/device_info节点 。
这个节点有点像kernel 里面常用的quirk等fix机制 , 内容如下

文章插图

文章插图
结构体的前面三类分别是vendor,model和revision , 其实就是scsi inquiry命令返回的数据 , 最后一个是个整形flag值 , 这个flag值影响着设备的初始话过程和操作过程 。例如BLIST_NOLUN会让scsi扫描外设时 , 只扫描lun0 。
(4) Scsi_init_sysctl这个函数创建了一个/proc/sys/dev/scsi/logging_level节点 , 这个节点控制着scsi子系统debug打印的log等级 , 值越小 , 打印越少 。
(5) Scsi_init_hosts和scsi_sysfs_register这两个函数创建了scsi子系统最关键的bus和class(“scsi”, “scsi_host”和“scsi_device”):
2.子设备驱动加载这类驱动加载一般比较简单 , 而且单独以module形式 , 耦合性很小 。它们一般在module初始化时注册到”scsi” bus总线上 , 然后一直等待有对应的子设备sdev_devgen挂到”scsi” bus上来 。例如:

文章插图
3.外设扫描Scsi扫描过程定义: 是识别每个host , 每个targe和每个lun , 给其创建对应的device结构 , 并将device挂载到相应的bus或class上 。
设备扫描的方式很多:
- 以host为单位进行scan 。它会把host对应的device下面所有的target和lun全扫描出来 。
- 以target为单位触发scsi进行scan 。它会把target下面所有的lun全扫出来
- 以lun为单位触发scsi进行scan 。它会扫描特定lun 。
- 通过/proc/scsi/scsi触发特定的target或lun的scan 。
- 通过host对应user空间设备的属性”scan”节点触发特定的target或lun的scan 。
例如我电脑上 , host设备是名为”ahci”的pci_driver扫描创建的控制器 , 一共有6个控制器 , 其中只有host4这个控制器上接了一块硬盘 。

文章插图
无论哪种当上一级驱动找到host后 , 会通过下面的
scsi_host_alloc:创建shost_gendev和shost_dev 。
推荐阅读
- linux之间传文件命令之Rsync傻瓜式教程
- 微软提交补丁,用Linux替代Hyper-V根分区的Win
- 借助 HTTP 通过 SSH 绕过 Linux 防火墙
- Linux或者Mac下命令行speedtest测试网络速度
- 硬盘有必要分区吗?MacOS、Linux都不分区
- linux中ELF格式二进制程序
- 利用这个 USB ID 仓库识别更多 Linux 上的设备
- Linux内核虚拟内存管理之匿名映射缺页异常分析
- 在Linux中使用Bashtop与Bpytop监管系统资源
- Linux驱动-互斥锁用法,建议先保存
