vmalloc_init

 

/* linux/mm/vmalloc.c*/
struct vmap_area {
    unsigned long va_start;
    unsigned long va_end;
    unsigned long flags;
    struct rb_node rb_node;        /* address sorted rbtree */
    struct list_head list;        /* address sorted list */
    struct list_head purge_list;    /* "lazy purge" list */
    void *private;
    struct rcu_head rcu_head;
};

/*
* 显示通过vmalloc分配的内存区域,个vm_struct通过红黑树管理,
* 红黑树的各节点显示为vmap_area结构体
*/
struct vm_struct {
    struct vm_struct    *next;
    void            *addr;
    unsigned long        size;
    unsigned long        flags;
    struct page        **pages;
    unsigned int        nr_pages;
    unsigned long        phys_addr;
    void            *caller;
};

struct vmap_block_queue {
    spinlock_t lock;
    struct list_head free;
    struct list_head dirty;
    unsigned int nr_dirty;
};
struct vmap_block {
    spinlock_t lock;
    struct vmap_area *va;
    struct vmap_block_queue *vbq;
    unsigned long free, dirty;
    DECLARE_BITMAP(alloc_map, VMAP_BBMAP_BITS);
    DECLARE_BITMAP(dirty_map, VMAP_BBMAP_BITS);
    union {
        struct list_head free_list;
        struct rcu_head rcu_head;
    };
};
/* Queue of free and dirty vmap blocks, for allocation and flushing purposes */
static DEFINE_PER_CPU(struct vmap_block_queue, vmap_block_queue);

void __init vmalloc_init(void)

/*以下代码应该在 中执行*/
int rc;
rc = pcpu_embed_first_chunk(PERCPU_MODULE_RESERVE,PERCPU_DYNAMIC_RESERVE,
        PAGE_SIZE,NULL,pcpu_dfl_fc_alloc,pcpu_dfl_fc_free);  
if (rc<0)  
    panic("Failed to initialize percpu areas.");

/* 
* linux/mm/vmalloc.c
* 全局变量vmlist的初始化流程
*/
struct vm_struct *vmlist;
asmlinkage void __init start_kernel(void)
    -->setup_per_cpu_areas();
        -->ssize_t __init pcpu_embed_first_chunk(size_t static_size, size_t reserved_size,
                      ssize_t dyn_size, ssize_t unit_size)
            -->size_t __init pcpu_setup_first_chunk(pcpu_get_page_fn_t get_page_fn,
                     size_t static_size, size_t reserved_size,
                     ssize_t dyn_size, ssize_t unit_size,
                     void *base_addr,
                     pcpu_populate_pte_fn_t populate_pte_fn)
                -->void __init vm_area_register_early(struct vm_struct *vm, size_t align)
                    -->vmlist = vm;

/*建立vm_struct与vmap_area的关联*/
#define RB_ROOT    (struct rb_root) { NULL, }
static struct rb_root vmap_area_root = RB_ROOT;
static LIST_HEAD(vmap_area_list);

static void __insert_vmap_area(struct vmap_area *va)

 

转载于:https://www.cnblogs.com/yangjiguang/p/8343945.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
是的,vmalloc_user() 和 remap_pfn_range() 函数可以一起使用,用于将 vmalloc_user() 分配的内核虚拟空间映射到用户空间。 vmalloc_user() 函数用于分配内核虚拟空间,它和 vmalloc() 函数类似,但是它还会将分配的内存空间以 uncache 映射的方式映射到用户空间。这种映射方式可以确保用户空间对内存的读写操作与 CPU 缓存无关,从而避免出现缓存不一致的问题,通常用于需要频繁进行 I/O 操作的设备驱动程序中。 remap_pfn_range() 函数用于将物理页面映射到用户空间。在使用 vmalloc_user() 函数分配内存空间后,我们可以使用 vmalloc_to_pfn() 函数将虚拟地址转换成物理地址的页帧号,然后通过 remap_pfn_range() 函数将这些物理页面映射到用户空间。 下面是一个简单的示例代码,演示了如何使用 vmalloc_user() 和 remap_pfn_range() 函数一起使用: ```c #include <linux/module.h> #include <linux/init.h> #include <linux/slab.h> #include <linux/vmalloc.h> #include <linux/mm.h> #define PAGE_SIZE 4096 static int __init my_module_init(void) { void *virt_addr; unsigned long phys_addr; int i; // 分配 4 个页面大小的内存空间 virt_addr = vmalloc_user(4 * PAGE_SIZE); if (!virt_addr) { printk(KERN_ERR "Failed to allocate memory\n"); return -ENOMEM; } // 获取物理地址并打印 for (i = 0; i < 4; i++) { phys_addr = vmalloc_to_pfn(virt_addr + i * PAGE_SIZE) << PAGE_SHIFT; printk(KERN_INFO "Page %d: virt_addr=%p, phys_addr=%lx\n", i, virt_addr + i * PAGE_SIZE, phys_addr); } // 将页面映射到用户空间 if (remap_pfn_range(vma, vma->vm_start, vmalloc_to_pfn(virt_addr), 4 * PAGE_SIZE, vma->vm_page_prot)) { printk(KERN_ERR "Failed to map memory\n"); vfree(virt_addr); return -EAGAIN; } return 0; } static void __exit my_module_exit(void) { // 释放内存空间 vfree(virt_addr); } module_init(my_module_init); module_exit(my_module_exit); MODULE_LICENSE("GPL"); ``` 以上代码中,我们首先使用 vmalloc_user() 函数分配 4 个页面大小的内存空间。然后,我们使用 vmalloc_to_pfn() 函数获取每个页面的物理地址,并打印出来。最后,我们使用 remap_pfn_range() 函数将这些页面映射到用户空间。 需要注意的是,在实际使用中,我们需要根据具体的应用场景和需求来选择是否使用 uncache 映射,以及如何正确地使用 vmalloc_user() 和 remap_pfn_range() 函数。同时,在释放内存空间时,我们应该使用 vfree() 函数来释放 vmalloc_user() 分配的内存空间。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值