日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

【Linux内核】虚拟地址空间布局架构

發(fā)布時間:2023/12/10 linux 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Linux内核】虚拟地址空间布局架构 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

虛擬地址空間布局架構(gòu)(Linux內(nèi)核學(xué)習(xí))

1.Linux內(nèi)核整體架構(gòu)及子系統(tǒng)

內(nèi)核對下管理硬件,對上通過運行時庫對應(yīng)用提供服務(wù)

  • 用戶空間

    使用malloc()分配內(nèi)存通過free()釋放內(nèi)存

  • 內(nèi)核空間

    虛擬進(jìn)程負(fù)責(zé)從進(jìn)程的虛擬地址空間分配虛擬頁,sys_brk來擴大或收縮堆,sys_mmap負(fù)責(zé)在內(nèi)存映射區(qū)分配虛擬頁,

    頁分配器負(fù)責(zé)分配物理頁

    不連續(xù)內(nèi)存分配器提供分配內(nèi)存的接口vmalloc和釋放內(nèi)存接口vfree,申請連續(xù)的物理頁的成功率比較低,可以申請不連續(xù)的物理頁,r然后映射到連續(xù)的虛擬頁,及虛擬地址連續(xù)而物理地址不連續(xù)

    內(nèi)存控制組來控制進(jìn)程占用的資源,當(dāng)內(nèi)存碎片化的時候,找不到連續(xù)的物理頁,內(nèi)存碎片整理通過遷移方式得到連續(xù)的物理頁,當(dāng)內(nèi)存不足的時候,負(fù)責(zé)回收物理頁

  • 硬件

    MMU1包含一個頁表緩存,保存最近使用過的頁表映射,避免每次都要查詢虛擬頁對應(yīng)的物理頁,解決了CPU執(zhí)行速度與內(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", 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; }

    運行,不要停止

    輸出為:

    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ù)#ifdef CONFIG_COMPAT #define TASK_SIZE_32 UL(0x100000000) //32位操作系統(tǒng)

    進(jìn)程的用戶虛擬地址空間包含區(qū)域:代碼段、數(shù)據(jù)段、未初始化數(shù)據(jù)段;
    動態(tài)庫的代碼段、數(shù)據(jù)段和未初始化數(shù)據(jù)段;存放動態(tài)生成的數(shù)據(jù)的堆;
    存放局部變量和實現(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ū)找到一個沒有映射的區(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; //用戶虛擬空間長度 /* size of task vm space */unsigned long highest_vm_end; /* highest vma end address */pgd_t * pgd;atomic_t mm_users; //共享一個用戶虛擬空間的進(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)

    本人能力有限,筆記難免有疏漏,如果有錯誤,歡迎各位關(guān)注公眾號與我交流,一定會及時回復(fù)

    總結(jié)

    以上是生活随笔為你收集整理的【Linux内核】虚拟地址空间布局架构的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。