Linux块设备驱动代码例子
时间: 2024-01-21 13:46:24 浏览: 82
以下是一个简单的Linux块设备驱动代码示例,它实现了一个虚拟块设备:
```c
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/blkdev.h>
#include <linux/version.h>
#define VIRTUAL_DEVICE_NAME "virtblk"
#define VIRTUAL_DEVICE_SIZE (1024 * 1024) // 1MB
#define SECTOR_SIZE 512
static int major_num = 0;
static struct request_queue *req_queue = NULL;
static struct gendisk *virtblk_disk = NULL;
static unsigned char *virtblk_data = NULL;
static void virtblk_request(struct request_queue *q)
{
struct request *req = NULL;
int err = 0;
while ((req = blk_fetch_request(q)) != NULL) {
if (req->cmd_type != REQ_TYPE_FS) {
printk(KERN_WARNING "virtblk: Unsupported command\n");
err = -EIO;
goto error;
}
switch (rq_data_dir(req)) {
case READ:
memcpy(req->buffer, virtblk_data + (req->sector << 9), req->current_nr_sectors * SECTOR_SIZE);
break;
case WRITE:
memcpy(virtblk_data + (req->sector << 9), req->buffer, req->current_nr_sectors * SECTOR_SIZE);
break;
default:
printk(KERN_WARNING "virtblk: Unsupported data direction\n");
err = -EIO;
goto error;
}
if (!__blk_end_request_cur(req, err))
req = NULL;
}
return;
error:
printk(KERN_ERR "virtblk: Request error\n");
__blk_end_request_cur(req, err);
while ((req = blk_fetch_request(q)) != NULL)
__blk_end_request_cur(req, -EIO);
}
static struct block_device_operations virtblk_fops = {
.owner = THIS_MODULE,
};
static int __init virtblk_init(void)
{
virtblk_data = kzalloc(VIRTUAL_DEVICE_SIZE, GFP_KERNEL);
if (!virtblk_data) {
printk(KERN_ERR "virtblk: Memory allocation failed\n");
return -ENOMEM;
}
major_num = register_blkdev(0, VIRTUAL_DEVICE_NAME);
if (major_num <= 0) {
printk(KERN_ERR "virtblk: Unable to register block device\n");
kfree(virtblk_data);
return -EBUSY;
}
req_queue = blk_init_queue(virtblk_request, NULL);
if (!req_queue) {
printk(KERN_ERR "virtblk: Request queue creation failed\n");
unregister_blkdev(major_num, VIRTUAL_DEVICE_NAME);
kfree(virtblk_data);
return -ENOMEM;
}
blk_queue_logical_block_size(req_queue, SECTOR_SIZE);
virtblk_disk = alloc_disk(1);
if (!virtblk_disk) {
printk(KERN_ERR "virtblk: Disk allocation failed\n");
blk_cleanup_queue(req_queue);
unregister_blkdev(major_num, VIRTUAL_DEVICE_NAME);
kfree(virtblk_data);
return -ENOMEM;
}
virtblk_disk->major = major_num;
virtblk_disk->first_minor = 0;
virtblk_disk->fops = &virtblk_fops;
virtblk_disk->queue = req_queue;
sprintf(virtblk_disk->disk_name, "virtblk%c", 'a' + virtblk_disk->first_minor);
set_capacity(virtblk_disk, VIRTUAL_DEVICE_SIZE / SECTOR_SIZE);
add_disk(virtblk_disk);
printk(KERN_INFO "virtblk: Virtual block device registered\n");
return 0;
}
static void __exit virtblk_exit(void)
{
del_gendisk(virtblk_disk);
put_disk(virtblk_disk);
blk_cleanup_queue(req_queue);
unregister_blkdev(major_num, VIRTUAL_DEVICE_NAME);
kfree(virtblk_data);
printk(KERN_INFO "virtblk: Virtual block device unregistered\n");
}
module_init(virtblk_init);
module_exit(virtblk_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("Virtual block device driver");
```
阅读全文
相关推荐















