精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Linux進程地址空間詳解

馬哥Linux運維 ? 來源:稀土掘金技術社區 ? 2023-12-18 09:45 ? 次閱讀

RAM 的某些部分永久地分配給內核, 并用來存放內核代碼以及靜態內核數據結構. RAM 的其余部分稱為動態內存 (dynamic memory). 動態內存不僅是進程所需的寶貴資源, 也是內核本身所需的寶貴資源. 實際上,整個系統的性能取決于如何有效地管理動態內存. 因此, 現在所有多任務操作系統都在盡力優化對動態內存的使用, 也就是說, 盡可能做到當需要時分配, 不需要時釋放.

0bfcda9a-9ccd-11ee-8b88-92fbcf53809c.jpg

當給內核分配動態內存時, 是相對容易的, 有如下兩點原因:

內核是操作系統中優先級最高的成分. 如果某個內核函數請求動態內存, 那么, 必定有正當的理由發出這個請求, 因此, 沒有道理試圖推遲這個請求.

內核信任自己. 所有的內核函數都被假定是沒有錯誤的, 因此內核函數不必針對程序錯誤施加任何保護措施.

而當給用戶態進程分配內存時, 情況完全不同:

進程對動態內存的請求被認為是不緊急的. 例如, 當進程對應在磁盤上所存儲的可執行文件被裝入內存時, 進程并不一定會立即對所有的代碼和數據進行訪問. 類似地, 當進程調用malloc()以請求獲得額外的動態內存時, 也并不意味著進程很快就會訪問所獲得的額外的動態內存.因此, 一般來說, 內核總是盡量推遲給用戶態進程分配動態內存.

由于用戶進程是不可信任的, 因此, 內核必須能隨時準備捕獲用戶態進程引起的所有尋址錯誤.

為了使得動態內存得到最大限度的使用, 內核使用一種新的資源成功實現了對進程動態內存的推遲分配. 當用戶態進程請求動態內存時, 并沒有獲得請求的動態內存, 而僅僅得到了對一個新的線性地址區間的使用權, 這樣的線性地址區間有很多, 由允許進程使用的全部線性地址區間所組成的集合就叫做進程地址空間.

與進程地址空間有關的全部信息都包含在一個叫做內存描述符的數據結構中 (實際上就是描述進程虛擬內存的數據結構), 這個結構的類型為mm_struct, 進程描述符的mm字段就指向這個結構.


struct mm_struct *mm;

如下為Linux 2.6.11版的內核中mm_struct的實現.

struct mm_struct {
  struct vm_area_struct * mmap;    
  struct rb_root mm_rb;
  struct vm_area_struct * mmap_cache;  
  unsigned long (*get_unmapped_area) (struct file *filp,
        unsigned long addr, unsigned long len,
        unsigned long pgoff, unsigned long flags);
  void (*unmap_area) (struct vm_area_struct *area);
  unsigned long mmap_base;    
  unsigned long free_area_cache;    
  pgd_t * pgd;
  atomic_t mm_users;      
  atomic_t mm_count;      
  int map_count;        
  struct rw_semaphore mmap_sem;
  spinlock_t page_table_lock;    


  struct list_head mmlist;    
             * together off init_mm.mmlist, and are protected
             * by mmlist_lock
             */


  unsigned long start_code, end_code, start_data, end_data;
  unsigned long start_brk, brk, start_stack;
  unsigned long arg_start, arg_end, env_start, env_end;
  unsigned long rss, anon_rss, total_vm, locked_vm, shared_vm;
  unsigned long exec_vm, stack_vm, reserved_vm, def_flags, nr_ptes;


  unsigned long saved_auxv[42]; 


  unsigned dumpable:1;
  cpumask_t cpu_vm_mask;


  
  mm_context_t context;


  
  unsigned long swap_token_time;
  char recent_pagein;


  
  int core_waiters;
  struct completion *core_startup_done, core_done;


  
  rwlock_t    ioctx_list_lock;
  struct kioctx    *ioctx_list;


  struct kioctx    default_kioctx;


  unsigned long hiwater_rss;  
  unsigned long hiwater_vm;  
};

其中用來標識相應進程特定線性區的字段如下:

0c149d2e-9ccd-11ee-8b88-92fbcf53809c.jpg

start_code, end_code

正文代碼的起始地址和終止地址.

start_data, end_data

已初始化數據的起始地址和終止地址.

start brk, brk

堆的起始地址和當前終止地址.

start_stack

用戶態堆棧的起始地址.

arg_start, arg_end

命令行參數的起始地址和終止地址.

env_start, env_end

環境變量的起始地址和終止地址.

如下為進程地址空間的布局, 由一個一個的線性地址區間組成, 線性地址 (linear address), 也稱虛擬地址 (virtual address) 是一個 32 位無符號整數 (unsigned long), 可以用來表示數值高達 4GB 的地址, 也就是 4,294,967,296 個內存單元.線性地址通常用十六進制數字表示, 值的范圍從 0x00000000 到 0xffffffff.

