内核地址空间分布
文章插图
直接映射区:线性空间中从3G开始最大896M的区间,为直接内存映射区,该区域的线性地址和物理地址存在线性转换关系:线性地址=3G+物理地址 。
动态内存映射区:该区域由内核函数VMALLOC来分配,特点是:线性空间连续,但是对应的物理空间不一定连续 。vmalloc分配的线性地址所对应的物理页可能处于低端内存,也可能处于高端内存 。
永久内存映射区:该区域可访问高端内存 。访问方法是使用alloc_page(_GFP_HIGHMEM)分配高端内存页或者使用kmap函数将分配到的高端内存映射到该区域 。
固定映射区:该区域和4G的顶端只有4k的隔离带,其每个地址项都服务于特定的用途,如ACPI_BASE等 。
进程的地址空间
linux采用虚拟内存管理技术,每一个进程都有一个3G大小的独立的进程地址空间,这个地址空间就是用户空间 。每个进程的用户空间都是完全独立、互不相干的 。进程访问内核空间的方式:系统调用和中断 。
创建进程等进程相关操作都需要分配内存给进程 。这时进程申请和获得的不是物理地址,仅仅是虚拟地址 。
实际的物理内存只有当进程真的去访问新获取的虚拟地址时,才会由“请页机制”产生“缺页”异常,从而进入分配实际页框的程序 。该异常是虚拟内存机制赖以存在的基本保证,它会告诉内核去为进程分配物理页,并建立对应的页表,这之后虚拟地址才实实在在的映射到了物理地址上 。
文章插图
vmalloc和kmalloc区别
1,kmalloc对应于kfree,分配的内存处于3GB~high_memory之间,这段内核空间与物理内存的映射一一对应,可以分配连续的物理内存; vmalloc对应于vfree,分配的内存在VMALLOC_START~4GB之间,分配连续的虚拟内存,但是物理上不一定连续 。
2,vmalloc() 分配的物理地址无需连续,而kmalloc() 确保页在物理上是连续的
3,kmalloc分配内存是基于slab,因此slab的一些特性包括着色,对齐等都具备,性能较好 。物理地址和逻辑地址都是连续的 。
4,最主要的区别是分配大小的问题,比如你需要28个字节,那一定用kmalloc,如果用vmalloc,分配不多次机器就罢工了 。
尽管仅仅在某些情况下才需要物理上连续的内存块,但是,很多内核代码都调用kmalloc(),而不是用vmalloc()获得内存 。这主要是出于性能的考虑 。vmalloc()函数为了把物理上不连续的页面转换为虚拟地址空间上连续的页,必须专门建立页表项 。还有,通过 vmalloc()获得的页必须一个一个的进行映射(因为它们物理上不是连续的),这就会导致比直接内存映射大得多的缓冲区刷新 。因为这些原因,vmalloc()仅在绝对必要时才会使用,最典型的就是为了获得大块内存时,例如,当模块被动态插入到内核中时,就把模块装载到由vmalloc()分配的内存上 。
【一篇读懂Linux内核-内核地址空间分布和进程地址空间】进程地址空间
前边我已经说过了内核是如何管理物理内存 。但事实是内核是操作系统的核心,不光管理本身的内存,还要管理进程的地址空间 。linux操作系统采用虚拟内存技术,所有进程之间以虚拟方式共享内存 。进程地址空间由每个进程中的线性地址区组成,而且更为重要的特点是内核允许进程使用该空间中的地址 。通常情况况下,每个进程都有唯一的地址空间,而且进程地址空间之间彼此互不相干 。但是进程之间也可以选择共享地址空间,这样的进程就叫做线程 。
内核使用内存描述符结构表示进程的地址空间,由结构体mm_struct结构体表示,定义在linux/sched.h中,如下:
struct mm_struct { struct vm_area_struct *mmap; /* list of memory areas */ struct rb_root mm_rb; /* red-black tree of VMAs */ struct vm_area_struct *mmap_cache; /* last used memory area */ unsigned long free_area_cache; /* 1st address space hole */ pgd_t *pgd; /* page global directory */ atomic_t mm_users; /* address space users */ atomic_t mm_count; /* primary usage counter */ int map_count; /* number of memory areas */ struct rw_semaphore mmap_sem; /* memory area semaphore */ spinlock_t page_table_lock; /* page table lock */ struct list_head mmlist; /* list of all mm_structs */ unsigned long start_code; /* start address of code */ unsigned long end_code; /* final address of code */ unsigned long start_data; /* start address of data */ unsigned long end_data; /* final address of data */ unsigned long start_brk; /* start address of heap */ unsigned long brk; /* final address of heap */ unsigned long start_stack; /* start address of stack */ unsigned long arg_start; /* start of arguments */ unsigned long arg_end; /* end of arguments */ unsigned long env_start; /* start of environment */ unsigned long env_end; /* end of environment */ unsigned long rss; /* pages allocated */ unsigned long total_vm; /* total number of pages */ unsigned long locked_vm; /* number of locked pages */ unsigned long def_flags; /* default access flags */ unsigned long cpu_vm_mask; /* lazy TLB switch mask */ unsigned long swap_address; /* last scanned address */ unsigned dumpable:1; /* can this mm core dump? */ int used_hugetlb; /* used hugetlb pages? */ mm_context_t context; /* arch-specific data */ int core_waiters; /* thread core dump waiters */ struct completion *core_startup_done; /* core start completion */ struct completion core_done; /* core end completion */ rwlock_t ioctx_list_lock; /* AIO I/O list lock */ struct kioctx *ioctx_list; /* AIO I/O list */ struct kioctx default_kioctx; /* AIO default I/O context */ };
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Linux系统安全加固的常规操作
- Linux用户管理简单指令
- 一图读懂!揭秘美国NSA专用网络武器“饮茶”
- 我和诸葛亮的作文?围绕诸葛亮写一篇作文
- 小狗学叫是一篇什么故事用了什么修辞手法?小狗学叫是一篇什么故事寓言还是童话
- 魏晨|魏晨\吃饭砸锅\被群嘲后,才读懂俞灏明:娱圈兄弟间从不缺假社交
- 十个唯美古风小故事?古代故事1000字
- 励志正能量短文?正能量的文章青春励志
- 如何快速写好一篇毕业论文?毕业论文方法怎么写
- AMD|开源驱动更新:AMD Linux下也有光追了