模拟块设备的c++代码,支持压缩

时间: 2023-08-11 11:35:12 浏览: 44
下面是一个简单的模拟块设备的C代码,它支持压缩和解压缩: ```c #include <linux/module.h> #include <linux/blkdev.h> #include <linux/genhd.h> #include <linux/completion.h> #include <linux/errno.h> #include <linux/slab.h> #include <linux/bio.h> #include <linux/crypto.h> #include <crypto/hash.h> #include <crypto/aead.h> #define DEVICE_NAME "mydevice" #define SECTOR_SIZE 512 #define NUM_SECTORS 1024 #define COMPRESSED_SECTOR_SIZE 256 #define MAX_CRYPTO_KEY_SIZE 32 #define MAX_CRYPTO_IV_SIZE 16 struct mydevice { struct request_queue *queue; struct gendisk *disk; unsigned char *data; unsigned char *compressed_data; unsigned char *crypto_key; unsigned char *crypto_iv; struct crypto_aead *aead; struct completion completion; }; static int mydevice_open(struct block_device *bdev, fmode_t mode) { printk(KERN_INFO "mydevice: device opened\n"); return 0; } static void mydevice_release(struct gendisk *disk, fmode_t mode) { printk(KERN_INFO "mydevice: device released\n"); } static int mydevice_transfer(struct mydevice *dev, sector_t sector, unsigned int num_sectors, char *buffer, int write) { unsigned int i; unsigned int offset; unsigned int compressed_size; struct bio *bio; struct bio_vec bvec; struct scatterlist sg; struct crypto_aead *aead; struct aead_request *req; char *src; char *dst; char *iv; char *tag; int err; if (write) { /* Compression */ compressed_size = COMPRESSED_SECTOR_SIZE; err = crypto_aead_setauthsize(dev->aead, COMPRESSED_SECTOR_SIZE); if (err) { printk(KERN_ERR "mydevice: failed to set authsize\n"); return -EIO; } err = crypto_aead_encrypt(dev->aead, dev->crypto_iv, MAX_CRYPTO_IV_SIZE, dev->compressed_data, compressed_size, dev->data + sector * SECTOR_SIZE, num_sectors * SECTOR_SIZE, dev->crypto_key); if (err) { printk(KERN_ERR "mydevice: encryption failed\n"); return -EIO; } src = dev->compressed_data; dst = buffer; } else { /* Decompression */ compressed_size = num_sectors * COMPRESSED_SECTOR_SIZE; err = crypto_aead_setauthsize(dev->aead, COMPRESSED_SECTOR_SIZE); if (err) { printk(KERN_ERR "mydevice: failed to set authsize\n"); return -EIO; } err = crypto_aead_decrypt(dev->aead, dev->crypto_iv, MAX_CRYPTO_IV_SIZE, dev->data + sector * SECTOR_SIZE, compressed_size, dev->compressed_data, COMPRESSED_SECTOR_SIZE, dev->crypto_key); if (err) { printk(KERN_ERR "mydevice: decryption failed\n"); return -EIO; } src = dev->compressed_data; dst = buffer; } /* Scatter-gather I/O */ bio = bio_alloc(GFP_KERNEL, 1); if (!bio) return -EIO; bvec.bv_page = virt_to_page(dst); offset = offset_in_page(dst); bvec.bv_len = min_t(unsigned int, num_sectors * SECTOR_SIZE, PAGE_SIZE - offset); bvec.bv_offset = offset; sg_init_one(&sg, src, compressed_size); bio_add_page(bio, bvec.bv_page, bvec.bv_len, bvec.bv_offset); bio_add_page(bio, &sg, compressed_size, 0); req = aead_request_alloc(dev->aead, GFP_KERNEL); if (!req) { bio_put(bio); return -EIO; } aead_request_set_callback(req, 0, NULL, NULL); aead_request_set_crypt(req, bio, bio, bvec.bv_len, iv); if (write) err = crypto_aead_encrypt(req); else err = crypto_aead_decrypt(req); if (err == -EINPROGRESS) { wait_for_completion(&dev->completion); err = req->base.error; } aead_request_free(req); bio_put(bio); return err ? -EIO : 0; } static void mydevice_request(struct request_queue *queue) { struct request *req; struct mydevice *dev; dev = queue->queuedata; while ((req = blk_fetch_request(queue)) != NULL) { if (req->cmd_type != REQ_TYPE_FS) { printk(KERN_ERR "mydevice: unknown request\n"); __blk_end_request_all(req, -EIO); continue; } if (req->sector + req->current_nr_sectors > NUM_SECTORS) { printk(KERN_ERR "mydevice: invalid request\n"); __blk_end_request_all(req, -EIO); continue; } if (blk_rq_is_passthrough(req)) { printk(KERN_INFO "mydevice: passthrough request\n"); __blk_end_request_all(req, -EIO); continue; } if (blk_rq_map_kern(dev->disk, req, dev->data)) { printk(KERN_ERR "mydevice: rq_map_kern failed\n"); __blk_end_request_all(req, -EIO); continue; } if (mydevice_transfer(dev, blk_rq_pos(req), blk_rq_cur_sectors(req), bio_data(req->bio), rq_data_dir(req))) { printk(KERN_ERR "mydevice: transfer failed\n"); __blk_end_request_all(req, -EIO); continue; } __blk_end_request_all(req, 0); } } static int mydevice_init(void) { int err; struct mydevice *dev; dev = kzalloc(sizeof(struct mydevice), GFP_KERNEL); if (!dev) return -ENOMEM; dev->data = vmalloc(NUM_SECTORS * SECTOR_SIZE); if (!dev->data) { kfree(dev); return -ENOMEM; } dev->compressed_data = vmalloc(NUM_SECTORS * COMPRESSED_SECTOR_SIZE); if (!dev->compressed_data) { vfree(dev->data); kfree(dev); return -ENOMEM; } dev->crypto_key = kzalloc(MAX_CRYPTO_KEY_SIZE, GFP_KERNEL); if (!dev->crypto_key) { vfree(dev->compressed_data); vfree(dev->data); kfree(dev); return -ENOMEM; } dev->crypto_iv = kzalloc(MAX_CRYPTO_IV_SIZE, GFP_KERNEL); if (!dev->crypto_iv) { kfree(dev->crypto_key); vfree(dev->compressed_data); vfree(dev->data); kfree(dev); return -ENOMEM; } err = crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC); if (err) { kfree(dev->crypto_iv); kfree(dev->crypto_key); vfree(dev->compressed_data); vfree(dev->data); kfree(dev); return err; } dev->aead = crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(dev->aead)) { crypto_free_aead(dev->aead); kfree(dev->crypto_iv); kfree(dev->crypto_key); vfree(dev->compressed_data); vfree(dev->data); kfree(dev); return PTR_ERR(dev->aead); } dev->queue = blk_init_queue(mydevice_request, NULL); if (!dev->queue) { crypto_free_aead(dev->aead); kfree(dev->crypto_iv); kfree(dev->crypto_key); vfree(dev->compressed_data); vfree(dev->data); kfree(dev); return -ENOMEM; } blk_queue_logical_block_size(dev->queue, SECTOR_SIZE); blk_queue_physical_block_size(dev->queue, SECTOR_SIZE); dev->queue->queuedata = dev; dev->disk = alloc_disk(1); if (!dev->disk) { blk_cleanup_queue(dev->queue); crypto_free_aead(dev->aead); kfree(dev->crypto_iv); kfree(dev->crypto_key); vfree(dev->compressed_data); vfree(dev->data); kfree(dev); return -ENOMEM; } dev->disk->major = 0; dev->disk->first_minor = 0; dev->disk->fops = &(struct file_operations) { .owner = THIS_MODULE, .open = mydevice_open, .release = mydevice_release, }; dev->disk->queue = dev->queue; dev->disk->private_data = dev; sprintf(dev->disk->disk_name, DEVICE_NAME); set_capacity(dev->disk, NUM_SECTORS); init_completion(&dev->completion); add_disk(dev->disk); printk(KERN_INFO "mydevice: device initialized\n"); return 0; } static void mydevice_exit(void) { struct mydevice *dev; dev = disk->private_data; del_gendisk(dev->disk); put_disk(dev->disk); blk_cleanup_queue(dev->queue); crypto_free_aead(dev->aead); kfree(dev->crypto_iv); kfree(dev->crypto_key); vfree(dev->compressed_data); vfree(dev->data); kfree(dev); printk(KERN_INFO "mydevice: device removed\n"); } module_init(mydevice_init); module_exit(mydevice_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("A simple simulated block device driver with compression and encryption"); ``` 在此示例中,我们使用结构体`mydevice`来保存设备的状态信息。我们为设备分配了内存,并使用`crypto_alloc_aead()`函数为设备分配了一个GCM(AES)加密算法。我们还定义了一个`mydevice_transfer()`函数,该函数在读取和写入请求期间执行压缩和解压缩操作,并使用散列-聚合I/O进行数据传输。我们在`mydevice_request()`函数中处理请求,将它们映射到设备数据上,并使用`mydevice_transfer()`函数执行实际的读取和写入操作。 此外,我们使用`blk_queue_logical_block_size()`和`blk_queue_physical_block_size()`函数设置设备的逻辑和物理块大小,并使用`aead_request_alloc()`函数和`aead_request_free()`函数分配和释放AED请求。我们还使用`blk_init_queue()`函数为设备分配请求队列,并使用`add_disk()`函数将设备添加到系统中。最后,我们在模块初始化函数中注册设备驱动程序,并在模块退出函数中注销它。

