【Linux内核】虚拟地址空间布局架构
虛擬地址空間布局架構(Linux內核學習)
1.Linux內核整體架構及子系統
內核對下管理硬件,對上通過運行時庫對應用提供服務
用戶空間
使用malloc()分配內存通過free()釋放內存
內核空間
虛擬進程負責從進程的虛擬地址空間分配虛擬頁,sys_brk來擴大或收縮堆,sys_mmap負責在內存映射區分配虛擬頁,
頁分配器負責分配物理頁
不連續內存分配器提供分配內存的接口vmalloc和釋放內存接口vfree,申請連續的物理頁的成功率比較低,可以申請不連續的物理頁,r然后映射到連續的虛擬頁,及虛擬地址連續而物理地址不連續
內存控制組來控制進程占用的資源,當內存碎片化的時候,找不到連續的物理頁,內存碎片整理通過遷移方式得到連續的物理頁,當內存不足的時候,負責回收物理頁
硬件
MMU1包含一個頁表緩存,保存最近使用過的頁表映射,避免每次都要查詢虛擬頁對應的物理頁,解決了CPU執行速度與內存速度不匹配的問題
來個例子:
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <unistd.h> constexpr int MAX = 1024;int main(int argc, char const *argv[]) {/*sbrk函數在內核的管理下將虛擬地址空間映射到內存,供malloc函數使用。*/void *p = sbrk(0);void *old = p;p = (int *)sbrk(MAX * MAX);if (p == (void *)(-1)){std::cout << "sbrk error\n";exit(0);}printf("old:%p\tp=%p\n", p, old);void *new_ = sbrk(0);printf("new:%p", new_);sbrk(-MAX * MAX);return 0; }輸出
old:0x55555557a000 p=0x55555557a000 new:0x55555567a000可見成功分配了新的內存.
那我們如何更加具體的看到是否獲取了內存呢?
更改代碼如下:
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <unistd.h> constexpr int MAX = 1024;int main(int argc, char const *argv[]) {/*sbrk函數在內核的管理下將虛擬地址空間映射到內存,供malloc函數使用。*/void *p = sbrk(0);void *old = p;p = (int *)sbrk(MAX * MAX);if (p == (void *)(-1)){std::cout << "sbrk error\n";exit(0);}printf("old:%p\tp=%p\n", p, old);void *new_ = sbrk(0);printf("new:%p\n", new_);printf("pid= %d\n", getpid());while (true){}sbrk(-MAX * MAX);return 0; }運行,不要停止
輸出為:
old:0x55555557a000 p=0x55555557a000 new:0x55555567a000 pid= 1193打開新終端輸入cat /proc/1193/maps(一切皆文件)查看內存情況:
后續就不在演示了(懶)
2.虛擬內存空間內存架構
linux-4.4.4\arch\arm64\include\asm\memory.h
#define TASK_SIZE_64 (UL(1) << VA_BITS)//64位操作系統 //VA_BITS 編譯內核的時候選擇的虛擬地址的位數#ifdef CONFIG_COMPAT #define TASK_SIZE_32 UL(0x100000000) //32位操作系統進程的用戶虛擬地址空間包含區域:代碼段、數據段、未初始化數據段;
動態庫的代碼段、數據段和未初始化數據段;存放動態生成的數據的堆;
存放局部變量和實現函數調用的棧;
把文件區間映射到虛擬地址空間的內存映射區域;存放在棧底部的環境變量和參數字符串。
部分內核代碼:
struct mm_struct {struct vm_area_struct *mmap;//虛擬內存區域鏈表 /* list of VMAs */struct rb_root mm_rb;//虛擬內存區紅黑樹u32 vmacache_seqnum; /* per-thread vmacache */ #ifdef CONFIG_MMU //在內存映射區找到一個沒有映射的區域unsigned long (*get_unmapped_area) (struct file *filp,unsigned long addr, unsigned long len,unsigned long pgoff, unsigned long flags);unsigned long mmap_base; //內存映射區起始地址 /* base of mmap area */unsigned long mmap_legacy_base; /* base of mmap area in bottom-up allocations */unsigned long task_size; //用戶虛擬空間長度 /* size of task vm space */unsigned long highest_vm_end; /* highest vma end address */pgd_t * pgd;atomic_t mm_users; //共享一個用戶虛擬空間的進程數量,進程包含的線程的數量 /* How many users with user space? */atomic_t mm_count; /* How many references to "struct mm_struct" (users count as 1) */atomic_long_t nr_ptes; unsigned long hiwater_rss;//進程所擁有的最大頁框數 /* High-watermark of RSS usage */unsigned long hiwater_vm; // 最大頁數/* High-water virtual memory usage */unsigned long total_vm; //進程頁數 /* Total pages mapped */unsigned long locked_vm;//鎖住不能交換的頁數 /* Pages that have PG_mlocked set */unsigned long pinned_vm; /* Refcount permanently increased */unsigned long shared_vm; /* Shared pages (files) */unsigned long exec_vm; /* VM_EXEC & ~VM_WRITE */unsigned long stack_vm; /* VM_GROWSUP/DOWN */unsigned long def_flags;unsigned long start_code, end_code, start_data, end_data;//代碼段起始結束,數據段起始結束unsigned long start_brk, brk, start_stack;//堆 棧的起始地址**我所有的學習筆記都在Github倉庫里:https://github.com/fanxing-6/CPP-learning-notes **
,如果訪問Github有問題也可以訪問Gitee:CPP-learning-notes: C++學習筆記 (gitee.com)
本人能力有限,筆記難免有疏漏,如果有錯誤,歡迎各位關注公眾號與我交流,一定會及時回復
總結
以上是生活随笔為你收集整理的【Linux内核】虚拟地址空间布局架构的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 登录验证----滑块/拼图碎片/随机nu
- 下一篇: linux异步io底层原理,异步IO简析