块设备驱动系统架构和简单设计
来源:互联网 发布:手机淘宝抠图 编辑:程序博客网 时间:2024/06/07 18:31
1.块设备概念
块设备是指只能以块(512Byte)为单位进行访问的设备,块大小一般是512个字节的整数倍。常见的块设备包括硬件,SD卡,光盘等。
2.快速体验
3.块设备驱动系统架构
VFS是对各种具体文件系统的一种封装 ,为用户程序访问文件提供统一的接口。
4.系统架构-Cache
5.Mapping Layer(映射层、FS文件系统)
块设备是指只能以块(512Byte)为单位进行访问的设备,块大小一般是512个字节的整数倍。常见的块设备包括硬件,SD卡,光盘等。
2.快速体验
- insmod simple-blk.ko
- ls /dev/simp_blkdev0
- mkfs.ext3 /dev/simp_blk0
- mkdir –p /mnt/blk
- mount /dev/simp_blk0 /mnt/blk
- cp /etc/init.d/* /mnt/blk
- ls /mnt/blk
- umount /mnt/blk
- ls /mnt/blk
3.块设备驱动系统架构
VFS是对各种具体文件系统的一种封装 ,为用户程序访问文件提供统一的接口。
4.系统架构-Cache
当用户发起文件访问请求的时候,首先会到Disk Cache中寻找文件是否被缓存了,如果在cache中,则直接从cache中读取。
如果数据不在缓存中,就必须要到具体的文件系统中读取数据了。
5.Mapping Layer(映射层、FS文件系统)
1. 首先确定文件系统的block size,然后计算所请求的数据包含多少个block。
2. 调用具体文件系统的函数来访问文件的inode结构,确定所请求的数据在磁盘上的地址。
6. Generic Block Layer
Linux内核把把块设备看作是由若干个扇区组成的数据空间。上层的读写请求在通用块层被构造成一个或多个bio结构。
7. I/O Scheduler Layer
I/O调度层负责采用某种算法(如:电梯调度算法)将I/O操作进行排序。
8. I/O Scheduler Layer
电梯调度算法的基本原则:如果电梯现在朝上运动,如果当前楼层的上方和下方都有请求,则先响应所有上方的请求,然后才向下响应下方的请求;如果电梯向下运动,则刚好相反。
9.块设备驱动
在块系统架构的最底层,由块设备驱动根据排序好的请求,对硬件进行数据访问。
10.块设备驱动实例分析
11、简单块设备驱动设计
错误总结:一开始写的时候,编译完加载进内核。直接死机,因为代码有点长。就从逻辑处一点一点注释掉来分析,果然有好多错误。
第一次遇到的问题,内核中常用goto跳转处理错误情况。如果跳转处前面没有return就坑爹了,第一次遇到找了好久
6. Generic Block Layer
Linux内核把把块设备看作是由若干个扇区组成的数据空间。上层的读写请求在通用块层被构造成一个或多个bio结构。
7. I/O Scheduler Layer
I/O调度层负责采用某种算法(如:电梯调度算法)将I/O操作进行排序。
8. I/O Scheduler Layer
电梯调度算法的基本原则:如果电梯现在朝上运动,如果当前楼层的上方和下方都有请求,则先响应所有上方的请求,然后才向下响应下方的请求;如果电梯向下运动,则刚好相反。
9.块设备驱动
在块系统架构的最底层,由块设备驱动根据排序好的请求,对硬件进行数据访问。
10.块设备驱动实例分析
- #include <linux/module.h>
- #include <linux/moduleparam.h>
- #include <linux/init.h>
- #include <linux/sched.h>
- #include <linux/kernel.h> /* printk() */
- #include <linux/slab.h> /* kmalloc() */
- #include <linux/fs.h> /* everything... */
- #include <linux/errno.h> /* error codes */
- #include <linux/timer.h>
- #include <linux/types.h> /* size_t */
- #include <linux/fcntl.h> /* O_ACCMODE */
- #include <linux/hdreg.h> /* HDIO_GETGEO */
- #include <linux/kdev_t.h>
- #include <linux/vmalloc.h>
- #include <linux/genhd.h>
- #include <linux/blkdev.h>
- #include <linux/buffer_head.h> /* invalidate_bdev */
- #include <linux/bio.h>
- MODULE_LICENSE("Dual BSD/GPL");
- static int major = 0;
- static int sect_size = 512;
- static int nsectors = 1024;
- /*
- * The internal representation of our device.
- */
- struct blk_dev{
- int size; /* Device size in sectors */
- u8 *data; /* The data array */
- struct request_queue *queue; /* The device request queue */
- struct gendisk *gd; /* The gendisk structure */
- };
- struct blk_dev *dev;
- /*
- * Handle an I/O request, in sectors.
- */
- static void blk_transfer(struct blk_dev *dev, unsigned long sector,
- unsigned long nsect, char *buffer, int write) //扇区访问函数
- {
- unsigned long offset = sector*sect_size;
- unsigned long nbytes = nsect*sect_size;
- if ((offset + nbytes) > dev->size) {
- printk (KERN_NOTICE "Beyond-end write (%ld %ld)\n", offset, nbytes);
- return;
- }
- if (write)
- memcpy(dev->data + offset, buffer, nbytes); //对内存读写
- else
- memcpy(buffer, dev->data + offset, nbytes);
- }
- /*
- * The simple form of the request function.
- */
- static void blk_request(struct request_queue *q) //实现读写请求处理函数
- {
- struct request *req;
- req = blk_fetch_request(q); //从队列中取出一个请求
- while (req != NULL) {
- struct blk_dev *dev = req->rq_disk->private_data;
- blk_transfer(dev, blk_rq_pos(req), blk_rq_cur_sectors(req), req->buffer, rq_data_dir(req));
-
- if(!__blk_end_request_cur(req, 0)) //判断请求队列是否为空
- {
- req = blk_fetch_request(q); //嵌套处理
- }
- }
- }
- /*
- * The device operations structure.
- */
- static struct block_device_operations blk_ops = {
- .owner = THIS_MODULE,
- };
- /*
- * Set up our internal device.
- */
- static void setup_device()
- {
- /*
- * Get some memory.
- */
- dev->size = nsectors*sect_size; //获取设备大小
- dev->data = vmalloc(dev->size); //获取数据指针
- if (dev->data == NULL) {
- printk (KERN_NOTICE "vmalloc failure.\n");
- return;
- }
- dev->queue = blk_init_queue(blk_request, NULL); //请求队列初始化,blk_request是处理上层传下来的请求的
- if (dev->queue == NULL)
- goto out_vfree;
- blk_queue_logical_block_size(dev->queue, sect_size); //指明扇区大小
- dev->queue->queuedata = dev;
- /*
- * And the gendisk structure.
- */
- dev->gd = alloc_disk(1); //为块设备分配gendisk结构,并初始化
- if (! dev->gd) {
- printk (KERN_NOTICE "alloc_disk failure\n");
- goto out_vfree;
- }
- dev->gd->major = major;
- dev->gd->first_minor = 0;
- dev->gd->fops = &blk_ops;
- dev->gd->queue = dev->queue;
- dev->gd->private_data = dev;
- sprintf (dev->gd->disk_name, "simp_blk%d", 0);
- set_capacity(dev->gd, nsectors*(sect_size/sect_size));
- add_disk(dev->gd); //注册块设备
- return;
- out_vfree:
- if (dev->data)
- vfree(dev->data);
- }
- static int __init blk_init(void)
- {
- /*
- * Get registered.
- */
- major = register_blkdev(major, "blk"); //注册块设备驱动,major若为0会自动分配
- if (major <= 0) {
- printk(KERN_WARNING "blk: unable to get major number\n");
- return -EBUSY;
- }
- dev = kmalloc(sizeof(struct blk_dev), GFP_KERNEL); //分配一个blk_dev空间
- if (dev == NULL)
- goto out_unregister;
- setup_device(); //调用函数
-
- return 0;
- out_unregister:
- unregister_blkdev(major, "sbd");
- return -ENOMEM;
- }
- static void blk_exit(void)
- {
- if (dev->gd) {
- del_gendisk(dev->gd);
- put_disk(dev->gd);
- }
- if (dev->queue)
- blk_cleanup_queue(dev->queue);
- if (dev->data)
- vfree(dev->data);
- unregister_blkdev(major, "blk");
- kfree(dev);
- }
- module_init(blk_init);
- module_exit(blk_exit);
11、简单块设备驱动设计
- #include <linux/module.h>
- #include <linux/init.h>
- #include <linux/errno.h>
- #include <linux/blkdev.h>
- #include <linux/bio.h>
- #include <linux/string.h>
- #include <asm/uaccess.h>
- #include <linux/kernel.h>
- #include <linux/types.h>
- #include <linux/genhd.h>
- MODULE_LICENSE("GPL");
- static int major = 0;
- static int sect_size = 512;
- static int nsectors = 1024;
- struct blk_dev {
- int size;
- u8 *data;
- struct request_queue *queue;
- struct gendisk *gd;
- };
- struct blk_dev *dev;
- static void blk_transfer(struct blk_dev *dev, unsigned long sector, unsigned long nsect,char *buffer, int write)
- {
- unsigned long offset = sector * sect_size;
- unsigned long nbyte = nsect * sect_size;
-
- if((offset + nbyte) > dev->size)
- {
- printk(KERN_NOTICE"Beyond-end write (%ld %ld)\n", offset, nbyte);
- return;
- }
- if(write)
- {
- memcpy(dev->data + offset, buffer, nbyte);
- }
- else
- {
- memcpy(buffer, dev->data + offset, nbyte);
- }
- }
- void blk_request(struct request_queue *q)
- {
- struct request *req;
- req = blk_fetch_request(q);
- while(req != NULL)
- {
- struct blk_dev *dev = req->rq_disk->private_data;
- //处理该请求
- blk_transfer(dev, blk_rq_pos(req), blk_rq_cur_sectors(req), req->buffer, rq_data_dir(req));
-
- if(!__blk_end_request_cur(req, 0))
- req = blk_fetch_request(q);
- }
- }
- static struct block_device_operations blk_ops = {
- .owner = THIS_MODULE,
- };
- static void setup_device(void)
- {
- dev->size = nsectors * sect_size;
- dev->data = vmalloc(dev->size);
- if(dev->data == NULL) {
- printk(KERN_NOTICE "vmalloc failure.\n");
- return;
- }
-
- dev->queue = blk_init_queue(blk_request, NULL);
- if(dev->queue == NULL)
- {
- goto out_vfree;
- }
-
- blk_queue_logical_block_size(dev->queue, sect_size);
- dev->queue->queuedata = dev;
- dev->gd = alloc_disk(1);
- if(!dev->gd)
- {
- printk(KERN_NOTICE "alloc_disk failure\n");
- goto out_vfree;
- }
- dev->gd->major = major;
- dev->gd->first_minor = 0;
- dev->gd->fops = &blk_ops;
- dev->gd->queue = dev->queue;
- dev->gd->private_data = dev;
- sprintf(dev->gd->disk_name, "simp_blk%d", 0);
- set_capacity(dev->gd, nsectors);
- add_disk(dev->gd);
- return;
- out_vfree:
- if(dev->data)
- vfree(dev->data);
- }
- static int __init blk_init(void)
- {
- major = register_blkdev(0, "blk");
- if(major <= 0)
- {
- printk(KERN_WARNING "register blk dev fail!\n");
- return -EBUSY;
- }
- dev = kmalloc(sizeof(struct blk_dev), GFP_KERNEL);
- if(dev == NULL)
- goto out_unregister;
- setup_device();
- return 0;
- out_unregister:
- unregister_blkdev(major, "sbd");
- return -ENOMEM;
- }
- static void blk_exit(void)
- {
- del_gendisk(dev->gd);
- blk_cleanup_queue(dev->queue);
- vfree(dev->data);
- unregister_blkdev(major, "blk");
- kfree(dev);
- }
- module_init(blk_init);
- module_exit(blk_exit);
错误总结:一开始写的时候,编译完加载进内核。直接死机,因为代码有点长。就从逻辑处一点一点注释掉来分析,果然有好多错误。
第一次遇到的问题,内核中常用goto跳转处理错误情况。如果跳转处前面没有return就坑爹了,第一次遇到找了好久
0
上一篇:LCD驱动程序架构和分析
下一篇:MTD系统架构和yaffs2使用、Nandflash驱动设计
相关热门文章
- SHTML是什么_SSI有什么用...
- 查看linux中某个端口(port)...
- 卡尔曼滤波的原理说明...
- shell中字符串操作
- 关于java中的“错误:找不到或...
给主人留下些什么吧!~~
评论热议
阅读全文
0 0
- 块设备驱动系统架构和简单设计
- 块设备驱动设计
- Linux-Flash驱动(3)-简单块设备驱动设计
- Linux-Flash驱动(1)-块设备系统架构
- 块设备驱动架构分析
- FLASH 驱动程序设计 --- 块设备驱动设计
- 块设备和字符设备驱动比较
- 块设备和字符设备驱动比较
- 块设备和字符设备驱动比较
- Linux块设备驱动设计概述
- 简单虚拟块设备驱动流程
- Linux SPI总线和设备驱动架构之一:系统概述
- Linux SPI总线和设备驱动架构之一:系统概述
- Linux SPI总线和设备驱动架构之一:系统概述
- Linux SPI总线和设备驱动架构之一:系统概述
- Linux SPI总线和设备驱动架构之一:系统概述
- Linux SPI总线和设备驱动架构之一:系统概述
- Linux SPI总线和设备驱动架构之一:系统概述
- DM9000驱动网卡编程
- 输入子系统模型解析和原理分析
- drawerlayout侧滑
- 触摸屏驱动分析和编程
- LCD驱动程序架构和分析
- 块设备驱动系统架构和简单设计
- MTD系统架构和yaffs2使用、Nandflash驱动设计
- I2C学习
- 蓝牙搜索
- I2C用户态驱动设计
- SpringBoot的热部署
- I2C自编设备驱动设计
- crontab执行shell脚本和直接运行的结果不一样
- SPI总线介绍和裸机编程分析
原创粉丝点击
热门IT博客
热门问题
老师的惩罚
人脸识别
我在镇武司摸鱼那些年
重生之率土为王
我在大康的咸鱼生活
盘龙之生命进化
天生仙种
凡人之先天五行
春回大明朝
姑娘不必设防,我是瞎子
尚观arm
尚观dba培训
尚观堂
尚观课件
尚观网
尚观php
尚观4g
尚观家园
尚观招聘
尚观居
尚观 骗
尚观吧
尚观培训中心
尚观学费多少
佛山尚观嘉园
尚观嵌入式怎么样
尚观培训费用
尚观培训地址
尚观培训机构
尚观linux培训怎么样
尚观linux培训费用
尚观和达内哪个好
我赢职场 尚观
尚观科技培训怎么样
尚观培训课程
尚观我赢职场
尚观培训学校
尚观培训电话
尚观linux教材
尚观ios培训怎么样
尚观单片机培训
尚观御园户型图
罗村尚观御园
东尚观湖房价
尚观御园二手房
尚观培训 怎么样
尚观dba培训怎么样
尚观linux练习手册
中影飞尚百誉影城沙井
中影飞尚百誉影城 团购
尚怎么读