相关推荐

最新推荐

recommend-type

emWin5用户手册(中文)

3.1.2 通过 emWin 源代码使用模拟 .........................................................................42 3.1.2.1 目录结构...............................................................................
recommend-type

node-v4.1.0-linux-x64.tar.xz

Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。
recommend-type

基于AT89S52的数字温度计设计说明.docx

基于AT89S52的数字温度计设计说明.docx
recommend-type

HTML+CSS+JS精品网页模板H108.rar

HTML5+CSS+JS精品网页模板,设置导航条、轮翻效果,鼠标滑动效果,自动弹窗,点击事件、链接等功能;适用于大学生期末大作业或公司网页制作。响应式网页,可以根据不同的设备屏幕大小自动调整页面布局; 支持如Dreamweaver、HBuilder、Text 、Vscode 等任意html编辑软件进行编辑修改; 支持包括IE、Firefox、Chrome、Safari主流浏览器浏览; 下载文件解压缩,用Dreamweaver、HBuilder、Text 、Vscode 等任意html编辑软件打开,只需更改源代码中的文字和图片可直接使用。图片的命名和格式需要与原图片的名字和格式一致,其他的无需更改。如碰到HTML5+CSS+JS等专业技术问题,以及需要对应行业的模板等相关源码、模板、资料、教程等,随时联系博主咨询。 网页设计和制作、大学生网页课程设计、期末大作业、毕业设计、网页模板,网页成品源代码等,5000+套Web案例源码,主题涵盖各行各业,关注作者联系获取更多源码; 更多优质网页博文、网页模板移步查阅我的CSDN主页:angella.blog.csdn.net。
recommend-type

