设为首页 加入收藏

TOP

Linux驱动开发之块设备初入门(四)
2016-12-12 08:15:24 】 浏览:630
Tags:Linux 驱动 开发 设备 入门
);

该函数撤销函数bvec_kmap_irq()创建的内存映射.
char* bio_kmap_irq(struct bio* bio, unsigned long* flags);

该函数是对bvec_kmap_irq函数的封装,它返回给定的比偶的当前bio_vec入口的映射.
char* __bio_kmap_atomic(struct bio* bio, int i, enum km_type type);

该函数是通过kmap_atomic()获得返回给定bio的第i个缓冲区的虚拟地址.
void __bio_kunmap_atomic(char* addr, enum km_type type);

该函数返还由函数__bio_kmap_atomic()获得的内核虚拟地址给系统.
void bio_get(struct bio* bio);
void bio_put(struct bio* bio);
7、块设备注册与取消


块设备驱动的第一个任务就是将他们自己注册到内核中,其函数原型如下:

☆int register_blkdev(unsigned int major, const char* name);
major参数是块设备要使用的主设备号,name为设备名,它会在/proc/devices中被现实.如果major为0,内核会自动分配一个新的主设备号,并由该函数返回.如果返回值为负值,则说明设备号分派失败.
注销函数是unregister_blkdev(),原型如下:


☆int unreister_blkdev(unsigned int major, const char* name);

这里unreister_blkdev与register_blkdev的参数必须匹配,否则这个函数会返回-EINVAL. 在Linux2.6中,对register_blkdev的调用是可选的.register_blkdev这个调用在Linux2.6中只完成了两件事情:
①如果需要,分派一个主设备号;
②在/proc/devices中创建一个入口.


8、块设备驱动程序编写模板


块驱动中相关相关模块模板


1.块设备驱动的模块加载与卸载


1)块设备驱动的模块加载完成的工作如下:


☆ 分配,初始化请求队列,绑定请求队列和请求函数


☆ 分配,初始化gendisk,给gendisk的major,fops,queue等成员赋值,最后添加gendisk.


☆ 注册块设备驱动.



代码1:使用blk_alloc_queue函数完成块设备驱动的模块加载模板


static int __init xxx_init(void){


//分配gendisk


xxx_disks = alloc_disk(1);


if(!xxx_disks){


goto out;


}


//块设备驱动注册


if(register_blkdev(xxx_MAJOR, "xxx"){


err = -EIO;


goto out;


}


//"请求队列"分配


xxx_queue = blk_alloc_queue(GFP_KERNEL);


if(!xxx_queue){


goto out_queue;


}


blk_queue_make_request(xxx_queue, &xxx_make_request);//绑定"制造请求"函数


blk_queue_hardsect_size(xxx_queue,xxx_blocksize);//告知内核硬件扇区尺寸


//gendisk初始化


xxx_disks->major = xxx_MAJOR;


xxx_disks->first_minor = 0;


xxx_disks->fops = &xxx_fop;


xxx_disks->queue = xxx_queue;


sprintf(xxx_disks->disk_name, "xxx%d", i);


set_capacity(xxx_disks, xxx_size);//设置gendisk容量为xxx_size个扇区大小


add_disk(xxx_disks);


return 0;


out_queue:unregister_blkdev(xxx_MAJOR, "xxx");


out:put_disk(xxx_disks);


blk_cleanup_queue(xxx_queue);


return -ENOMEM;


}


代码2:使用blk_init_queue函数完成块设备驱动的模块加载模板


static int __init xxx_init(void){


//块设备驱动注册


if(register_blkdev(xxx_MAJOR, "xxx"){


err = -EIO;


goto out;


}


//请求队列初始化


xxx_queue = blk_init_queue(xxx_request, xxx_lock);


if(!xxx_queue){


goto out_queue;


}


blk_queue_hardsect_size(xxx_queue, xxx_blocksize);//告知内核硬件扇区大小


//gendisk初始化


xxx_disks->major = xxx_MAJOR;


xxx_disks->first_minor = 0;


xxx_disks->fops = &xxx_fop;


xxx_disks->queue = xxx_queue;


sprintf(xxx_disks->disk_name, "xxx%d", i);


set_capacity(xxx_disks, xxx_size*2);//设置gendisk容量为xxx_size个扇区大小


add_disk(xxx_disks);


return 0;


out_queue:unregister_blkdev(xxx_MAJOR, "xxx");


out:put_disk(xxx_disks);


blk_cleanup_queue(xxx_queue);


return -ENOMEM;


}


2)块设备驱动的模块卸载完成的工作如下:


☆ 清除请求队列.


☆ 删除gendisk和gendisk的引用


☆ 删除对块设备的引用,注销块设备驱动.



代码3:块设备驱动模块卸载函数模板


static void __exit xxx_exit(void){


if(bdev){


invalidate_bdev(xxx_bdev, 1);


blkdev_put(xxx_bdev);


}


del_gendisk(xxx_disks);//删除gendisk


put_disk(xxx_disks);


blk_cleanup_queue(xxx_queue[i]);//清除请求队列


unregister_

首页 上一页 1 2 3 4 5 6 下一页 尾页 4/6/6
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Nand Flash驱动程序编写 下一篇在Linux下的中断方式读取按键驱动..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目