linux 块设备驱动程序之helloworld

#include <linux/module.h>

#include <linux/blkdev.h>

#include <linux/genhd.h>

#include <linux/fs.h>

#include <linux/slab.h>

#include <linux/vmalloc.h>

#define DEVICE_NAME "blk_test"

#define DEVICE_SIZE (1024 * 1024 * 10) // 10MB

#define SECTOR_SHIFT 9

#define SECTOR_SIZE (1 << SECTOR_SHIFT)

static struct blk_test_device {

struct gendisk *disk;

struct request_queue *queue;

void *data;

sector_t capacity;

} test_dev;

static void blk_test_request( struct request_queue *q )

{

struct request *rq;

printk(KERN_INFO "blk_test: blk_test_request\n");

while ((rq = blk_fetch_request(q)) != NULL) {

sector_t sector = blk_rq_pos(rq);

struct req_iterator iter;

struct bio_vec bvec;

if (blk_rq_pos(rq) + blk_rq_sectors(rq) > test_dev.capacity) {

__blk_end_request_all(rq, -EIO);

continue;

}

if (rq->cmd_type != REQ_TYPE_FS) {

__blk_end_request_all(rq, -EIO);

continue;

}

// 使用兼容的请求段迭代方式

rq_for_each_segment(bvec, rq, iter) {

void *buffer = page_address(bvec.bv_page) + bvec.bv_offset;

unsigned long len = bvec.bv_len;

if (rq_data_dir(rq) == READ)

memcpy(buffer, test_dev.data + (sector << SECTOR_SHIFT), len);

else

memcpy(test_dev.data + (sector << SECTOR_SHIFT), buffer, len);

sector += (len >> SECTOR_SHIFT);

}

__blk_end_request_all(rq, 0);

}

}

static int blk_test_open(struct block_device *bdev, fmode_t mode)

{

printk(KERN_INFO "blk_test: device opened\n");

return 0;

}

static void blk_test_release(struct gendisk *disk, fmode_t mode)

{

printk(KERN_INFO "blk_test: device released\n");

}

static const struct block_device_operations blk_test_fops = {

.owner = THIS_MODULE,

.open = blk_test_open,

.release = blk_test_release,

};

static int __init blk_test_init(void)

{

int ret = 0;

// 分配内存空间

test_dev.data = vmalloc(DEVICE_SIZE);

if (!test_dev.data) {

printk(KERN_ERR "blk_test: failed to allocate memory\n");

return -ENOMEM;

}

memset(test_dev.data, 0, DEVICE_SIZE);

test_dev.capacity = DEVICE_SIZE >> SECTOR_SHIFT;

// 初始化请求队列

test_dev.queue = blk_init_queue(blk_test_request, NULL);

if (!test_dev.queue) {

ret = -ENOMEM;

goto out_vfree;

}

blk_queue_logical_block_size(test_dev.queue, SECTOR_SIZE);

blk_queue_physical_block_size(test_dev.queue, SECTOR_SIZE);

// 分配gendisk结构

test_dev.disk = alloc_disk(1);

if (!test_dev.disk) {

ret = -ENOMEM;

goto out_cleanup_queue;

}

// 动态分配主设备号

int major = register_blkdev(0, "blk_test");

test_dev.disk->major = major;

// 设置gendisk属性

// test_dev.disk->major = 0; // 动态分配主设备号

test_dev.disk->first_minor = 0;

test_dev.disk->fops = &blk_test_fops;

test_dev.disk->private_data = &test_dev;

test_dev.disk->queue = test_dev.queue;

snprintf(test_dev.disk->disk_name, DISK_NAME_LEN, DEVICE_NAME);

//snprintf(test_dev.disk->disk_name, DISK_NAME_LEN, "blk_test_%d", unique_id);

// 设置容量

set_capacity(test_dev.disk, test_dev.capacity);

// 添加磁盘到系统

add_disk(test_dev.disk);

printk(KERN_INFO "\n\n\n************************************************\n");

printk(KERN_INFO "blk_test: module loaded, device size: %lu sectors\n",

(unsigned long)test_dev.capacity);

return 0;

out_cleanup_queue:

blk_cleanup_queue(test_dev.queue);

out_vfree:

vfree(test_dev.data);

return ret;

}

//# 写入测试

//dd if=/dev/zero of=/dev/blk_test bs=1M count=5

//# 读取测试

//dd if=/dev/blk_test of=/dev/null bs=1M count=5

static void __exit blk_test_exit(void)

{

if (test_dev.disk) {

del_gendisk(test_dev.disk);

put_disk(test_dev.disk);

}

if (test_dev.queue) {

blk_cleanup_queue(test_dev.queue);

}

if (test_dev.data) {

vfree(test_dev.data);

}

unregister_blkdev(test_dev.disk->major, "blk_test"); // 新增

}

//module_init(blk_test_init);

late_initcall(blk_test_init);

module_exit(blk_test_exit);

MODULE_LICENSE("GPL");

MODULE_AUTHOR("Test");

MODULE_DESCRIPTION("Block device test module for IO queue simulation");

相关推荐
hhhjhl36 分钟前
Protobuf.js 跨端三方库仓颉适配全流程
javascript·网络·udp
琥珀.1 小时前
mysql中json数组转列表查询
linux·运维·服务器
dawnsky.liu1 小时前
在 RHEL 中使用 goose 实现远程主机管理
linux·运维·ai
ITxiaobing20232 小时前
中国公司海外广告投放的 IP 地址库选型:从“查归属”到“验真实”的工程视角
网络·网络协议·tcp/ip
KKKlucifer2 小时前
运营商非结构化文档安全管控体系建设实践
大数据·网络·安全
Linux运维技术栈3 小时前
CVE-2026-91403 高危漏洞修复:Rocky Linux 9 多版本 JDK 环境清理实操
java·linux·运维
云边云科技_云网融合4 小时前
连锁门店组网怎么做?SD-WAN 多分支组网的架构选型、部署与成本结构
服务器·数据库·php
网络小江4 小时前
组网第35课:静态路由——下一跳、出接口、默认路由、浮动静态与黑洞路由
服务器·网络·默认路由·黑洞路由·浮动静态路由
acrel75 小时前
医院用电隐患治理与节能降耗及智慧能源平台应用
网络·数据库
slongzhang_5 小时前
linux 递归删除源码文件|递归删除目录下 *.js,但排除 *.min.js
linux·开发语言·javascript