node-v6.15.0-linux-armv7l.tar.xz

Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。
recommend-type

zigbee-cluster-library-specification

最新的zigbee-cluster-library-specification说明文档。
recommend-type

管理建模和仿真的文件

管理Boualem Benatallah引用此版本:布阿利姆·贝纳塔拉。管理建模和仿真。约瑟夫-傅立叶大学-格勒诺布尔第一大学,1996年。法语。NNT:电话:00345357HAL ID:电话:00345357https://theses.hal.science/tel-003453572008年12月9日提交HAL是一个多学科的开放存取档案馆,用于存放和传播科学研究论文,无论它们是否被公开。论文可以来自法国或国外的教学和研究机构,也可以来自公共或私人研究中心。L’archive ouverte pluridisciplinaire
recommend-type

实现实时数据湖架构:Kafka与Hive集成

![实现实时数据湖架构:Kafka与Hive集成](https://img-blog.csdnimg.cn/img_convert/10eb2e6972b3b6086286fc64c0b3ee41.jpeg) # 1. 实时数据湖架构概述** 实时数据湖是一种现代数据管理架构,它允许企业以低延迟的方式收集、存储和处理大量数据。与传统数据仓库不同,实时数据湖不依赖于预先定义的模式,而是采用灵活的架构,可以处理各种数据类型和格式。这种架构为企业提供了以下优势: - **实时洞察:**实时数据湖允许企业访问最新的数据,从而做出更明智的决策。 - **数据民主化:**实时数据湖使各种利益相关者都可
recommend-type

spring添加xml配置文件

1. 创建一个新的Spring配置文件,例如"applicationContext.xml"。 2. 在文件头部添加XML命名空间和schema定义,如下所示: ``` <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans
recommend-type

JSBSim Reference Manual

JSBSim参考手册,其中包含JSBSim简介,JSBSim配置文件xml的编写语法,编程手册以及一些应用实例等。其中有部分内容还没有写完,估计有生之年很难看到完整版了,但是内容还是很有参考价值的。