linux 块设备驱动(二)——块设备数据结构
本文来源于:
1. http://www.cnblogs.com/dyllove98/archive/2013/07/01/3165567.html
块设备相关的数据结构以及接口:
块设备接口则相对复杂,读写API没有直接到块设备层,而是直接到文件系统层,然后再由文件系统层发起读写请求。
一: block_device: block_device结构代表了内核中的一个块设备。它可以表示整个磁盘或一个特定的分区。当这个结构代表一个分区时,它的bd_contains成员指向包含这个分区的设备,bd_part成员指向设备的分区结构。当这个结构代表一个块设备时,bd_disk成员指向设备的gendisk结构。
- struct block_device {
- dev_t bd_dev;
- struct inode * bd_inode; /*分区结点*/
- int bd_openers;
- struct semaphore bd_sem; /*打开/关闭锁*/
- struct semaphore bd_mount_sem; /* 加载互斥锁*/
- struct list_head bd_inodes;
- void * bd_holder;
- int bd_holders;
- struct block_device * bd_contains;
- unsigned bd_block_size;//分区块大小
- struct hd_struct * bd_part;
- unsigned bd_part_count;//打开次数
- int bd_invalidated;
- struct gendisk * bd_disk;
- struct list_head bd_list;
- struct backing_dev_info *bd_inode_backing_dev_info;
- unsigned long bd_private;
- };
- 二:gendisk是一个单独的磁盘驱动器的内核表示。内核还使用gendisk来表示分区。
- struct gendisk {
- int major; //主设备号
- int first_minor;
- int minors; //最大的次设备号数量,如果设备不能分区,该值为1
- char disk_name[32]; //主设备名
- struct hd_struct **part; //分区信息,有minors个
- struct block_device_operations *fops;//设备操作
- struct request_queue *queue; //设备管理I/O请求
- void *private_data;
- sector_t capacity;
- int flags;
- char devfs_name[64];
- int number;
- struct device *driverfs_dev;
- struct kobject kobj;
- struct timer_rand_state *random;
- int policy;
- atomic_t sync_io;
- unsigned long stamp, stamp_idle;
- int in_flight;
- #ifdef CONFIG_SMP
- struct disk_stats *dkstats;
- #else
- struct disk_stats dkstats;
- #endif
- };
- gendisk结构的操作函数包括以下几个:
- struct gendisk *alloc_disk(int minors); //分配磁盘
- void add_disk(struct gendisk *disk); //增加磁盘信息
- void unlink_gendisk(struct gendisk *disk) //删除磁盘信息
- void delete_partition(struct gendisk *disk, int part); //删除分区
- void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len, int flags);//添加分区
- 三: block_device_operations结构是块设备对应的操作接口,是连接抽象的块设备操作与具体块设备操作之间的枢纽。
- struct block_device_operations {
- int (*open) (struct inode *, struct file *);
- int (*release) (struct inode *, struct file *);
- int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long);
- long (*unlocked_ioctl) (struct file *, unsigned, unsigned long);
- long (*compat_ioctl) (struct file *, unsigned, unsigned long);
- int (*direct_access) (struct block_device *, sector_t, unsigned long *);
- int (*media_changed) (struct gendisk *);
- int (*revalidate_disk) (struct gendisk *);
- int (*getgeo)(struct block_device *, struct hd_geometry *);
- struct module *owner;
- };
- block_device_operations并不能完全提供文件操作全部的API,实际上只提供了open、release等函数,其他的文件操作依赖于def_blk_fops:
- const struct file_operations def_blk_fops = {
- .open = blkdev_open,
- .release = blkdev_close,
- .llseek = block_llseek,
- .read = do_sync_read,
- .write = do_sync_write,
- .aio_read = generic_file_aio_read,
- .aio_write= generic_file_aio_write_nolock,
- .mmap = generic_file_mmap,
- .fsync = block_fsync,
- .unlocked_ioctl = block_ioctl,
- #ifdef CONFIG_COMPAT
- .compat_ioctl = compat_blkdev_ioctl,
- #endif
- .splice_read = generic_file_splice_read,
- .splice_write = generic_file_splice_write,
- };
四: 系统对块设备进行读写操作时,通过块设备通用的读写操作函数将一个请求保存在该设备的操作请求队列(request queue)中,然后调用这个块设备的底层处理函数,对请求队列中的操作请求进行逐一执行。request_queue结构描述了块设备的请求队列,该结构定义如下:
- struct request_queue
- {
- struct list_head queue_head;
- struct request *last_merge;
- elevator_t elevator;
- /*请求队列列表*/
- struct request_list rq;
- request_fn_proc *request_fn;
- merge_request_fn *back_merge_fn;
- merge_request_fn *front_merge_fn;
- merge_requests_fn *merge_requests_fn;
- make_request_fn *make_request_fn;
- prep_rq_fn *prep_rq_fn;
- unplug_fn *unplug_fn;
- merge_bvec_fn *merge_bvec_fn;
- activity_fn *activity_fn;
- /*自动卸载状态*/
- struct timer_list unplug_timer;
- int unplug_thresh;
- unsigned long unplug_delay; /*自动卸载延时*/
- struct work_struct unplug_work;
- struct backing_dev_info backing_dev_info;
- void *queuedata;
- void *activity_data;
- unsigned long bounce_pfn;
- int bounce_gfp;
- unsigned long queue_flags;//各种队列标志
- /*保护队列结构,避免重入*/
- spinlock_t *queue_lock;
- /* 请求的核心结构*/
- struct kobject kobj;
- /*请求的配置*/
- unsigned long nr_requests; /* 请求的最大数*/
- unsigned int nr_congestion_on;
- unsigned int nr_congestion_off;
- unsigned short max_sectors;
- unsigned short max_phys_segments;
- unsigned short max_hw_segments;
- unsigned short hardsect_size;
- unsigned int max_segment_size;
- unsigned long seg_boundary_mask;
- unsigned int dma_alignment;
- struct blk_queue_tag *queue_tags;
- atomic_t refcnt;
- unsigned int in_flight;
- /*sg 参数配置*/
- unsigned int sg_timeout;
- unsigned int sg_reserved_size;
- };
- 请求队列相关的处理函数包括:
- //创建队列时提供了一个自旋锁。
- request_queue_t *blk_init_queue(request_fn_proc *rfn, spinlock_t *lock);
- //获得队列中第一个未完成的请求。
- struct request *elv_next_request(request_queue_t *q);
- void end_request(struct request *req, int uptodate);//请求完成
- void blk_stop_queue(request_queue_t *queue); //停止请求
- void blk_start_queue(request_queue_t *queue); //开始请求
- void blk_cleanup_queue(request_queue_t *);//清除请求队列
五:向内核注册和注销一个块设备可使用如下函数:
- int register_blkdev(unsigned int major, const char *name);
- int unregister_blkdev(unsigned int major, const char *name);
linux 块设备驱动(二)——块设备数据结构的更多相关文章
- 【转】深入浅出:Linux设备驱动之字符设备驱动
深入浅出:Linux设备驱动之字符设备驱动 一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用驱动程序: 字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据 ...
- Linux 设备驱动开发 —— platform设备驱动应用实例解析
前面我们已经学习了platform设备的理论知识Linux 设备驱动开发 —— platform 设备驱动 ,下面将通过一个实例来深入我们的学习. 一.platform 驱动的工作过程 platfor ...
- 字符设备驱动、平台设备驱动、设备驱动模型、sysfs的比较和关联
转载自:http://www.kancloud.cn/yueqian_scut/emlinux/106829 学习Linux设备驱动开发的过程中自然会遇到字符设备驱动.平台设备驱动.设备驱动模型和sy ...
- [kernel]字符设备驱动、平台设备驱动、设备驱动模型、sysfs几者之间的比较和关联
转自:http://www.2cto.com/kf/201510/444943.html Linux驱动开发经验总结,绝对干货! 学习Linux设备驱动开发的过程中自然会遇到字符设备驱动.平台设备驱动 ...
- Linux块设备驱动(二) _MTD驱动及其用户空间编程
MTD(Memory Technology Device)即常说的Flash等使用存储芯片的存储设备,MTD子系统对应的是块设备驱动框架中的设备驱动层,可以说,MTD就是针对Flash设备设计的标准化 ...
- 乾坤合一~Linux设备驱动之块设备驱动
1. 题外话 在蜕变成蝶的一系列学习当中,我们已经掌握了大部分Linux驱动的知识,在乾坤合一的分享当中,以综合实例为主要讲解,在一个月的蜕茧成蝶的学习探索当中,觉得数据结构,指针,链表等等占据了代码 ...
- 深入浅出:Linux设备驱动之字符设备驱
一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用驱动程序: 字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据,读取数据需要按照先后数据.字符设备是面向流 ...
- 蜕变成蝶~Linux设备驱动之字符设备驱动
一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用驱动程序: 字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据,读取数据需要按照先后数据.字符设备是面向流 ...
- 深入浅出:Linux设备驱动之字符设备驱动
一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用驱动程序: 字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据,读取数据需要按照先后数据.字符设备是面向流 ...
- Linux 设备驱动之字符设备
参考转载博客:http://blog.chinaunix.net/uid-26833883-id-4369060.html https://www.cnblogs.com/xiaojiang1025/ ...
随机推荐
- [转] Makefile 基础 (2) —— Makefile 总述
该篇文章为转载,是对原作者系列文章的总汇加上标注. 支持原创,请移步陈浩大神博客:(最原始版本) http://blog.csdn.net/haoel/article/details/2886 我转自 ...
- visual studio NuGet 常用包管理命令
visual studio NuGet 常用包管理命令 查找包 Find-Package [包名] Find-Package [包名] -AllVersions 安装包 Install-Package ...
- 我要好offer之 字符串相关大总结
1. str*系列手写代码 a. 一定要注意末尾'\0'的处理,切记切记 b. 一定要对输入做有效性判断,多用断言就是了 int Strlen(const char* str) { assert(st ...
- 集合工具类CollectionUtils、ListUtils、SetUtils、MapUtils探究(转)
之前一直以为集合工具类只有CollectionUtils,主要用它的isEmpty(final Collection<?> coll)静态方法来判断一个给定的集合是否为null或者是否长度 ...
- 开始学习es6(一) 搭建个es6的开发环境
1.开始学习es6 如果想在浏览器跑es6 需要给es6个环境 因为一直用vue-cli全家桶 这样虽然方便 但如果用es6需要跑起个vue全家桶 于是想到可以用gulp搭建个开发环境 首先需要1. ...
- C语言处理json字符串
JSON语法说明 先来看一个简单的JSON 1 { 2 "stars": [ 3 { 4 "name": "Faye", 5 "a ...
- Spring MVC学习一
SpringMVC是一个基于DispatcherServlet的MVC框架,每一个请求最先访问的都是DispatcherServlet,DispatcherServlet负责转发每一个Request请 ...
- 微信小程序踩坑之一[thist]使用技巧
刚上手小程序 时,习惯把this当成jquery中的$(this)来用,实际上这两个还是有差别的 在页面方法中调用其他方法,一般是用this.function(),直接调用小程序 的方法或函数则是用w ...
- mac下安装pyQt4
1.首先安装QT,同时要有gcc 2.然后就是先安装sip,然后安装pyqt4 python configure.py -q /usr/bin/qmake-4.8 -d /Library/Python ...
- BZOJ2002弹飞绵羊
动态树LCT模板题 #include<cstdio> #include<cctype> #include<algorithm> using namespace st ...