mremap()

mremap()

扩大/缩小现有内存映射,flags参数还可以控制是否需要页对齐

#define_GNU_SOURCE
	#include<unistd.h>
	#include<sys/mman.h>
	void * mremap(void *old_address, size_t old_size , size_t new_size, int flags.../* void *new_address */);

参数

old_address:旧地址已经被page aligned页对齐
old_sixe:VMB虚拟内存块的大小
new_size:mremap操作后需要的VMB大小
flags:默认情况下,没有足够空间expand,mremap()失败

flag描述
MREMAP_MAYMOVE允许内核将映射重定位到新的虚拟地址
MREMAP_FIXED(Linux 2.3.31)接受第五个参数void * new_address,该参数指定映射必须移动到页面对齐地址page_align。在new_address和new_size指定的地址范围内的所有先前映射都不会被映射。如果指定了MREMAP_FIXED,还必须指定MREMAP_MAYMOVE

new_address:可选择映射地址的位置,也可以NULL,系统返回映射地址。

返回值

成功,返回一个指向新虚拟内存区域的指针。
失败,返回MAP_FAILED。
mremap() uses the Linux page table scheme.
mremap() changes the mapping between virtual addresses and memory pages.
This can be used to implement a very efficient realloc().

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个响应mremap系统调用的内核驱动程序示例: ```c #include <linux/module.h> #include <linux/kernel.h> #include <linux/mm.h> #include <linux/mman.h> #include <linux/fs.h> #include <linux/slab.h> #include <linux/uaccess.h> #include <linux/version.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("mremap driver"); static int my_mremap(struct file *filep, struct vm_area_struct *vma, unsigned long old_addr, unsigned long old_size, unsigned long new_addr, unsigned long new_size) { int ret = 0; struct page *page = NULL; if (new_size > old_size) { // Expand memory mapping unsigned long npages = (new_size - old_size) >> PAGE_SHIFT; while (npages-- > 0) { page = alloc_page(GFP_KERNEL); if (!page) { printk(KERN_ERR "Failed to allocate page\n"); ret = -ENOMEM; goto out; } ret = vm_insert_page(vma, new_addr + old_size, page); if (ret < 0) { printk(KERN_ERR "Failed to insert page\n"); __free_page(page); goto out; } old_size += PAGE_SIZE; } } else if (new_size < old_size) { // Shrink memory mapping unsigned long npages = (old_size - new_size) >> PAGE_SHIFT; while (npages-- > 0) { page = vmalloc_to_page((void *) new_addr + new_size); if (!page) { printk(KERN_ERR "Failed to get page\n"); ret = -EFAULT; goto out; } ret = vm_delete_page(vma, new_addr + new_size, page); if (ret < 0) { printk(KERN_ERR "Failed to delete page\n"); goto out; } __free_page(page); old_size -= PAGE_SIZE; } } // Update memory mapping vma->vm_end = new_addr + new_size; vma->vm_pgoff = new_addr >> PAGE_SHIFT; out: return ret; } static const struct file_operations fops = { .mremap = my_mremap, }; static int __init mremap_init(void) { int ret = 0; ret = register_chrdev(0, "mremap", &fops); if (ret < 0) { printk(KERN_ERR "Failed to register device\n"); goto out; } printk(KERN_INFO "mremap driver loaded\n"); out: return ret; } static void __exit mremap_exit(void) { unregister_chrdev(0, "mremap"); printk(KERN_INFO "mremap driver unloaded\n"); } module_init(mremap_init); module_exit(mremap_exit); ``` 以上代码中,我们定义了一个my_mremap()函数来处理mremap系统调用。在这个函数中,我们首先检查新的映射大小是否比旧的映射大小大,如果是,则分配新的页面,并将它们插入到内存映射区域中。如果新的映射大小比旧的映射大小小,则删除不再需要的页面。 最后,我们更新内存映射区域的大小和页偏移,并返回适当的错误代码。我们将这个函数作为file_operations结构体的mremap字段的值,以便内核可以调用它来处理mremap系统调用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值