块设备
1.块设备(磁盘、SD卡)
2.网络设备
3.字符设备
这三种设备驱动程序。
块设备与字符设备区别:
1.读取数据单位不同,块设备固定。
2.块设备随机访问、字符设备顺序访问。
VFS:虚拟文件系统。是对各种具体文件系统的一种封装,为用户程序访问文件提供统一的接口。
Disk cache:当用户发起文件访问请求的时候,首先到Disk Cache中寻找文件是否被缓存,如果是,则直接从cache中读取。如果不在,就必须到具体文件系统中读取数据。
Mapping layer:1、首先确定文件系统的block size,然后计算所请求的数据包含多少个blk。
2.调用具体文件系统的函数访问文件的inode结构,确定所请求的数据在磁盘上的地址。
Generic Block layer:linux内核把块设备看做由若干个扇区组成的数据空间,上层的读写请求在通用块层被构造成一个或多个bio结构。
I/O调度算法
设备描述:linux内核使用struct gendisk (定义于<linux/genhd.h>)来描述块设备
二、注册设备:
使用add_disk函数向内核注册块设备驱动
三、设备操作:块设备使用一个结构体:struct block_device_operations:
四、I/O请求:
在linux内核中、使用struct request来表示等待处理的块设备I/O请求。
请求队列:
简单的讲,请求队列就是I/O请求request所形成的队列,在linux内核中struct request_queue描述。
初始化请求队列:
编写好程序后,先编译:make
加载驱动:insmod simple-blk.ko
检查驱动:在dev下查看: ls /dev/simp_blkdev -l
块设备驱动测试:
1.insmod simple-blk.ko
2.ls /dev/simp_blkdev
3.mkfs.ext3 /dev/simp_blkdev //格式化
4.mkdir -p /mnt/blk
5.mount /dev/simp_blkdev /mnt/blk/ //挂载
6.cp /etc/init.d/* /mnt/blk/ //写数据
7.ls /mnt/blk
8. umount /mnt/blk
9. ls /mnt/blk
第二种方法:
BIO:1个struct bio代表1次块设备I/O请求,IO调度器可将连续的bio合并成1个请求 struct request。
不用kernel提供的_make_request()(包含I/O调度算法),自己写请求队列并绑定函数方法:
static int __init simp_blkdev_init(void) { int ret; simp_blkdev_queue = blk_alloc_queue(GFP_KERNEL); if (!simp_blkdev_queue) { ret = -ENOMEM; goto err_alloc_queue; } blk_queue_make_request(simp_blkdev_queue, simp_blkdev_make_request); simp_blkdev_disk = alloc_disk(1); if (!simp_blkdev_disk) { ret = -ENOMEM; goto err_alloc_disk; } strcpy(simp_blkdev_disk->disk_name, SIMP_BLKDEV_DISKNAME); simp_blkdev_disk->major = SIMP_BLKDEV_DEVICEMAJOR; simp_blkdev_disk->first_minor = 0; simp_blkdev_disk->fops = &simp_blkdev_fops; simp_blkdev_disk->queue = simp_blkdev_queue; set_capacity(simp_blkdev_disk, SIMP_BLKDEV_BYTES>>9); add_disk(simp_blkdev_disk); return 0; err_alloc_disk: blk_cleanup_queue(simp_blkdev_queue); err_alloc_queue: return ret; }