2.2 详细设计:
2.2.1 函数加载模块具体功能实现:
首先,对块设备驱动程序进行注册, int register_blkdev(unsigned int major,const
char *name);,获得主设备号。
然后,对 sbull_dev 数据结构进行内存的分配和初始化工作:
Devices = kmalloc(sizeof(struct sbull_dev),GFP_KERNEL);
memset(Devices,0,sizeof(struct sbull_dev));
Devices->size = nsectors * hardsect_size;
Devices->data = vmalloc(Devices->size);
memset(Devices->data,0,Devices->size);
对自旋锁进行分配和初始化:
spin_lock_init(&Devices->lock);
分配请求队列:
Devices->queue = blk_init_queue(sbull_request,&Devices->lock);
设置扇区大小:
blk_queue_logical_block_size(Devices->queue, hardsect_size);
分配、初始化及安装相应的 gendisk 结构
Devices->gd = alloc_disk(1);
Devices->gd->major = sbull_major;
Devices->gd->first_minor = 0;
Devices->gd->fops = &sbull_ops;
Devices->gd->queue = Devices->queue;
Devices->gd->private_data = Devices;
strcpy(Devices->gd->disk_name,"sbull0");
set_capacity(Devices->gd,nsectors * (hardsect_size / KERN_SECTOR_SIZE));
最后,调用 add_disk()结束设置过程。
add_disk(Devices->gd);
2.2.2 函数操作模块的具体实现:
在块设备驱动程序中,主要有设备的打开、IO 控制与释放三个基本操作。而这三
个操作是通过 block_device_operations 结构中的 sbull_open、sbull_release、sbull_ioctl
实现的。
其中,因为此次的块设备驱动程序只是虚拟内存,而没有操作实际的硬件,在打
开和、释放操作中并没有具体的功能。
而在 IO 控制中,主要实现了得到主设备号、得到扇区总数、得到块设备大小的操
作功能。
在 IO 控制中,首先对参数进行了检测:
//检测命令的有效性
if(_IOC_TYPE(cmd) != SBULL_IOC_MAGIC)
{
return -EINVAL;
}