加入星計(jì)劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴(kuò)散
  • 作品版權(quán)保護(hù)
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長期合作伙伴
立即加入
  • 正文
    • 幾個(gè)關(guān)鍵的數(shù)據(jù)結(jié)構(gòu)
    •  
    • 小實(shí)驗(yàn)
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請入駐 產(chǎn)業(yè)圖譜

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

2021/03/18
193
閱讀需 14 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

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

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

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

每一個(gè)進(jìn)程都會有自己獨(dú)立的mm_struct,這樣每一個(gè)進(jìn)程都會有自己獨(dú)立的地址空間,這樣才能互不干擾。當(dāng)進(jìn)程之間的地址空間被共享的時(shí)候,我們可以理解為這個(gè)時(shí)候是多個(gè)進(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ū)間的個(gè)數(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;
}
  • 分配的每個(gè)虛擬內(nèi)存區(qū)域都由一個(gè)vm_area_struct 數(shù)據(jù)結(jié)構(gòu)來管理,包括虛擬內(nèi)存的起始和結(jié)束地址,以及內(nèi)存的訪問權(quán)限等,通常命名為vma;vm_area_struct 數(shù)據(jù)結(jié)構(gòu)的定義如下:

 

struct vm_area_struct {
 /* The first cache line has the info for VMA tree walking. 
 第一個(gè)緩存行具有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
 每個(gè)任務(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中我們下面的一個(gè)VMA與其->vm_prev之間。 
  這有助于get_unmapped_area找到合適大小的空閑區(qū)域。
  */
 unsigned long rb_subtree_gap;
 
 /* Second cache line starts here. 
 第二個(gè)緩存行從這里開始*/
 
 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;
 
 /*
  在其中一個(gè)文件頁面的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
};

 

小實(shí)驗(yàn)

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

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

 

看下兩種方式的對比:

 

 

相關(guān)推薦

電子產(chǎn)業(yè)圖譜

針對嵌入式人工智能,物聯(lián)網(wǎng)等專業(yè)技術(shù)分享和交流平臺,內(nèi)容涉及arm,linux,android等各方面。

Arm64 ?;厮?>
				</a>
							</li>
						<li id= 查看更多