【Linux内核】虚拟地址空间布局架构
虛擬地址空間布局架構(gòu)(Linux內(nèi)核學(xué)習(xí))
1.Linux內(nèi)核整體架構(gòu)及子系統(tǒng)
內(nèi)核對(duì)下管理硬件,對(duì)上通過運(yùn)行時(shí)庫對(duì)應(yīng)用提供服務(wù)
用戶空間
使用malloc()分配內(nèi)存通過free()釋放內(nèi)存
內(nèi)核空間
虛擬進(jìn)程負(fù)責(zé)從進(jìn)程的虛擬地址空間分配虛擬頁,sys_brk來擴(kuò)大或收縮堆,sys_mmap負(fù)責(zé)在內(nèi)存映射區(qū)分配虛擬頁,
頁分配器負(fù)責(zé)分配物理頁
不連續(xù)內(nèi)存分配器提供分配內(nèi)存的接口vmalloc和釋放內(nèi)存接口vfree,申請(qǐng)連續(xù)的物理頁的成功率比較低,可以申請(qǐng)不連續(xù)的物理頁,r然后映射到連續(xù)的虛擬頁,及虛擬地址連續(xù)而物理地址不連續(xù)
內(nèi)存控制組來控制進(jìn)程占用的資源,當(dāng)內(nèi)存碎片化的時(shí)候,找不到連續(xù)的物理頁,內(nèi)存碎片整理通過遷移方式得到連續(xù)的物理頁,當(dāng)內(nèi)存不足的時(shí)候,負(fù)責(zé)回收物理頁
硬件
MMU1包含一個(gè)頁表緩存,保存最近使用過的頁表映射,避免每次都要查詢虛擬頁對(duì)應(yīng)的物理頁,解決了CPU執(zhí)行速度與內(nèi)存速度不匹配的問題
來個(gè)例子:
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <unistd.h> constexpr int MAX = 1024;int main(int argc, char const *argv[]) {/*sbrk函數(shù)在內(nèi)核的管理下將虛擬地址空間映射到內(nèi)存,供malloc函數(shù)使用。*/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可見成功分配了新的內(nèi)存.
那我們?nèi)绾胃泳唧w的看到是否獲取了內(nèi)存呢?
更改代碼如下:
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <unistd.h> constexpr int MAX = 1024;int main(int argc, char const *argv[]) {/*sbrk函數(shù)在內(nèi)核的管理下將虛擬地址空間映射到內(nèi)存,供malloc函數(shù)使用。*/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; }運(yùn)行,不要停止
輸出為:
old:0x55555557a000 p=0x55555557a000 new:0x55555567a000 pid= 1193打開新終端輸入cat /proc/1193/maps(一切皆文件)查看內(nèi)存情況:
后續(xù)就不在演示了(懶)
2.虛擬內(nèi)存空間內(nèi)存架構(gòu)
linux-4.4.4\arch\arm64\include\asm\memory.h
#define TASK_SIZE_64 (UL(1) << VA_BITS)//64位操作系統(tǒng) //VA_BITS 編譯內(nèi)核的時(shí)候選擇的虛擬地址的位數(shù)#ifdef CONFIG_COMPAT #define TASK_SIZE_32 UL(0x100000000) //32位操作系統(tǒng)進(jìn)程的用戶虛擬地址空間包含區(qū)域:代碼段、數(shù)據(jù)段、未初始化數(shù)據(jù)段;
動(dòng)態(tài)庫的代碼段、數(shù)據(jù)段和未初始化數(shù)據(jù)段;存放動(dòng)態(tài)生成的數(shù)據(jù)的堆;
存放局部變量和實(shí)現(xiàn)函數(shù)調(diào)用的棧;
把文件區(qū)間映射到虛擬地址空間的內(nèi)存映射區(qū)域;存放在棧底部的環(huán)境變量和參數(shù)字符串。
部分內(nèi)核代碼:
struct mm_struct {struct vm_area_struct *mmap;//虛擬內(nèi)存區(qū)域鏈表 /* list of VMAs */struct rb_root mm_rb;//虛擬內(nèi)存區(qū)紅黑樹u32 vmacache_seqnum; /* per-thread vmacache */ #ifdef CONFIG_MMU //在內(nèi)存映射區(qū)找到一個(gè)沒有映射的區(qū)域unsigned long (*get_unmapped_area) (struct file *filp,unsigned long addr, unsigned long len,unsigned long pgoff, unsigned long flags);unsigned long mmap_base; //內(nèi)存映射區(qū)起始地址 /* base of mmap area */unsigned long mmap_legacy_base; /* base of mmap area in bottom-up allocations */unsigned long task_size; //用戶虛擬空間長(zhǎng)度 /* size of task vm space */unsigned long highest_vm_end; /* highest vma end address */pgd_t * pgd;atomic_t mm_users; //共享一個(gè)用戶虛擬空間的進(jìn)程數(shù)量,進(jìn)程包含的線程的數(shù)量 /* 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;//進(jìn)程所擁有的最大頁框數(shù) /* High-watermark of RSS usage */unsigned long hiwater_vm; // 最大頁數(shù)/* High-water virtual memory usage */unsigned long total_vm; //進(jìn)程頁數(shù) /* Total pages mapped */unsigned long locked_vm;//鎖住不能交換的頁數(shù) /* 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;//代碼段起始結(jié)束,數(shù)據(jù)段起始結(jié)束unsigned long start_brk, brk, start_stack;//堆 棧的起始地址**我所有的學(xué)習(xí)筆記都在Github倉庫里:https://github.com/fanxing-6/CPP-learning-notes **
,如果訪問Github有問題也可以訪問Gitee:CPP-learning-notes: C++學(xué)習(xí)筆記 (gitee.com)
本人能力有限,筆記難免有疏漏,如果有錯(cuò)誤,歡迎各位關(guān)注公眾號(hào)與我交流,一定會(huì)及時(shí)回復(fù)
總結(jié)
以上是生活随笔為你收集整理的【Linux内核】虚拟地址空间布局架构的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 登录验证----滑块/拼图碎片/随机nu
- 下一篇: 硬件:路由器的基础知识