當前位置:首頁 » 操作系統 » linux進程地址空間

linux進程地址空間

發布時間: 2025-02-15 14:30:34

『壹』 linux虛擬地址空間布局


Linux虛擬地址空間布局詳解


在多任務操作系統中,每個進程擁有獨立的內存空間,稱為虛擬地址空間。在32位系統中,它佔用4GB。Linux內核與用戶進程的虛擬內存分配比例不同,通常是1:3,而Windows(通過特定標志調整)可調整為1:3。虛擬地址通過頁表映射到物理內存,內核空間擁有較高許可權,用戶程序訪問內核空間會觸發頁錯誤。


Linux進程的內存布局包含內核空間和用戶空間。內核空間始終存在,並映射到同一物理內存,處理中斷和系統調用。用戶空間隨著進程切換動態變化,包含棧、內存映射區和堆。棧用於存儲局部變數和函數調用信息,映射區用於文件I/O,堆則用於動態內存分配。


下面是Linux進程地址空間的典型布局:



  • 用戶地址空間:包含映射到物理內存的不同內存段,如隨機化棧和映射區域。

  • 棧:由編譯器管理,執行時存儲函數調用上下文,大小可動態調整。

  • 內存映射:包括動態鏈接庫和匿名內存映射,通過系統調用進行文件I/O。

  • 堆:程序運行時動態分配的內存,用於存放大塊數據。


代碼段、數據段和BSS段是程序編譯時的組成部分,運行時需要棧和堆支持。每個部分有其特定的管理方式和使用場景,如棧的自動管理,堆的動態分配和釋放。


