简单linux块设备驱动程序
2013-12-02 21:26
471 查看
本文代码参考《LINUX设备驱动程序》第十六章 块设备驱动程序
本文中的“块设备”是一段大小为PAGE_SIZE的内存空间(两个扇区,每个扇区512字节)
功能:向块设备中输入内容,从块设备中读出内容
注:ldd自带块设备驱动源码在2.6.32内核的发行版上编译时会提示很多API未定义,原因是kernel 2.6中block layer API已经变更了很多,本文的程序参考了http://hi.baidu.com/casualfish/item/7931bbb58925fb951846977d,感谢!
代码:
1. sbull.c
2. sbull.h
3. Makefile
4. 验证效果
1)#make
2)#insmod sbull.ko
3)#ls /dev/ //会显示sbull
4)#ls -lh /tmp/test1
-rw-r--r--. 1 root root 4.3k Dec 2 20:47 test1
5)#dd if=/tmp/test1 of=/dev/sbull bs=512 count=2 //将test1中两个扇区的内容输入到块设备sbull中
6)#dd if=/dev/sbull of=/tmp/test2 bs=512 count=2 //将块设备sbull中两个扇区的内容输入到临时文件test2中
7)#ls -lh /tmp/test2
-rw-r--r--. 1 root root 1.0k Dec 2 21:19 test2
8)#vim test2 //test2中的内容跟test1前1024个字节的内容相同
本文中的“块设备”是一段大小为PAGE_SIZE的内存空间(两个扇区,每个扇区512字节)
功能:向块设备中输入内容,从块设备中读出内容
注:ldd自带块设备驱动源码在2.6.32内核的发行版上编译时会提示很多API未定义,原因是kernel 2.6中block layer API已经变更了很多,本文的程序参考了http://hi.baidu.com/casualfish/item/7931bbb58925fb951846977d,感谢!
代码:
1. sbull.c
#include <linux/module.h> #include <linux/moduleparam.h> #include <linux/init.h> #include <linux/sched.h> #include <linux/kernel.h> #include <linux/slab.h> #include <linux/fs.h> #include <linux/errno.h> #include <linux/timer.h> #include <linux/types.h> #include <linux/fcntl.h> #include <linux/hdreg.h> #include <linux/kdev_t.h> #include <linux/vmalloc.h> #include <linux/genhd.h> #include <linux/blkdev.h> #include <linux/buffer_head.h> #include <linux/bio.h> #include "sbull.h" static int sbull_major = SBULL_MAJOR; static int hardsect_size = SBULL_HARDSECT; static int nsectors = 2; module_param(sbull_major, int, 0); module_param(hardsect_size, int, 0); module_param(nsectors, int, 0); struct sbull_dev { int size; u8 *data; short users; spinlock_t lock; struct request_queue *queue; struct gendisk *gd; }; static struct sbull_dev *device = NULL; static void sbull_transfer(struct sbull_dev *dev, unsigned long sector, unsigned long nsect, char *buffer, int write) { unsigned long offset = sector*KERNEL_SECTOR_SIZE; unsigned long nbytes = nsect*KERNEL_SECTOR_SIZE; if ((offset+nbytes) > dev->size) { return; } if (write) { memcpy(dev->data+offset, buffer, nbytes); } else { memcpy(buffer, dev->data+offset, nbytes); } } static int sbull_xfer_bio(struct sbull_dev *dev, struct bio *bio) { int i; struct bio_vec *bvec; sector_t sector = bio->bi_sector; bio_for_each_segment(bvec, bio, i) { char *buffer = __bio_kmap_atomic(bio, i, KM_USER0); sbull_transfer(dev, sector, bio_cur_bytes(bio)>>9, buffer, bio_data_dir(bio) == WRITE); sector += bio_cur_bytes(bio)>>9; __bio_kunmap_atomic(bio, KM_USER0); } return 0; } static int sbull_xfer_request(struct sbull_dev *dev, struct request *req) { struct bio *bio; int nsect = 0; __rq_for_each_bio(bio, req) { sbull_xfer_bio(dev, bio); nsect += bio->bi_size/KERNEL_SECTOR_SIZE; } return nsect; } static void sbull_full_request(struct request_queue *q) { struct request *req; int sectors_xferred; struct sbull_dev *dev = q->queuedata; while((req = blk_fetch_request(q)) != NULL) { if (req->cmd_type != REQ_TYPE_FS) { __blk_end_request_all(req, -EIO); continue; } sectors_xferred = sbull_xfer_request(dev, req); __blk_end_request_cur(req, 0); } } static int sbull_open(struct block_device *device, fmode_t mode) { struct sbull_dev *dev = device->bd_disk->private_data; spin_lock(&dev->lock); dev->users++; spin_unlock(&dev->lock); return 0; } static int sbull_release(struct gendisk *disk, fmode_t mode) { struct sbull_dev *dev = disk->private_data; spin_lock(&dev->lock); dev->users--; spin_unlock(&dev->lock); return 0; } static struct block_device_operations sbull_ops = { .owner = THIS_MODULE, .open = sbull_open, .release = sbull_release, }; static void setup_device(struct sbull_dev *dev) { memset(dev, 0, sizeof(struct sbull_dev)); dev->size = nsectors*hardsect_size; dev->data = vmalloc(dev->size); if (dev->data == NULL) { return; } spin_lock_init(&dev->lock); dev->queue = blk_init_queue(sbull_full_request, &dev->lock); if (dev->queue == NULL) { goto out_vfree; } blk_queue_logical_block_size(dev->queue, hardsect_size); dev->queue->queuedata = dev; dev->gd = alloc_disk(1); if (!dev->gd) { goto out_vfree; } dev->gd->major = sbull_major; dev->gd->first_minor = 0; dev->gd->fops = &sbull_ops; dev->gd->queue = dev->queue; dev->gd->private_data = dev; snprintf(dev->gd->disk_name, 6, "sbull"); set_capacity(dev->gd, nsectors*(hardsect_size/KERNEL_SECTOR_SIZE)); add_disk(dev->gd); return; out_vfree: if (dev->data) { vfree(dev->data); } } static int __init sbull_init(void) { sbull_major = register_blkdev(sbull_major, "sbull"); if (sbull_major <= 0) { return -EBUSY; } device = kmalloc(sizeof(struct sbull_dev), GFP_KERNEL); if (device == NULL) { goto out_unregister; } setup_device(device); return 0; out_unregister: unregister_blkdev(sbull_major, "sbull"); return -ENOMEM; } static void sbull_exit(void) { struct sbull_dev *dev = device; 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(sbull_major, "sbull"); kfree(device); } module_init(sbull_init); module_exit(sbull_exit); MODULE_LICENSE("GPL");
2. sbull.h
#ifndef _SBULL_H #define _SBULL_H #define SBULL_MAJOR 0 #define SBULL_HARDSECT 512 #define KERNEL_SECTOR_SIZE 512 #endif
3. Makefile
obj-m += sbull.o CURRENT_PATH:=$(shell pwd) LINUX_KERNEL:=$(shell uname -r) LINUX_KERNEL_PATH:=/usr/src/kernels/$(LINUX_KERNEL) all: make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules clean: make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean
4. 验证效果
1)#make
2)#insmod sbull.ko
3)#ls /dev/ //会显示sbull
4)#ls -lh /tmp/test1
-rw-r--r--. 1 root root 4.3k Dec 2 20:47 test1
5)#dd if=/tmp/test1 of=/dev/sbull bs=512 count=2 //将test1中两个扇区的内容输入到块设备sbull中
6)#dd if=/dev/sbull of=/tmp/test2 bs=512 count=2 //将块设备sbull中两个扇区的内容输入到临时文件test2中
7)#ls -lh /tmp/test2
-rw-r--r--. 1 root root 1.0k Dec 2 21:19 test2
8)#vim test2 //test2中的内容跟test1前1024个字节的内容相同
相关文章推荐
- linux设备驱动程序之简单字符设备驱动
- Linux驱动USB驱动程序之USB设备驱动程序1简单编写
- 最简单的字符设备驱动程序
- linux简单的字符设备驱动程序
- Linux输入设备简单驱动程序编写练习(2014-8-27)
- linux 设备驱动程序编写--最简单的hellomod
- 驱动程序学习(二)一个简单的字符型设备驱动函数
- Linux字符设备驱动程序的一个简单示例(转)
- 简单字符设备驱动程序分析(一)
- linux块设备驱动程序分析之 nor flash驱动分析 以及使用内存模拟 nor flash
- LINUX设备驱动程序笔记(一)设备驱动程序简单介绍
- Linux设备驱动程序的简单Makefile
- linux设备驱动程序之简单字符设备驱动
- 简单字符设备驱动程序
- Linux设备驱动--简单字符设备驱动程序
- 20150216简单的Linux字符设备驱动程序
- 简单字符设备驱动程序
- Linux设备驱动程序——简单字符设备驱动程序
- Linux字符设备驱动程序的一个简单示例
- Linux字符设备驱动程序的一个简单示例