溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

如何理解Linux進(jìn)程的內(nèi)存管理

發(fā)布時間:2021-09-27 17:30:47 來源:億速云 閱讀:104 作者:柒染 欄目:系統(tǒng)運(yùn)維

這篇文章給大家介紹如何理解Linux進(jìn)程的內(nèi)存管理,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

幾個關(guān)鍵的數(shù)據(jù)結(jié)構(gòu)

一個進(jìn)程的虛擬地址空間主要由兩個數(shù)據(jù)結(jié)來描述,一個是 mm_struct,一個是 vm_area_structs。

mm_struct結(jié)構(gòu)描述了一個進(jìn)程的整個虛擬地址空間,vm_area_truct描述了虛擬地址空間的一個區(qū)間(簡稱虛擬區(qū))。下圖就是我們所說的由task_struct到mm_struct,進(jìn)程的地址空間的分布。

如何理解Linux進(jìn)程的內(nèi)存管理

每一個進(jìn)程都會有自己獨立的mm_struct,這樣每一個進(jìn)程都會有自己獨立的地址空間,這樣才能互不干擾。當(dāng)進(jìn)程之間的地址空間被共享的時候,我們可以理解為這個時候是多個進(jìn)程使用一份地址空間,這就是線程。

struct mm_struct {      struct vm_area_struct *mmap;    //指向虛擬區(qū)間(VMA)鏈表      struct rb_root mm_rb;           //指向red_black樹      struct vm_area_struct *mmap_cache;    //找到最近的虛擬區(qū)間       unsigned long(*get_unmapped_area)(struct file *filp,unsigned long addr,unsigned long len,unsigned long pgoof,unsigned long flags);       void (*unmap_area)(struct mm_struct *mm,unsigned long addr);       unsigned long mmap_base;       unsigned long task_size;   //擁有該結(jié)構(gòu)體的進(jìn)程的虛擬地址空間的大小      unsigned long cached_hole_size;      unsigned long free_area_cache;       pgd_t *pgd;  //指向頁全局目錄       atomic_t mm_users;         //用戶空間中有多少用戶      atomic_t mm_count;         //對"struct mm_struct"有多少引用       int map_count;            //虛擬區(qū)間的個數(shù)      struct rw_semaphore mmap_sem;      spinlock_t page_table_lock;       //保護(hù)任務(wù)頁表和mm->rss       struct list_head mmlist;          //所有活動mm的鏈表      mm_counter_t _file_rss;      mm_counter_t _anon_rss;      unsigned long hiwter_rss;      unsigned long hiwater_vm;        unsigned long total_vm,locked_vm,shared_vm,exec_vm;      usingned long stack_vm,reserved_vm,def_flags,nr_ptes;       unsingned long start_code,end_code,start_data,end_data;  //代碼段的開始start_code ,結(jié)束end_code,數(shù)據(jù)段的開始start_data,結(jié)束end_data       unsigned long start_brk,brk,start_stack;    //start_brk和brk記錄有關(guān)堆的信息,start_brk是用戶虛擬地址空間初始化,brk是當(dāng)前堆的結(jié)束地址,start_stack是棧的起始地址       unsigned long arg_start,arg_end,env_start,env_end;     //參數(shù)段的開始arg_start,結(jié)束arg_end,環(huán)境段的開始env_start,結(jié)束env_end      unsigned long saved_auxv[AT_VECTOR_SIZE];       struct linux_binfmt *binfmt;       cpumask_t cpu_vm_mask;      mm_counter_t context;      unsigned int faultstamp;      unsigned int token_priority;      unsigned int last_interval;       unsigned long flags;      struct core_state *core_state; }

分配的每個虛擬內(nèi)存區(qū)域都由一個vm_area_struct  數(shù)據(jù)結(jié)構(gòu)來管理,包括虛擬內(nèi)存的起始和結(jié)束地址,以及內(nèi)存的訪問權(quán)限等,通常命名為vma;vm_area_struct 數(shù)據(jù)結(jié)構(gòu)的定義如下:

如何理解Linux進(jìn)程的內(nèi)存管理

struct vm_area_struct {  /* The first cache line has the info for VMA tree walking.   第一個緩存行具有VMA樹移動的信息*/    unsigned long vm_start;  /* Our start address within vm_mm. */  unsigned long vm_end;  /* The first byte after our end address within vm_mm. */    /* linked list of VM areas per task, sorted by address  每個任務(wù)的VM區(qū)域的鏈接列表,按地址排序*/  struct vm_area_struct *vm_next, *vm_prev;    struct rb_node vm_rb;    /*   此VMA左側(cè)最大的可用內(nèi)存間隙(以字節(jié)為單位)。    在此VMA和vma-> vm_prev之間,   或者在VMA rbtree中我們下面的一個VMA與其->vm_prev之間。    這有助于get_unmapped_area找到合適大小的空閑區(qū)域。   */  unsigned long rb_subtree_gap;    /* Second cache line starts here.   第二個緩存行從這里開始*/    struct mm_struct *vm_mm; /* 我們所屬的address space*/  pgprot_t vm_page_prot;  /* 此VMA的訪問權(quán)限 */  unsigned long vm_flags;  /* Flags, see mm.h. */    /*   對于具有地址空間(address apace)和后備存儲(backing store)的區(qū)域,   鏈接到address_space->i_mmap間隔樹,或者鏈接到address_space-> i_mmap_nonlinear列表中的vma。   */  union {   struct {    struct rb_node rb;    unsigned long rb_subtree_last;   } linear;   struct list_head nonlinear;  } shared;    /*   在其中一個文件頁面的COW之后,文件的MAP_PRIVATE vma可以在i_mmap樹和anon_vma列表中。   MAP_SHARED vma只能位于i_mmap樹中。    匿名MAP_PRIVATE,堆?;騜rk vma(帶有NULL文件)只能位于anon_vma列表中。   */  struct list_head anon_vma_chain; /* Serialized by mmap_sem & * page_table_lock           由mmap_sem和* page_table_lock序列化*/  struct anon_vma *anon_vma; /* Serialized by page_table_lock 由page_table_lock序列化*/    /* 用于處理此結(jié)構(gòu)體的函數(shù)指針 */  const struct vm_operations_struct *vm_ops;    /* 后備存儲(backing store)的信息: */  unsigned long vm_pgoff;  /* 以PAGE_SIZE為單位的偏移量(在vm_file中),*不是* PAGE_CACHE_SIZE*/  struct file * vm_file;  /* 我們映射到文件(可以為NULL)*/  void * vm_private_data;  /* 是vm_pte(共享內(nèi)存) */   #ifndef CONFIG_MMU  struct vm_region *vm_region; /* NOMMU映射區(qū)域 */ #endif #ifdef CONFIG_NUMA  struct mempolicy *vm_policy; /* 針對VMA的NUMA政策 */ #endif };

小實驗

  • insmod test.ko pid_mem=3253 顯示各個vma區(qū)域

如何理解Linux進(jìn)程的內(nèi)存管理

  • cat /proc/3253/maps 顯示各個vma區(qū)域

如何理解Linux進(jìn)程的內(nèi)存管理

看下兩種方式的對比:

如何理解Linux進(jìn)程的內(nèi)存管理

關(guān)于如何理解Linux進(jìn)程的內(nèi)存管理就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI