编译块设备驱动程序实例代码sbull遇到的问题
示例代码版本为 2.6.10,编译时的内核版本为2.6.39。内核中许多函数和结构发生变化,造成了编译问题,记录如下:
error: unknown type name ‘request_queue_t’
原因:新版内核中已经没有request_queue_t
的定义
解决方法:可在代码所在文件添加如下定义:
typedef struct request_queue request_queue_t;
error: implicit declaration of function ‘elv_next_request’
原因:在新版本中已经将elv_next_request
用blk_fetch_request
替代。参考网址
解决方法:在相应代码处替换即可。
error: implicit declaration of function ‘blk_fs_request’
原因:在 新版本中已经没有blk_fs_request
函数来判断命令类型。
解决方法:可将判断语句改为:req->cmd_type != REQ_TYPE_FS
error: implicit declaration of function end_request
原因:新版本内核中void end_request(struct request *req, int succeeded)
已不存在。
解决方法:可用void __blk_end_request_all(struct request *rq, int error);
替代。
error: ‘struct request’ has no member named ‘sector’
error: ‘struct request’ has no member named ‘current_nr_sectors’
原因:新版本内核,struct request
中删除了成员sector
和current_nr_sectors
。
解决方法 :采用如下两个函数作相应代换:blk_rq_pos(req)
和blk_rq_cur_sectors(req)
。
error: implicit declaration of function ‘bio_cur_sectors’
原因:新版本内核中 ‘bio_cur_sectors’已经删除。
解决方法:与 2.610和2.6.39代码对照可知,可使用bio_cur_bytes(bio) / KERNEL_SECTOR_SIZE
代替该函数。
error: implicit declaration of function ‘rq_for_each_bio’
原因:新版本中改为了__rq_for_each_bio
。
解决方法:修改之。
error: implicit declaration of function ‘end_that_request_first’
error: implicit declaration of function ‘blkdev_dequeue_request’
error: implicit declaration of function ‘end_that_request_last’
原因:新版本中以上三个函数已经不存在。
解决方法:参考网址代替将
sectors_xferred = sbull_xfer_request(dev, req);
if (! end_that_request_first(req, 1, sectors_xferred)) {
blkdev_dequeue_request(req);
end_that_request_last(req);
}
改为
sbull_xfer_request(dev, req);
if (!__blk_end_request_cur(req, 0)) {
blk_start_request(req);
blk_fetch_request(q);
}
但是在我这边运行不了,以下为亲测可用代码,只是可以正常运行,不知其中原理 :
sbull_xfer_request(dev, req);
__blk_end_request_all(req, 0);
error: too many arguments to function ‘bio_endio’
原因:新版本内核该函数参数改为两个,少了中间那个参数。
解决方法:将中间那个参数去掉。
error: implicit declaration of function ‘blk_queue_hardsect_size’
原因:与 2.610和2.6.39代码对照可知, 可由blk_queue_logical_block_size
代替。
解决方法:修改之。
- 编译之后,有一个warning,
"blk_put_queue" [/root/examples/sbull/sbull.ko] undefined!
原因:新版本未定义该函数,可以使用kobject_put(&(dev->queue)->kobj);
代替。
解决方法:修改之 。
- 修改上述错误后,便可编译成功,但是在安装模块时会提示killed。
- 原因:观察编译时的输出:
即warning: initialization from incompatible pointer type [enabled by default] 警告:从不兼容的指针类型初始化[默认启用]
,有好几个函数指针类型均不匹配。查看新的内核版本代码struct block_device_operations
结构:
struct block_device_operations {
int (*open) (struct block_device *, fmode_t);
int (*release) (struct gendisk *, fmode_t);
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 *);
unsigned int (*check_events) (struct gendisk *disk,
unsigned int clearing);
/* ->media_changed() is DEPRECATED, use ->check_events() instead */
int (*media_changed) (struct gendisk *);
void (*unlock_native_capacity) (struct gendisk *);
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;
};
解决方法:将代码中相关函数改为对应定义的类型,并修改代码。 并且新版本结构中国包含getgeo
函数,从而不再需要在ioctl
函数实现HDIO_GETGEO
命令。具体修改方法可见所附代码。
接下来即可进行测试。
ll /dev | grep sbull
- 分区:
fdisk /dev/sbull
- 格式化,指定文件系统:
mkfs.ext4 /dev/sbull
- 挂载:
mount /dev/sbull /mnt
- 查看磁盘物理分区信息:
cat /proc/partitions
- 查看磁盘分区占用情况:
df -ahT
参考网址:
sbull.c:
/*
* Sample disk driver, from the beginning.
*/
//#include <linux/config.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/kernel.h> /* printk() */
#