全部博文(16)
分类: LINUX
2012-03-28 12:35:47
①struct block_device_operations在2.6.28开始发生很大变化在上找到的英文说明The block driver API has changed considerably, with the inode and file parameters being removed from most block device operations. The new API looks like this:struct block_device_operations {
int (*open) (struct block_device *bdev, fmode_t mode);
int (*release) (struct gendisk *gd, fmode_t mode);
int (*locked_ioctl) (struct block_device *bdev, fmode_t mode,
unsigned cmd, unsigned long arg);
int (*ioctl) (struct block_device *bdev, fmode_t mode,
unsigned cmd, unsigned long arg);
int (*compat_ioctl) (struct block_device *bdev, fmode_t mode,
unsigned cmd, unsigned long arg);
int (*direct_access) (struct block_device *bdev, sector_t sector,
void **kaddr, unsigned long *pfn);
int (*media_changed) (struct gendisk *gd);
int (*revalidate_disk) (struct gendisk *gd);
int (*getgeo)(struct block_device *bdev, struct hd_geometry *geo);
struct module *owner;
};
The new prototypes do away with the file and inode structure pointers which were passed in previous kernels. Note that the ioctl() method is now called without the big kernel lock; code needing BKL protection must explicitly define a locked_ioctl() function instead.在2.6.28之前的struct 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,
- void **, unsigned long *);
- int (*media_changed) (struct gendisk *);
- int (*revalidate_disk) (struct gendisk *);
- int (*getgeo)(struct block_device *, struct hd_geometry *);
- struct module *owner;
- };
从2.6.28开始的struct block_device_operations结构体
点击(此处)折叠或打开
- 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 *);
- int (*revalidate_disk) (struct gendisk *);
- int (*getgeo)(struct block_device *, struct hd_geometry *);
- struct module *owner;
- };
参数的变化比较大,具体使用要去看源码了②blk_queue_make_request(struct request_queue *, make_request_fn *)在内核2.6.33.20该函数中后面的make_request_fn函数参数的原型与书中2.6.4也有所不同书中(2.6.4)的定义typedef int (make_request_fn) (request_queue_t *q, struct bio *bio);typedef struct request_queue request_queue_t;2.6.33.20中的定义typedef int (make_request_fn) (struct request_queue *q, struct bio *bio);可以看到其实原型内容是没有变化的,只是先前版本对request_queue进行了新的类型声明(没有看更深层的代码,不知道内部是否有变化)实例中make_request_fn函数中要用到bio_endio()和bio_io_error()两个函数其在2.6.33.20原型与在书中原型的参数个数不同在书中(2.6.4)两个函数的原型void bio_endio(struct bio *bio, unsigned int bytes_done, int error)
#define bio_io_error(bio, bytes) bio_endio((bio), (bytes), -EIO)在2.6.33.20两个函数的原型void bio_endio(struct bio *bio, int error)
#define bio_io_error(bio) bio_endio((bio), -EIO)
①书中实例代码(2.6.4)
点击(此处)折叠或打开
- #include <linux/init.h>
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/fs.h>
- #include <linux/errno.h>
- #include <linux/types.h>
- #include <linux/fcntl.h>
- #include <linux/vmalloc.h>
- #include <linux/hdreg.h>
- #include <linux/blkdev.h>
- #include <linux/blkpg.h>
- #include <asm/uaccess.h>
- #define VRD_DEV_NAME "vrd"
- #define VRD_DEV_MAJOR "240"
- #define VRD_MAX_DEVICE 2
- #define VRD_SECTOR_SIZE 512
- #define VRD_SIZE (4*1024*1024)
- #define VRD_SECTOR_TOTAL (VRD_SIZE/VRD_SECTOR_SIZE)
- typedef struct{
- unsigned char *data;
- struct request_queue *queue;
- struct gendisk *gd;
- }vrd_device;
- static char *vdisk[VRD_MAX_DEVICE];
- static vrd_device device[VRD_MAX_DEVICE];
- static int vrd_make_request(request_queue_t *q,struct bio *bio)
- {
- vrd_device *pdevice;
- char *pVHDDDdata;
- char *pBuffer;
- struct bio_vec *bvec;
- int i;
- if(((bio-bi_sector*VRD_SECTOR_SIZE)+bio->bi_size)>VRD_SIZE){
- goto fail;
- }
- pdevice=(vrd_device *)bio->bi_bdev->bd_disk->private_data;
- pVHDDDdata=private_data+(bio->bi_sector*VRD_SECTOR_SIZE);
- bio_for_each_segment(bvec,bio,i)
- {
- pBuffer=kmap(bev->bv_page)+bvec->bv_offset;
- switch(bio_data_dir(bio))
- {
- case READA:
- case READ:memcpy(pBuffer,pVHDDData,bvec->bv_len);break;
- case WRITE:memcpy(pVHDDData,pBuffer,bvec->bv_len);break;
- default:kunmap(bvec->bv_page);goto fail;
- }
- kunmap(bvec->bv_page);
- pVHDDData+=bvec->bv_len;
- }
- bio_endio(bio,bio->bi_size,0);
- return 0;
- fail:
- bio_io_error(bio,bio->bi_size);
- return 0;
- }
- int vrd_open(struct inode *inode,struct file *filp)
- {
- return 0;
- }
- int vrd_release(struct inode *inode,struct file *filp)
- {
- return 0;
- }
- int vrd_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg)
- {
- return -ENOTTY;
- }
- static struct block_device_operations vrd_fops={
- .owner=THIS_MODULE,
- .open=vrd_open,
- .release=vrd_release,
- .ioctl=vrd_ioctl,
- };
- int vrd_init(void)
- {
- int lp;
- vdisk[0]=vmalloc(VRD_SIZE);
- vdisk[1]=vmalloc(VRD_SIZE);
- register_blkdev(VRD_DEV_MAJOR,VRD_DEV_NAME);
- for(lp=0;lp<VRD_MAX_DEVICE;lp++){
- device[lp].data=vdisk[lp];
- device[lp].gd=alloc_disk(1);
- device[lp].queue=blk_alloc_queue(GFP_KERNEL);
- blk_queue_make_request(device[lp].queue,&vrd_make_request);
- device[lp].gd->major=VRD_DEV_MAJOR;
- device[lp].gd->first_minor=lp;
- device[lp].gd->fops=&vrd_fops;
- device[lp].gd->queue=device[lp].queue;
- device[lp].gd->private_data=&device[lp];
- sprintf(device[lp].gd->disk_name,"vrd%c",'a'+lp);
- set_capacity(device[lp].gd,VRD_SECTOR_TOTAL);
- add_disk(device[lp].gd);
- }
- return 0;
- }
- void vrd_exit(void)
- {
- int lp;
- for(lp=0;lp<VRD_MAX_DEVICE;lp++){
- del_gendisk(device[lp].gd);
- put_disk(device[lp].gd);
- }
- unregister_blkdev(VRD_DEV_MAJOR,VRD_DEV_NAME);
- vfree(vdisk[0]);
- vfree(vdisk[1]);
- }
- module_init(vrd_init);
- module_exit(vrd_exit);
- MODULE_LICENSE("Dual BSD/GPL");
②修改后实例代码后面的mkrequest.c
点击(此处)折叠或打开
点击(此处)折叠或打开
点击(此处)折叠或打开