學習Linux內核和內存管理,有助於理解程序運行的內存布局,避免內存問題如棧溢出、內存泄漏,以及理解如何最有效地使用棧和堆。進一步的學習資源可以參考:[Linux內核學習教程鏈接](https://ke.qq.com/course/4032547?flowToken=1040348)。


『貳』 linux進程地址空間劃分

Linux 64位系統在理論上擁有16位十六進製表示的巨大內存地址空間,即從0x0000000000000000到0xFFFFFFFFFFFFFFFF。然而,Linux僅實際使用了其中的256T空間,其餘部分未被使用。

在Linux 64位操作中,實際使用的是低47位地址,高17位用於擴展,只能取全0或全1值。這樣,可用的地址空間被分為兩部分:用戶空間(0x0000000000000000至0x00007FFFFFFFFFFF)和內核空間(0xFFFF800000000000至0xFFFFFFFFFFFFFFFF),剩餘部分未被利用。

用戶空間主要包含以下部分:代碼段、數據段、BSS段、堆和棧。

代碼段用於存放程序執行代碼,即CPU執行的機器指令。

數據段存放已初始化且初值不為0的全局變數和靜態局部變數,屬於靜態內存分配,可讀可寫。

BSS段包括未初始化全局變數和靜態局部變數的空間。

堆(heap)是動態分配內存的區域,當進程讀取文件時,若文件未在內存中,會通過缺頁中斷獲取物理內存,通過磁碟調頁將文件數據讀入內存,實現文件的讀取。

文件在兩個進程間共享時,即使它們映射到同一文件,虛擬地址空間也可能不同。若進程A先讀取文件,則會獲取物理內存,通過磁碟調頁將文件數據讀入內存。進程B在訪問文件時,若文件數據不在內存中,則會查找緩存區,如果緩存中有文件數據,則建立映射關系,實現進程間通信。

棧(stack)用於存儲函數調用時的局部變數。

以數組s和指針p3為例,數組s的內容是在運行時賦值,而指針p3指向的常量區字元串內容在編譯時已賦值。

使用malloc函數分配內存時,虛擬內存的分配情況如下:

當malloc分配的內存小於128k時,使用brk分配內存,將_edata向高地址移動,只分配虛擬空間,不對應物理內存。第一次讀/寫數據時,會觸發內核缺頁中斷,內核分配物理內存,建立虛擬地址空間映射關系。若分配的內存不被訪問,對應的物理內存不會被分配。

brk分配的內存需要等待高地址內存釋放後才能釋放,可能導致內存碎片。

當malloc分配的內存大於128k時,使用mmap分配內存,在堆和棧之間尋找空閑內存分配,對應獨立內存且初始化為0。mmap分配的內存可以直接通過free釋放。

當最高地址空間的空閑內存超過128k時,Linux執行內存緊縮操作,釋放部分內存。

當進程訪問未建立映射關系的虛擬內存時,邏輯地址轉換為物理地址,發現當前頁不在內存中,處理器自動觸發缺頁異常。

『叄』 Linux關於地址空間和MMAP映射有何特點

Linux採用
虛擬
內存技術,系統中的所有進程之間以虛擬方式共享內存。對每個進程來說,它們好像都可以訪問整個系統的所有物理內存。更重要的是,即使單獨一個進程,它擁有的地址空間也可以遠遠大於系統物理內存。
進程地址空間由每個進程中的線性地址區組成,每個進程都有一個32位或64位的平坦(flat)空間,空間的具體大小取決於體系結構。「平坦」指地址空間范圍是一個獨立的連續區間。通常情況下,每個進程都有唯一的這種平坦空間,而且每個進程的地址空間之間彼此互不相干。兩個不同的進程可以在它們各自地址空間的相同地址內存存放不同的數據。但是進程之間也可以選擇共享地址空間,我們稱這樣的進程為線程。
在地址空間中,我們更為關心的是進程有權訪問的虛擬內存地址區間,比如08048000~0804c000。這些可被訪問的合法地址區間被成為內存區域(memory area),通過內核,進程可以給自己的地址空間動態地添加或減少內存區域。
進程只能訪問有效范圍內的內存地址。每個內存區域也具有相應進程必須遵循的特定訪問屬性,如只讀、只寫、可執行等屬性。如果一個進程訪問了不在有效范圍中的地址,或以不正確的方式訪問有效地址,那麼內核就會終止該進程,並返回「段錯誤」信息。
?
內存區域可以包含各種內存對象,如下:
?
可執行文件代碼的內存映射,成為代碼段(text section)。
?
可執行文件的已初始化全局變數的內存映射,成為數據段(data section)。
?
包含未初始化全局變數的零頁(也就是bss段)的內存映射。零頁是指頁面中的數據全部為0。
?
用於進程用戶空間棧的零頁的內存映射。
?
每一個諸如C庫或動態鏈接程序等共享庫的代碼段、數據段和bss也會被載入進程的地址空間。
?
任何內存映射文件。
?
任何共享內存段。
?
任何匿名的內存映射,比如由malloc()分配的內存。
進程地址空間的任何有效地址都只能位於唯一的區域,這些內存區域不能相互覆蓋。可以看到,在執行的進程中,每個不同的內存片斷都對應一個獨立的內存區域:棧、對象代碼、全局變數、被映射的文件等等。
內核使用內存描述符表示進程的地址空間。內存描述符由mm_struct結構體表示,定義在文件中,該結構包含了和進程地址空間有關的全部信息。
VMA
內存區域由vm_area_struct結構體描述,定義在文件中,內存區域在內核中也經常被稱作虛擬內存區域或者VMA。
VMA標志是一種位標志,它定義在vm_area_struct結構中(該結構中的vm_flags子域)。和物理頁的訪問許可權不同,VMA標志反映了內核處理頁面索需要遵守的行為准則,而不是硬體要求。VM_IO標志內存區域中包含對設備I/O空間的映射。該標志通常在設備驅動程序執行 mmap()函數進行I/O空間映射時才被設置,同時該標志也表示該內存區域不能被包含在任何進程的存放轉存(core mp)中。VM_RESERVED標志內存區域不能被換出,它也是在設備驅動程序進行映射時被設置。
vm_area_struct結構體中的vm_ops域指向與指定內存區域相關的操作函數表,內核使用表中的方法操作VMA。
mmap()和do_mmap():創建地址區間
內核使用do_mmap()函數創建一個新的線性地址區間。但是說給函數創建一個新VMA並不非常准確,因為如果創建的地址區間和一個已經存在的地址區間相鄰,並且它們具有相同的訪問許可權的話,那麼兩個區間將合並為一個。如果不能合並,那麼就確實需要創建一個新的VMA了。但無論哪種情況,do_mmap()函數都會將一個地址區間加入到進程的地址空間中——無論是擴展已經存在的內存區域還是創建一個新的區域。
do_mmap()函數聲明在文件中,原型如下:
unsigned long do_mmap(struct file *file, unsigned long addr,
unsigned long len, unsigned long prot,
unsigned long flag, unsigned long offset)
在用戶空間可以通過mmap()函數調用獲取內核函數do_mmap()的功能。mmap()系統調用原型如下:
void *mmap2(void *start, size_t length,
int prot, int flags,
int fd, off_t pgoff)
do_munmap()函數從特定的進程地址空間中刪除指定地址區間,該函數在文件中聲明:
int do_munmap(struct mm_struct *mm, unsigned long start, size_t len)
系統調用munmap()給用戶空間程序提供了一種從自身地址空間中刪除指定地址區間的方法,它和系統調用mmap()的作用相反:
int munmap(void *start, size_t length)
mmap設備操作
對於驅動程序來說,內存映射可以提供給用戶程序直接訪問設備內存的能力。映射一個設備,意味著使用戶空間的一段地址關聯到設備內存上。無論何時,只要程序在分配的地址范圍內進行讀取或者寫入,實際上就是對設備的訪問。
並不是所有的設備都能進行mmap抽象。例如,串口設備和其他面向流的設備就無法實現這種抽象。mmap的另一個限制是映射都是以 PAGE_SIZE為單位的。內核只能在頁表一級處理虛擬地址;因此,被映射的區域必須是PAGE_SIZE的整數倍,而且必須位於起始於 PAGE_SIZE整數倍地址的物理內存內。如果區域的大小不是頁大小的整數倍,內核就通過生成一個稍微大一些的區域來容納它。
mmap方法是file_operations結構中的一員,並且在執行mmap系統調用時就會調用該方法。在調用實際方法之前,內核會完成很多工作,而且該方法的原型與系統調用的原型由很大區別。關於Linux命令的介紹,看看《linux就該這么學》,具體關於這一章地址3w(dot)linuxprobe/chapter-02(dot)html
文件操作聲明如下:
int (*mmap) (struct file * filp, struct vm_area_struct *vma);
其中vma參數包含了用於訪問設備的虛擬地址區間的信息。大部分工作已經由內核完成了,要實現mmap,驅動程序只要為這一地址范圍構造合適的頁表即可,如果需要的話,就用一個新的操作集替換vma->vm_ops。
有兩種建立頁表的方法:使用remap_page_range函數可一次建立所有的頁表,或者通過nopage VMA方法每次建立一個頁表。
構造用於映射一段物理地址的新頁表的工作是由remap_page_range完

熱點內容
jdbc創建資料庫 發布:2025-02-15 23:02:15 瀏覽:371
百度雲加密課 發布:2025-02-15 23:00:16 瀏覽:752
php網站畢業論文 發布:2025-02-15 23:00:11 瀏覽:517
linux伺服器日誌查看 發布:2025-02-15 22:48:35 瀏覽:416
模型雕刻機選擇哪個配置的好 發布:2025-02-15 22:44:46 瀏覽:327
我的世界伺服器神奇寶貝 發布:2025-02-15 22:26:21 瀏覽:725
我的世界如何防止伺服器生成怪物 發布:2025-02-15 22:25:35 瀏覽:299
描述瀏覽器緩存機制 發布:2025-02-15 22:25:33 瀏覽:892
手機什麼配置反應快 發布:2025-02-15 22:20:11 瀏覽:672
資料庫存儲表 發布:2025-02-15 22:09:15 瀏覽:961