天天看點

【Linux核心】虛拟位址空間布局架構虛拟位址空間布局架構(Linux核心學習)未完待續

虛拟位址空間布局架構(Linux核心學習)

1.Linux核心整體架構及子系統

【Linux核心】虛拟位址空間布局架構虛拟位址空間布局架構(Linux核心學習)未完待續

核心對下管理硬體,對上通過運作時庫對應用提供服務

【Linux核心】虛拟位址空間布局架構虛拟位址空間布局架構(Linux核心學習)未完待續
  1. 使用者空間

    使用

    malloc()

    配置設定記憶體通過

    free()

    釋放記憶體
  2. 核心空間

    虛拟程序負責從程序的虛拟位址空間配置設定虛拟頁,

    sys_brk

    來擴大或收縮堆,

    sys_mmap

    負責在記憶體映射區配置設定虛拟頁,

    頁配置設定器負責配置設定實體頁

    不連續記憶體配置設定器提供配置設定記憶體的接口

    vmalloc

    和釋放記憶體接口

    vfree

    ,申請連續的實體頁的成功率比較低,可以申請不連續的實體頁,r然後映射到連續的虛拟頁,及虛拟位址連續而實體位址不連續

    記憶體控制組來控制程序占用的資源,當記憶體碎片化的時候,找不到連續的實體頁,記憶體碎片整理通過遷移方式得到連續的實體頁,當記憶體不足的時候,負責回收實體頁

  3. 硬體

    MMU1包含一個頁表緩存,儲存最近使用過的頁表映射,避免每次都要查詢虛拟頁對應的實體頁,解決了CPU執行速度與記憶體速度不比對的問題

【Linux核心】虛拟位址空間布局架構虛拟位址空間布局架構(Linux核心學習)未完待續

來個例子:

#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

(一切皆檔案)檢視記憶體情況:

【Linux核心】虛拟位址空間布局架構虛拟位址空間布局架構(Linux核心學習)未完待續

後續就不在示範了(懶)

2.虛拟記憶體空間記憶體架構

【Linux核心】虛拟位址空間布局架構虛拟位址空間布局架構(Linux核心學習)未完待續

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;//堆 棧的起始位址
           
【Linux核心】虛拟位址空間布局架構虛拟位址空間布局架構(Linux核心學習)未完待續
【Linux核心】虛拟位址空間布局架構虛拟位址空間布局架構(Linux核心學習)未完待續
【Linux核心】虛拟位址空間布局架構虛拟位址空間布局架構(Linux核心學習)未完待續
【Linux核心】虛拟位址空間布局架構虛拟位址空間布局架構(Linux核心學習)未完待續
【Linux核心】虛拟位址空間布局架構虛拟位址空間布局架構(Linux核心學習)未完待續

未完待續