0c2a070e-9ccd-11ee-8b88-92fbcf53809c.jpg

0x00000000 ~ 0xbfffffff 這一線性地址區間被稱為用戶空間, 大小為 3GB; 而0xc0000000 ~ 0xffffffff 這一線性地址區間被稱為內核空間, 大小為 1GB.

可以通過以下代碼對進程地址空間的布局圖進行驗證.


#include 
#include 


int uninitialized_global_var;
int initialized_global_var = 100;


int main(int argc, char *argv[], char *envp[])
{
    printf("Code address:%p
", main);  
    printf("Initialized Data address:%p
", &initialized_global_var);  
    printf("Uninitialized Data address:%p
", &uninitialized_global_var);  
    int *p = (int*)malloc(sizeof(int));
    printf("Heap address:%p
", p);  
    printf("Stack address:%p
", &p);  


    for (int i = 0; i < argc; i++) {
        printf("Command-line Arguments address:%p
", argv[i]);  
    }
    
    for (int i = 0; envp[i]; i++) {
        printf("Environment Variables address:%p
", envp[i]);  
    }
    return 0;
}

運行結果如下, 與進程地址空間的布局相吻合.

0c3a7792-9ccd-11ee-8b88-92fbcf53809c.jpg

線性地址(虛擬地址)的集合稱為虛擬內存, 物理地址的集合稱為物理內存, 進程對于內存訪問的終點是物理內存而不是虛擬內存,所以必然存在一種將虛擬內存轉化為物理內存的結構, 這種結構被稱為頁表.

頁 (Page) && 頁幀 (Page Frame)

內核使用struct page作為基本單位來管理物理內存, 在內核看來,所有的 RAM 都被劃分成了固定長度的頁幀 (頁幀也叫頁框, 通常大小為4KB). 每一個頁幀包含了一個頁, 也就是說一個頁幀的長度和一個頁的長度相同.頁和頁幀的區別在于, 頁是抽象的數據結構, 可以存放在任意地方, 而頁幀是真實的存儲區域, 屬于主存的一部分.

如下為Linux 2.6.11版的內核中struct page的實現.


struct page {
  page_flags_t flags;    
           * updated asynchronously */
  atomic_t _count;    
  atomic_t _mapcount;    
           * to show when page is mapped
           * & limit reverse map searches.
           */
  unsigned long private;    
           * usually used for buffer_heads
           * if PagePrivate set; used for
           * swp_entry_t if PageSwapCache
           * When page is free, this indicates
           * order in the buddy system.
           */
  struct address_space *mapping;  
           * inode address_space, or NULL.
           * If page mapped as anonymous
           * memory, low bit is set, and
           * it points to anon_vma object:
           * see PAGE_MAPPING_ANON below.
           */
  pgoff_t index;      
  struct list_head lru;    
           * protected by zone->lru_lock !
           */
  
   * On machines where all RAM is mapped into kernel address space,
   * we can simply calculate the virtual address. On machines with
   * highmem some memory is mapped into kernel virtual memory
   * dynamically, so we need a place to store that address.
   * Note that this field could be 16 bits on x86 ... ;)
   *
   * Architectures with slow multiplication can define
   * WANT_PAGE_VIRTUAL in asm/page.h
   */
#if defined(WANT_PAGE_VIRTUAL)
  void *virtual;      
             not kmapped, ie. highmem) */
#endif 
};

CPU 管理物理地址, 因而虛擬地址需要轉化為物理地址才能給 CPU 使用.用于將進程(虛擬)地址空間映射成物理地址空間的數據結構稱為頁表.

0c5ca876-9ccd-11ee-8b88-92fbcf53809c.jpg

進程地址空間, 頁表的存在有什么意義?

讓所有進程以統一的視角看待內存,進程地址空間的存在讓我們在編寫程序的時候只需關注虛擬地址, 而無需關注數據在物理內存當中實際的存儲位置.

頁表的存在讓進程在間接訪問內存的時候, 增加一個轉換的過程, 在這個轉換的過程中, 內核對進程的尋址請求進行檢查, 如果該進程的尋址請求異常, 則該請求被操作系統攔截, 從而實現對物理內存的保護.

進程地址空間與頁表的存在, 讓內核對于進程管理模塊與內存管理模塊進行了解耦.

審核編輯:湯梓紅

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • RAM
    RAM
    +關注

    關注

    8

    文章

    1344

    瀏覽量

    114214
  • Linux
    +關注

    關注

    87

    文章

    11123

    瀏覽量

    207908
  • 操作系統
    +關注

    關注

    37

    文章

    6545

    瀏覽量

    122743
  • 動態內存
    +關注

    關注

    1

    文章

    24

    瀏覽量

    7956
  • 進程
    +關注

    關注

    0

    文章

    197

    瀏覽量

    13928

原文標題:Linux - 進程 - 進程地址空間

文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    Linux如何證明線程共享進程地址空間

    所有的書上都說,進程中的所有線程共享進程地址空間,如上圖中的藍框都在一個進程中。那么該如何證明這個結論呢?
    發表于 08-25 16:22 ?429次閱讀
    <b class='flag-5'>Linux</b>如何證明線程共享<b class='flag-5'>進程</b>的<b class='flag-5'>地址</b><b class='flag-5'>空間</b>

    Linux內核地址映射模型與Linux內核高端內存詳解

    的數據可能不在內存中。 Linux內核地址映射模型 x86 CPU采用了段頁式地址映射模型。進程代碼中的地址為邏輯
    發表于 05-08 10:33 ?3401次閱讀
    <b class='flag-5'>Linux</b>內核<b class='flag-5'>地址</b>映射模型與<b class='flag-5'>Linux</b>內核高端內存<b class='flag-5'>詳解</b>

    Linux守護進程詳解

    分享到:標簽:進程控制 Linux 守護進程進程 7.3 Linux守護進程 7.3.1 守
    發表于 10-18 14:24 ?0次下載
    <b class='flag-5'>Linux</b>守護<b class='flag-5'>進程</b><b class='flag-5'>詳解</b>

    linux進程的深入理解

    每個進程都有自己的堆棧,內核在創建一個新的進程時,在創建進程控制塊 task struct 的同時,也為進程創建堆棧。 一個進程有 2個堆棧
    發表于 01-16 14:43 ?2次下載

    Linux進程的內存結構

    Linux操作系統采用虛擬內存管理技術,使得每個進程都有各自互不干涉的進程地址空間。該地址
    發表于 06-01 09:17 ?1432次閱讀
    <b class='flag-5'>Linux</b>下<b class='flag-5'>進程</b>的內存結構

    Linux進程的創建、執行和終止

     許多操作系統提供的都是產生進程的機制,也就是說,首先在新的地址空間里創建進程、讀入可執行文件,后再開始執行。Linux
    發表于 06-11 09:21 ?585次閱讀

    深入淺出Linux進程地址空間

    我們知道,在32位機器上linux操作系統中的進程地址空間大小是4G,其中0-3G是用戶空間,3G-4G是內核
    的頭像 發表于 06-20 09:57 ?1866次閱讀

    Linux操作系統知識講解:走進linux 內存地址空間

    Linux操作系統知識講解:走進linux 內存地址空間
    的頭像 發表于 08-28 10:45 ?4915次閱讀
    <b class='flag-5'>Linux</b>操作系統知識講解:走進<b class='flag-5'>linux</b> 內存<b class='flag-5'>地址</b><b class='flag-5'>空間</b>

    Linux進程

    內核通過輕量級進程 (lightweight process) 來支持多線程。1個輕量級進程就對應1個線程,輕量級進程之間可以共享打開的文件、地址
    的頭像 發表于 11-29 09:51 ?2056次閱讀
    <b class='flag-5'>Linux</b>的<b class='flag-5'>進程</b>

    mlock如何鎖住進程地址空間關聯的物理內存

    的應用),Linux中提供了mlock相關的系統調用供用戶空間使用來鎖住部分或全部的地址空間關聯的物理頁面。 本文的分析基于arm64處理器架構,內核版本為
    的頭像 發表于 03-14 09:36 ?951次閱讀

    Linux進程的內存消耗和泄漏詳解

    當我們評估進程消耗多少內存時,就是指在用戶空間消耗的內存,即虛擬地址在0~3G的部分,對應的物理地址內存。內核空間的內存消耗屬于內核,系統調
    的頭像 發表于 05-14 10:07 ?2608次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>進程</b>的內存消耗和泄漏<b class='flag-5'>詳解</b>

    Linux程序地址空間詳解

    在正式講程序[地址空間]前我們先來看一段簡單的代碼來分析分析。
    的頭像 發表于 03-26 10:39 ?591次閱讀

    為什么進程地址空間中要包括操作系統(內核)呢?

    這張圖就是Linux程序運行起來后所謂的進程地址空間,這里包括我們熟悉的代碼區、數據區、以及堆區和棧區。
    的頭像 發表于 04-18 09:09 ?951次閱讀

    Linux系統為什么需要引入虛擬地址

    Linux 系統中,采用了虛擬內存管理技術,事實上大多數現在操作系統都是如此!在 Linux 系統中,每一個進程都在自己獨立的地址空間
    的頭像 發表于 10-07 17:28 ?803次閱讀
    <b class='flag-5'>Linux</b>系統為什么需要引入虛擬<b class='flag-5'>地址</b>

    Linux虛擬地址空間和物理地址空間的關系

    過程,這其實也是MMU的工作原理。 我們知道,在Linux中,每個進程都有自己獨立的地址空間,且互不干擾。每個進程
    的頭像 發表于 10-08 11:40 ?913次閱讀
    <b class='flag-5'>Linux</b>虛擬<b class='flag-5'>地址</b><b class='flag-5'>空間</b>和物理<b class='flag-5'>地址</b><b class='flag-5'>空間</b>的關系