块设备驱动实例

news/2024/11/7 18:30:36/

摘自:http://my.oschina.net/heiden/blog/194505
将ldd3(linxu device driver 3)中块设备驱动部分的代码在redhat6.3下编译时,会出现很多问题,主要是由于ldd3示例代码使用的内核版本较低(2.6.10版本),

对于块设备子系统,很多接口都已经发生了改变,

主要有如下变化:

1,elv_next_request已删除,使用如下方式从请求队列中获取请求

struct request *req;req =  blk_fetch_request (q);while(req != NULL){struct sbull_dev *dev = req->rq_disk->private_data;if(req->cmd_type != REQ_TYPE_FS){printk(KERN_NOTICE "Skip non-fs request\n");blk_end_request_all(req,-EIO);continue;}sbull_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 = NULL;}}

其中blk_peek_request从队列中获取请求,但是不会从队列中删除该请求。

从队列中删除请求需要调用blk_start_request(),blk_fetch_request 相当于调用blk_peek_request,和blk_start_request()

具体参考:http://lwn.net/Articles/333620/,

2,end_request,改成了blk_end_request_all

3,现在不能直接获取request结构的sector和current_nr_sector;而是通过函数blk_rq_pos和blk_rq_cur_sectors获得,所以将对用两处改为:

sbull_transfer(dev, blk_rq_pos(req), blk_rq_cur_sectors(req), req->buffer, rq_data_dir(req));

4,bio_endio参数过多

5,blk_queue_hardsect_size定义已删除,使用blk_queue_logical_block_size(dev->queue, hardsect_size);

6,block_device_operation接口已经发生了非常大的变化

新接口如下:(该接口包含getgeo函数,从而不再需要在ioctl函数实现HDIO_GETGEO命令)

struct block_device_operations {int (*open) (struct block_device *, fmode_t);int (*release) (struct gendisk *, fmode_t);int (*locked_ioctl) (struct block_device *, fmode_t, unsigned, unsigned long);int (*ioctl) (struct block_device *, fmode_t, unsigned, unsigned long);int (*compat_ioctl) (struct block_device *, fmode_t, unsigned, unsigned long);int (*direct_access) (struct block_device *, sector_t,void **, unsigned long *);int (*media_changed) (struct gendisk *);unsigned long long (*set_capacity) (struct gendisk *,unsigned long long);int (*revalidate_disk) (struct gendisk *);int (*getgeo)(struct block_device *, struct hd_geometry *);/* this callback is with swap_lock and sometimes page table lock held */void (*swap_slot_free_notify) (struct block_device *, unsigned long);struct module *owner;};

编译通过后就可以使用该设备,例如

创建分区:

fdisk /dev/sbulla

创建文件系统

mkfs.ext3 /dev/sbulla1

修改后的代码如下:

#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> /* 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 sbull_major = 0;module_param(sbull_major,int,0);static int hardsect_size =512;module_param(hardsect_size,int,0);static int nsectors = 1024;module_param(nsectors,int,0);static int ndevices = 4;module_param(ndevices,int,0);enum {RM_SIMPLE = 0,RM_FULL = 1,RM_NOQUEUE = 2,};static int request_mode = RM_SIMPLE;module_param(request_mode, int, 0);#define SBULL_MINORS 16#define KERNEL_SECTOR_SIZE 512#define INVALIDATE_DELAY 30*HZstruct sbull_dev{int size;u8 *data;short users;short media_change;spinlock_t lock;struct request_queue *queue;struct gendisk *gd;struct timer_list timer;};static struct sbull_dev *Devices = 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) {printk(KERN_NOTICE "Beyond-end write (%ld %ld)\n",offset,nbytes);return;}if(write)memcpy(dev->data + offset,buffer,nbytes);elsememcpy(buffer,dev->data + offset,nbytes);}static void sbull_request(struct request_queue *q){struct request *req;req = blk_fetch_request(q);while(req != NULL){struct sbull_dev *dev = req->rq_disk->private_data;if(req->cmd_type != REQ_TYPE_FS){printk(KERN_NOTICE "Skip non-fs request\n");blk_end_request_all(req,-EIO);continue;}sbull_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 = NULL;}}}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)/KERNEL_SECTOR_SIZE,buffer,bio_data_dir(bio) == WRITE);sector += bio_cur_bytes(bio)/KERNEL_SECTOR_SIZE;__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;struct sbull_dev *dev = q->queuedata;req = blk_fetch_request(q);while(req  != NULL){if(req->cmd_type != REQ_TYPE_FS){printk(KERN_NOTICE "Skip non-fs request\n");blk_end_request_all(req,-EIO);continue;}sbull_xfer_request(dev,req);if(!blk_end_request_cur(req,0)){req = NULL;}}}static int sbull_make_request(struct request_queue *q,struct bio *bio){struct sbull_dev *dev = q->queuedata;int status;status = sbull_xfer_bio(dev,bio);bio_endio(bio,status);return 0;}static int sbull_open(struct block_device *bd, fmode_t mode){struct sbull_dev *dev = bd->bd_disk->private_data;del_timer_sync(&dev->timer);spin_lock(&dev->lock);if(!dev->users)check_disk_change(bd);dev->users++;spin_unlock(&dev->lock);return 0;}static int sbull_release(struct gendisk *gd, fmode_t mode){struct sbull_dev *dev = gd->private_data;spin_lock(&dev->lock);dev->users--;if(!dev->users){dev->timer.expires = jiffies + INVALIDATE_DELAY;add_timer(&dev->timer);}spin_unlock(&dev->lock);return 0;}int sbull_media_change(struct gendisk *gd){struct sbull_dev *dev = gd->private_data;return dev->media_change;}int sbull_revalidate(struct gendisk *gd){struct sbull_dev *dev = gd->private_data;if(dev->media_change){dev->media_change = 0;memset(dev->data,0,dev->size);}return 0;}void sbull_invalidate(unsigned long ldev){struct sbull_dev *dev = (struct sbull_dev *)ldev;spin_lock(&dev->lock);if(dev->users || !dev->data)printk (KERN_WARNING "sbull: timer sanity check failed\n");elsedev->media_change = 1;spin_unlock(&dev->lock);}int sbull_ioctl(struct block_device *bd, fmode_t mode, unsigned cmd, unsigned long arg){return 0;}static int sbull_getgeo(struct block_device *bd, struct hd_geometry *geo){long size;struct sbull_dev *dev = bd->bd_disk->private_data;size = dev->size *(hardsect_size / KERNEL_SECTOR_SIZE);geo->cylinders = (size & ~0x3f) >> 6;geo->heads = 4;geo->sectors = 16;geo->start = 4;return 0;}static struct block_device_operations sbull_ops = {.owner = THIS_MODULE,.open = sbull_open,.release = sbull_release,.media_changed = sbull_media_change,.revalidate_disk = sbull_revalidate,.ioctl = sbull_ioctl,.getgeo = sbull_getgeo};static void setup_device(struct sbull_dev *dev,int which){printk(KERN_WARNING "sbull: step into into setup_device\n");memset(dev,0,sizeof(struct sbull_dev));dev->size = nsectors * hardsect_size;dev->data = vmalloc(dev->size);if(dev->data == NULL){printk(KERN_NOTICE "vmalloc failure\n");return;}spin_lock_init(&dev->lock);init_timer(&dev->timer);dev->timer.data = (unsigned long)dev;dev->timer.function = sbull_invalidate;switch(request_mode){case RM_NOQUEUE:dev->queue = blk_alloc_queue(GFP_KERNEL);if(dev->queue == NULL)goto out_vfree;blk_queue_make_request(dev->queue,sbull_make_request);break;case RM_FULL:dev->queue = blk_init_queue(sbull_full_request,&dev->lock);if(dev->queue == NULL)goto out_vfree;break;case RM_SIMPLE:dev->queue = blk_init_queue(sbull_request,&dev->lock);if(dev->queue == NULL)goto out_vfree;break;default:printk(KERN_NOTICE "Bad request mode %d, using simple\n", request_mode);}blk_queue_logical_block_size(dev->queue,hardsect_size);dev->queue->queuedata = dev;dev->gd = alloc_disk(SBULL_MINORS);if(!dev->gd){printk(KERN_NOTICE "alloc_disk failure\n");goto out_vfree;}dev->gd->major = sbull_major;dev->gd->first_minor = which * SBULL_MINORS;dev->gd->fops = &sbull_ops;dev->gd->queue = dev->queue;dev->gd->private_data = dev;snprintf(dev->gd->disk_name,32,"sbull%c",which + 'a');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){int i;printk(KERN_WARNING "sbull: start init\n");sbull_major = register_blkdev(sbull_major,"sbull");if (sbull_major <= 0) {printk(KERN_WARNING "sbull: unable to get major number\n");return -EBUSY;}printk(KERN_WARNING "sbull: start kmalloc\n");Devices = kmalloc(ndevices * sizeof(struct sbull_dev),GFP_KERNEL);if(Devices == NULL)goto out_unregister;printk(KERN_WARNING "sbull: start setup_device\n");for(i = 0; i < ndevices; i++)setup_device(Devices + i,i);return 0;out_unregister:unregister_blkdev(sbull_major,"sbd");return -ENOMEM;}static void sbull_exit(void){int i;for (i = 0; i < ndevices; i++) {struct sbull_dev *dev = Devices + i;del_timer_sync(&dev->timer);if (dev->gd) {del_gendisk(dev->gd);put_disk(dev->gd);}if (dev->queue) {if (request_mode == RM_NOQUEUE)kobject_put(&(dev->queue)->kobj);elseblk_cleanup_queue(dev->queue);}if (dev->data)vfree(dev->data);}unregister_blkdev(sbull_major, "sbull");kfree(Devices);}module_init(sbull_init);module_exit(sbull_exit);

其原始版本
摘自:http://www.linuxidc.com/Linux/2010-12/30792.htm

/** Sample disk driver, from the beginning.*/#include <linux/autoconf.h>
#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 sbull_major = 0;
module_param(sbull_major, int, 0);
static int hardsect_size = 512;
module_param(hardsect_size, int, 0);
static int nsectors = 25600;    /* How big the drive is */
module_param(nsectors, int, 0);
static int ndevices = 1;
module_param(ndevices, int, 0);/** The different "request modes" we can use.*/
enum {RM_SIMPLE  = 0,    /* The extra-simple request function */RM_FULL    = 1,    /* The full-blown version */RM_NOQUEUE = 2,    /* Use make_request */
};
//static int request_mode = RM_FULL;
static int request_mode = RM_SIMPLE;
//static int request_mode = RM_SIMPLE;
module_param(request_mode, int, 0);/** Minor number and partition management.*/
#define SBULL_MINORS    16
#define MINOR_SHIFT    4
#define DEVNUM(kdevnum)    (MINOR(kdev_t_to_nr(kdevnum)) >> MINOR_SHIFT/** We can tweak our hardware sector size, but the kernel talks to us* in terms of small sectors, always.*/
#define KERNEL_SECTOR_SIZE    512/** After this much idle time, the driver will simulate a media change.*/
#define INVALIDATE_DELAY    60*HZ/** The internal representation of our device.*/
struct sbull_dev {int size;                       /* Device size in sectors */// data 是本程序模拟的块设备,是一片连续的虚拟空间// 在初始化函数里分配的虚拟地址连续的内存空间u8 *data;                       /* The data array */short users;                    /* How many users */short media_change;             /* Flag a media change? */spinlock_t lock;                /* For mutual exclusion */struct request_queue *queue;    /* The device request queue */struct gendisk *gd;             /* The gendisk structure */struct timer_list timer;        /* For simulated media changes */
};static struct sbull_dev *Devices = NULL;/** Handle an I/O request.*/
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) {      // 判断输入参数是否合法,是否超出边界printk (KERN_NOTICE "Beyond-end write (%ld %ld)\n", offset, nbytes);return;}// 实际的读写操作// 由于本程序是用一片连续的内存空间模拟块设备// 所以这里对硬件(内存空间)的读写操作,就是复制内存// 在具体点,就是下面的memcpy// 具体的项目,需修改为具体的接口函数if (write)// 写memcpy(dev->data + offset, buffer, nbytes);else// 读memcpy(buffer, dev->data + offset, nbytes);
}/*The simple form of the request function.*/static void sbull_request(struct request_queue *q)
{struct request *req;// 服务完队列上的所有请求while ((req = elv_next_request(q)) != NULL) {  // elv_next_request :从队列上去一个下来struct sbull_dev *dev = req->rq_disk->private_data;if (! blk_fs_request(req)) {printk (KERN_NOTICE "Skip non-fs request\n");end_request(req, 0);continue;}sbull_transfer(dev, req->sector, req->current_nr_sectors,req->buffer, rq_data_dir(req));end_request(req, 1);}
}/** Transfer a single BIO.*/
static int sbull_xfer_bio(struct sbull_dev *dev, struct bio *bio)
{int i;struct bio_vec *bvec;sector_t sector = bio->bi_sector;/* Do each segment independently. */bio_for_each_segment(bvec, bio, i) {char *buffer = __bio_kmap_atomic(bio, i, KM_USER0);sbull_transfer(dev, sector, bio_cur_sectors(bio),buffer, bio_data_dir(bio) == WRITE);sector += bio_cur_sectors(bio);__bio_kunmap_atomic(bio, KM_USER0);}return 0; /* Always "succeed" */
}/** Transfer a full request.*/
static int sbull_xfer_request(struct sbull_dev *dev, struct request *req)
{struct bio *bio;int nsect = 0;// steps through each bio that makes up a request.// 遍历__rq_for_each_bio(bio, req) {sbull_xfer_bio(dev, bio);nsect += bio->bi_size/KERNEL_SECTOR_SIZE;}return nsect;
}/** Smarter request function that "handles clustering".*/
static void sbull_full_request(struct request_queue *q)
{struct request *req;int sectors_xferred;struct sbull_dev *dev = q->queuedata;printk("<0>""in %s\n",__FUNCTION__);while ((req = elv_next_request(q)) != NULL) {if (! blk_fs_request(req)) {printk (KERN_NOTICE "Skip non-fs request\n");end_request(req, 0);continue;}sectors_xferred = sbull_xfer_request(dev, req);__blk_end_request(req,0,sectors_xferred<<9);//add by lht for 2.6.27}
}//The direct make request version
static int sbull_make_request(struct request_queue *q, struct bio *bio)
{struct sbull_dev *dev = q->queuedata;int status;status = sbull_xfer_bio(dev, bio);//bio_endio(bio, bio->bi_size, status);bio_endio(bio, status);return 0;
}/** Open and close.*/static int sbull_open(struct inode *inode, struct file *filp)
{struct sbull_dev *dev = inode->i_bdev->bd_disk->private_data;//printk("<0>" "fdfjdlksjfdlkj\n");    del_timer_sync(&dev->timer);filp->private_data = dev;spin_lock(&dev->lock);if (! dev->users) check_disk_change(inode->i_bdev);dev->users++;spin_unlock(&dev->lock);return 0;
}static int sbull_release(struct inode *inode, struct file *filp)
{struct sbull_dev *dev = inode->i_bdev->bd_disk->private_data;spin_lock(&dev->lock);dev->users--;if (!dev->users) {dev->timer.expires = jiffies + INVALIDATE_DELAY;add_timer(&dev->timer);}spin_unlock(&dev->lock);return 0;
}/** Look for a (simulated) media change.*/
int sbull_media_changed(struct gendisk *gd)
{struct sbull_dev *dev = gd->private_data;return dev->media_change;
}/** Revalidate.  WE DO NOT TAKE THE LOCK HERE, for fear of deadlocking* with open.  That needs to be reevaluated.*/
int sbull_revalidate(struct gendisk *gd)
{struct sbull_dev *dev = gd->private_data;if (dev->media_change) {dev->media_change = 0;memset (dev->data, 0, dev->size);}return 0;
}/** The "invalidate" function runs out of the device timer; it sets* a flag to simulate the removal of the media.*/
void sbull_invalidate(unsigned long ldev)
{struct sbull_dev *dev = (struct sbull_dev *) ldev;spin_lock(&dev->lock);if (dev->users || !dev->data) printk (KERN_WARNING "sbull: timer sanity check failed\n");elsedev->media_change = 1;spin_unlock(&dev->lock);
}/** The ioctl() implementation*/int sbull_ioctl (struct inode *inode, struct file *filp,unsigned int cmd, unsigned long arg)
{long size;struct hd_geometry geo;struct sbull_dev *dev = filp->private_data;switch(cmd) {case HDIO_GETGEO:/** Get geometry: since we are a virtual device, we have to make* up something plausible.  So we claim 16 sectors, four heads,* and calculate the corresponding number of cylinders.  We set the* start of data at sector four.*///printk("<0>""-------------size=%d\n",size);/****************for early version************///size = dev->size*(hardsect_size/KERNEL_SECTOR_SIZE);//printk("<0>""-------------size=%d\n",size);//geo.cylinders = (size & ~0x3f) >> 6;//geo.cylinders=2000;//geo.heads = 4;//geo.sectors = 16;//geo.sectors=2560;//geo.start = 0;//if (copy_to_user((void __user *) arg, &geo, sizeof(geo)))//    return -EFAULT;return 0;}return -ENOTTY; /* unknown command */
}static int sbull_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{unsigned long size;struct sbull_dev *pdev = bdev->bd_disk->private_data;size = pdev->size;geo->cylinders = (size & ~0x3f) >> 6;geo->heads    = 4;geo->sectors = 16;geo->start = 0;return 0;
}/** The device operations structure.*/
static struct block_device_operations sbull_ops = {.owner           = THIS_MODULE,.open              = sbull_open,.release      = sbull_release,.media_changed   = sbull_media_changed,.revalidate_disk = sbull_revalidate,.ioctl             = sbull_ioctl,.getgeo            = sbull_getgeo,
};/** Set up our internal device.*/
// 初始化设备结构体 static struct sbull_dev *Devices中的成员
static void setup_device(struct sbull_dev *dev, int which)
{/** Get some memory.*/memset (dev, 0, sizeof (struct sbull_dev));dev->size = nsectors*hardsect_size;// 分配一片虚拟地址连续的内存空间,作为块设备。dev->data = vmalloc(dev->size);   if (dev->data == NULL) {printk (KERN_NOTICE "vmalloc failure.\n");return;}spin_lock_init(&dev->lock);/** The timer which "invalidates" the device.*/init_timer(&dev->timer);dev->timer.data = (unsigned long) dev;dev->timer.function = sbull_invalidate;/** The I/O queue, depending on whether we are using our own* make_request function or not.*/switch (request_mode) {case RM_NOQUEUE:dev->queue = blk_alloc_queue(GFP_KERNEL);if (dev->queue == NULL)goto out_vfree;blk_queue_make_request(dev->queue, sbull_make_request);break;case RM_FULL:dev->queue = blk_init_queue(sbull_full_request, &dev->lock);if (dev->queue == NULL)goto out_vfree;break;default:printk(KERN_NOTICE "Bad request mode %d, using simple\n", request_mode);/* fall into.. */case RM_SIMPLE:dev->queue = blk_init_queue(sbull_request, &dev->lock);if (dev->queue == NULL)goto out_vfree;break;}blk_queue_hardsect_size(dev->queue, hardsect_size);dev->queue->queuedata = dev;/** And the gendisk structure.*/dev->gd = alloc_disk(SBULL_MINORS);if (! dev->gd) {printk (KERN_NOTICE "alloc_disk failure\n");goto out_vfree;}dev->gd->major = sbull_major;dev->gd->first_minor = which*SBULL_MINORS;dev->gd->fops = &sbull_ops;dev->gd->queue = dev->queue;dev->gd->private_data = dev;snprintf (dev->gd->disk_name, 32, "sbull%c", which + 'a');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)
{int i;/** Get registered.*///    printk("<0>" "add by lht\n");sbull_major = register_blkdev(sbull_major, "sbull");if (sbull_major <= 0) {printk(KERN_WARNING "sbull: unable to get major number\n");return -EBUSY;}/** Allocate the device array, and initialize each one.*/Devices = kmalloc(ndevices*sizeof (struct sbull_dev), GFP_KERNEL);if (Devices == NULL)goto out_unregister;for (i = 0; i < ndevices; i++) setup_device(Devices + i, i);return 0;out_unregister:unregister_blkdev(sbull_major, "sbd");return -ENOMEM;
}static void sbull_exit(void)
{int i;for (i = 0; i < ndevices; i++) {struct sbull_dev *dev = Devices + i;del_timer_sync(&dev->timer);if (dev->gd) {del_gendisk(dev->gd);put_disk(dev->gd);}if (dev->queue) {if (request_mode == RM_NOQUEUE)//    blk_put_queue(dev->queue);kobject_put(&(dev->queue)->kobj);elseblk_cleanup_queue(dev->queue);}if (dev->data)vfree(dev->data);}unregister_blkdev(sbull_major, "sbull");kfree(Devices);
}module_init(sbull_init);
module_exit(sbull_exit);测试方法:# Makefile
ifeq ($(KERNELRELEASE),)#KERNELDIR ?= /home/lht/kernel2.6/linux-2.6.14KERNELDIR ?= /lib/modules/$(shell uname -r)/build M=$(PWD) modules
PWD := $(shell pwd)modules:$(MAKE) -C $(KERNELDIR) M=$(PWD) modulesmodules_install:$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_installclean:rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions.PHONY: modules modules_install cleanelseobj-m := sbull.o
endif将模块插入内核(2.6.27root@linuxidc:/source/workplace/test/sbull_linuxidc# insmod sbull.ko 
用lsmod查看模块是否成功插入内核
root@linuxidc:/source/workplace/test/sbull_linuxidc# lsmod | grep sbu
sbull                  13452  0 
出现上面结果,说明成功了
用ls查看/dev下是否有sbull设备
root@linuxidc:/source/workplace/test/sbull_linuxidc# ls /dev | grep sbu
sbulla
出现上面结果,说明有了,如果没有,用命令
mknod /dev/sbulla b 254 0
手动创建
至此,已经有一个块设备了
下面用fdisk对虚拟块设备分区
root@linuxidc:/source/workplace/test/sbull_linuxidc# fdisk /dev/sbulla 
Device contains neither a valid DOS partition table, nor Sun, SGI or OSF disklabel
Building a new DOS disklabel with disk identifier 0x14d0973f.
Changes will remain in memory only, until you decide to write them.
After that, of course, the previous content won't be recoverable.Warning: invalid flag 0x0000 of partition table 4 will be corrected by w(rite)Command (m for help): n        这里选择n,新建
Command actione   extendedp   primary partition (1-4)  这里选p,主分区
p
Partition number (1-4): 1   这里选1,第一个分区
First cylinder (1-400, default 1): 1
Last cylinder, +cylinders or +size{K,M,G} (1-400, default 400): 
Using default value 400Command (m for help): w  这里选w,保存并推出
The partition table has been altered!Calling ioctl() to re-read partition table.
Syncing disks.
接着将其格式化为ext2root@linuxidc:/source/workplace/test/sbull_linuxidc# mkfs.ext2 /dev/sbulla1 
mke2fs 1.41.3 (12-Oct-2008)
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
3200 inodes, 12792 blocks
639 blocks (5.00%) reserved for the super user
First data block=1
Maximum filesystem blocks=13107200
2 block groups
8192 blocks per group, 8192 fragments per group
1600 inodes per group
Superblock backups stored on blocks: 8193Writing inode tables: done                            
Writing superblocks and filesystem accounting information: doneThis filesystem will be automatically checked every 29 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.
新建一个文件夹,作为此处模拟的块设备的挂载点
root@linuxidc:/source/workplace/test/sbull_linuxidc# ls /mnt/
hgfs  initrd
root@linuxidc:/source/workplace/test/sbull_linuxidc# mkdir /mnt/sbulla1
挂载
root@linuxidc:/source/workplace/test/sbull_linuxidc# mount /dev/sbulla1 /mnt/sbulla1
进入目录,新建一个文件,测试一下
root@linuxidc:/source/workplace/test/sbull_linuxidc# cd /mnt/sbulla1/
root@linuxidc:/mnt/sbulla1# ls
lost+found
root@linuxidc:/mnt/sbulla1# echo hi > hello.c
root@linuxidc:/mnt/sbulla1# ls
hello.c  lost+found
root@linuxidc:/mnt/sbulla1# cat hello.c 
hi
root@linuxidc:/mnt/sbulla1#

bio 代表一个IO 请求
request 是bio 提交给IO调度器产生的数据,一个request 中放着顺序排列的bio
当设备提交bio 给IO调度器时,IO调度器可能会插入bio,或者生成新的request
request_queue代表着一个物理设备,顺序的放着request


http://www.ppmy.cn/news/335238.html

相关文章

快麦KM100s打印机驱动 v1.0.0.4官方版

名称&#xff1a;快麦KM100s打印机驱动 v1.0.0.4官方版 版本&#xff1a;1.0.0.4 大小&#xff1a;857KB 软件语言&#xff1a;简体中文 软件授权&#xff1a;免费版 应用平台&#xff1a;Win7/Win8/Win2003/WinXP 快麦KM100打印机官方驱动程序最新版&#xff0c;驱动安装后…

在CLion中构建Windows内核WDM驱动

在CLion中构建Windows内核WDM驱动 1、安装好CLion&#xff0c;VS2019&#xff0c;WDK 过程略 2、下载FindWDK.cmake 该文件来自于github/SergiusTheBest # Redistribution and use is allowed under the OSI-approved 3-clause BSD license. # Copyright (c) 2018 Sergey …

驱动开发:配置Visual Studio驱动开发环境

在正式开始驱动开发之前&#xff0c;需要自行搭建驱动开发的必要环境&#xff0c;首先我们需要安装Visual Studio 2013这款功能强大的程序开发工具&#xff0c;在课件内请双击ISO文件并运行内部的vs_ultimate.exe安装包&#xff0c;Visual Studio的安装非常的简单&#xff0c;您…

电源变频驱动主要有哪2种驱动方式?原理如何

将变频器的主电路连接到电源线后&#xff0c;要控制电动机的运行&#xff0c;必须将外围连接的控制电路连接到相应的端子&#xff0c;并将变频器的启动模式参数设置为外部操作模式。 电源变频驱动主要有哪2种驱动方式&#xff1f;原理如何 变频器控制电动机的运行&#xff0c;共…

VS2017、2019驱动WDF开发环境找不到头文件#include <ntddk.h>

一大堆的头文件找不到报错可能是因为SDK与WDF不对应&#xff0c; 例如&#xff1a; 先看自己的WDF安装了什么版本的&#xff0c;下图是没装&#xff11;&#xff10;.&#xff10;.&#xff11;&#xff19;&#xff10;&#xff14;&#xff11;.&#xff10;WDF的文件夹 如…

windows下WDK创建免费的测试证书,并签名windows驱动文件(附带测试效果)

windows下WDK创建免费的测试证书&#xff0c;并签名windows驱动文件&#xff08;附带测试效果&#xff09; 编译了一个sys驱动文件&#xff0c;每次加载使用都需要手动开启【禁用强制驱动签名】&#xff0c;很麻烦&#xff0c;用测试证书签名&#xff0c;再也不用这么麻烦了&a…

支付宝正式发布黑莓版客户端

5月28日&#xff0c;支付宝对外表示&#xff0c;该公司已正式发布黑莓版客户端&#xff0c;目前支付宝无线支付单项日交易笔数已接近20万笔。 据了解&#xff0c;自去年6月开始&#xff0c;支付宝已经相继发布了基于Windows Mobile、塞班、iPhone、J2ME、黑莓等手机系统平台的软…

黑莓bb10和Android,黑莓BB10.3.1更新发布,全面支持安卓应用

目前在国内市场仍拥有小众粉丝的黑莓手机日前发布了最新的BB10系统更新版本&#xff0c;最新版本来到了10.3.1&#xff0c;该版本刚刚发布&#xff0c;将陆续开始通过官方更新、亚马逊等应用商店开始推送。 据悉黑莓BB10.3.1版本最大的改变是增加了BlackBerry Blend的特性&…