【Linux内核】虚拟地址空间布局架构
虛擬地址空間布局架構(gòu)(Linux內(nèi)核學(xué)習(xí))
1.Linux內(nèi)核整體架構(gòu)及子系統(tǒng)
內(nèi)核對(duì)下管理硬件,對(duì)上通過(guò)運(yùn)行時(shí)庫(kù)對(duì)應(yīng)用提供服務(wù)
用戶(hù)空間
使用malloc()分配內(nèi)存通過(guò)free()釋放內(nèi)存
內(nèi)核空間
虛擬進(jìn)程負(fù)責(zé)從進(jìn)程的虛擬地址空間分配虛擬頁(yè),sys_brk來(lái)擴(kuò)大或收縮堆,sys_mmap負(fù)責(zé)在內(nèi)存映射區(qū)分配虛擬頁(yè),
頁(yè)分配器負(fù)責(zé)分配物理頁(yè)
不連續(xù)內(nèi)存分配器提供分配內(nèi)存的接口vmalloc和釋放內(nèi)存接口vfree,申請(qǐng)連續(xù)的物理頁(yè)的成功率比較低,可以申請(qǐng)不連續(xù)的物理頁(yè),r然后映射到連續(xù)的虛擬頁(yè),及虛擬地址連續(xù)而物理地址不連續(xù)
內(nèi)存控制組來(lái)控制進(jìn)程占用的資源,當(dāng)內(nèi)存碎片化的時(shí)候,找不到連續(xù)的物理頁(yè),內(nèi)存碎片整理通過(guò)遷移方式得到連續(xù)的物理頁(yè),當(dāng)內(nèi)存不足的時(shí)候,負(fù)責(zé)回收物理頁(yè)
硬件
MMU1包含一個(gè)頁(yè)表緩存,保存最近使用過(guò)的頁(yè)表映射,避免每次都要查詢(xún)虛擬頁(yè)對(duì)應(yīng)的物理頁(yè),解決了CPU執(zhí)行速度與內(nèi)存速度不匹配的問(wèn)題
來(lá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可見(jiàn)成功分配了新的內(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打開(kāi)新終端輸入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)程的用戶(hù)虛擬地址空間包含區(qū)域:代碼段、數(shù)據(jù)段、未初始化數(shù)據(jù)段;
動(dòng)態(tài)庫(kù)的代碼段、數(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ū)紅黑樹(shù)u32 vmacache_seqnum; /* per-thread vmacache */ #ifdef CONFIG_MMU //在內(nèi)存映射區(qū)找到一個(gè)沒(méi)有映射的區(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; //用戶(hù)虛擬空間長(zhǎng)度 /* size of task vm space */unsigned long highest_vm_end; /* highest vma end address */pgd_t * pgd;atomic_t mm_users; //共享一個(gè)用戶(hù)虛擬空間的進(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)程所擁有的最大頁(yè)框數(shù) /* High-watermark of RSS usage */unsigned long hiwater_vm; // 最大頁(yè)數(shù)/* High-water virtual memory usage */unsigned long total_vm; //進(jìn)程頁(yè)數(shù) /* Total pages mapped */unsigned long locked_vm;//鎖住不能交換的頁(yè)數(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倉(cāng)庫(kù)里:https://github.com/fanxing-6/CPP-learning-notes **
,如果訪問(wèn)Github有問(wèn)題也可以訪問(wèn)Gitee:CPP-learning-notes: C++學(xué)習(xí)筆記 (gitee.com)
本人能力有限,筆記難免有疏漏,如果有錯(cuò)誤,歡迎各位關(guān)注公眾號(hào)與我交流,一定會(huì)及時(shí)回復(fù)
總結(jié)
以上是生活随笔為你收集整理的【Linux内核】虚拟地址空间布局架构的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 登录验证----滑块/拼图碎片/随机nu
- 下一篇: linux异步io底层原理,异步IO简析