目錄
記憶體分配是如何完成的? " >記憶體分配是如何完成的?
第一個系統呼叫:brk" >第一個系統呼叫:brk
位址空間佈局隨機化:ASLR" >位址空間佈局隨機化:ASLR
第二个系统调用:mmap" >第二个系统调用:mmap
Linux 中内存分配的重要性" >Linux 中内存分配的重要性
首頁 系統教程 Linux Linux 上記憶體分配的工作原理

Linux 上記憶體分配的工作原理

Feb 10, 2024 pm 04:00 PM
linux linux教程 linux系統 linux指令 shell腳本 嵌入式linux linux入門 linux學習

了解 Linux 記憶體分配的細節非常重要,尤其是在核心和系統架構中。讓我們深入了解 Linux 記憶體分配並了解幕後發生的事情。

在電腦中,要讓進程可執行,就需要將其放置在記憶體中。為此,必須將欄位分配給記憶體中的進程。記憶體分配是一個需要注意的重要問題,尤其是在核心和系統架構中。

讓我們詳細了解 Linux 記憶體分配,並了解幕後發生的事情。

記憶體分配是如何完成的?

大多數軟體工程師不知道這個過程的細節。但如果你是系統程式設計師候選人,你應該對它了解更多。在看分配過程的時候,有必要對 Linux 和glibc庫做一個小細節。

當應用程式需要記憶體時,它們必須從作業系統請求它。來自核心的這個請求自然需要係統呼叫。您不能在使用者模式下自己分配記憶體。

**malloc()**系列函數負責 C 語言中的記憶體分配。這裡要問的問題是 malloc() 作為 glibc 函數是否進行直接系統呼叫。

Linux 核心中沒有稱為 malloc 的系統呼叫。但是,對於應用程式的記憶體需求有兩個系統調用,它們是brkmmap

由於您將透過 glibc 函數在應用程式中請求內存,您可能想知道此時 glibc 正在使用哪些系統呼叫。答案是兩者兼具。

Linux 上内存分配的工作原理

第一個系統呼叫:brk

#每個行程都有一個連續的資料欄位。透過 brk 系統調用,增加了決定資料域限制的程式中斷值,並執行了分配過程。

儘管使用這種方法分配記憶體非常快,但並非總是可以將未使用的空間傳回系統。

例如,假設您透過 malloc() 函數為 brk 系統呼叫分配了五個字段,每個字段大小為 16KB。當您完成其中第二個欄位時,無法傳回相關資源(解除指派)以便系統可以使用它。因為如果您減少位址值以顯示第二個欄位的開始位置,並呼叫 brk,您將完成第三、四個和五個欄位的釋放。

為了防止這種情況下的記憶體遺失,glibc 中的malloc 實作會監控進程資料欄位中分配的位置,然後透過free() 函數指定將其傳回給系統,以便系統可以將空閒空間用於進一步的記憶體分配。

也就是說,在分配了5 個16KB 的區域之後,如果用free() 函數傳回第二個區域,過一段時間再請求另一個16KB 的區域,而不是透過brk 系統呼叫擴大資料區域,之前的地址是回來。

但是,如果新要求的區域大於 16KB,則資料區域將透過 brk 系統呼叫指派新區域來擴大,因為區域 2 無法使用。雖然二號區域沒有使用,但由於大小不同,應用程式無法使用它。因為這樣的場景,有一種情況叫做內部碎片,實際上你很少能充分利用記憶體的所有部分。

為了更好地理解,請嘗試編譯並執行以下範例應用程式:

#include 
#include 
#include 
int main(int argc, char* argv[])
{
        char *ptr[7];
        int n;
        printf("Pid of %s: %d", argv[0], getpid());
        printf("Initial program break   : %p", sbrk(0));
        for(n=0; nprintf("After 5 x 16kB malloc   : %p", sbrk(0));
        free(ptr[1]);
        printf("After free of second 16kB       : %p", sbrk(0));
        ptr[5] = malloc(16 * 1024);
        printf("After allocating 6th of 16kB    : %p", sbrk(0));
        free(ptr[5]);
        printf("After freeing last block        : %p", sbrk(0));
        ptr[6] = malloc(18 * 1024);
        printf("After allocating a new 18kB     : %p", sbrk(0));
        getchar();
        return 0;
}
登入後複製

執行應用程式時,您將獲得類似於以下輸出的結果:

Pid of ./a.out: 31990
Initial program break   : 0x55ebcadf4000
After 5 x 16kB malloc   : 0x55ebcadf4000
After free of second 16kB       : 0x55ebcadf4000
After allocating 6th of 16kB    : 0x55ebcadf4000
After freeing last block        : 0x55ebcadf4000
After allocating a new 18kB     : 0x55ebcadf4000
登入後複製
Linux 上内存分配的工作原理

有 strace 的 brk 的輸出如下:

brk(NULL)                               = 0x5608595b6000
brk(0x5608595d7000)                     = 0x5608595d7000
登入後複製

如您所見,0x21000 已新增至資料欄位的結束位址。您可以從值 0x5608595d7000 中理解這一點。因此分配了大約 0x21000 或 132KB 的記憶體。

這裡有兩點要考慮。第一種是分配超過範例程式碼中指定的數量。另一個是哪一行程式碼導致了提供分配的 brk 呼叫。

位址空間佈局隨機化:ASLR

當您一個接一個地執行上述範例應用程式時,您每次都會看到不同的位址值。以這種方式隨機更改位址空間會使安全攻擊的工作變得非常複雜,並提高了軟體的安全性。

但是,在 32 位架构中,通常使用 8 位来随机化地址空间。增加位数将不合适,因为剩余位上的可寻址区域将非常低。此外,仅使用 8 位组合不会使攻击者的事情变得足够困难。

另一方面,在 64 位体系结构中,由于可以为 ASLR 操作分配的位太多,因此提供了更大的随机性,并且提高了安全程度。

Linux 内核还支持基于 Android 的设备,并且 ASLR 功能在 Android 4.0.3 及更高版本上完全激活。即使仅出于这个原因,也可以说 64 位智能手机比 32 位版本具有显着的安全优势。

通过使用以下命令暂时禁用 ASLR 功能,之前的测试应用程序每次运行时都会返回相同的地址值:

echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
登入後複製

要将其恢复到以前的状态,在同一个文件中写入 2 而不是 0 就足够了。

第二个系统调用:mmap

mmap 是 Linux 上用于内存分配的第二个系统调用。通过 mmap 调用,内存中任何区域的空闲空间都映射到调用进程的地址空间。

在以这种方式完成的内存分配中,当您想使用前面 brk 示例中的 free() 函数返回第二个 16KB 分区时,没有机制可以阻止此操作。从进程的地址空间中删除相关的内存段。它被标记为不再使用并返回系统。

因为与使用 brk 相比,使用 mmap 的内存分配非常慢,所以需要分配 brk。

使用 mmap,内存的任何空闲区域都映射到进程的地址空间,因此在该进程完成之前,已分配空间的内容被重置。如果没有以这种方式进行重置,则属于先前使用相关内存区域的进程的数据也可以被下一个不相关的进程访问。这样就不可能谈论系统中的安全性。

Linux 中内存分配的重要性

内存分配非常重要,尤其是在优化和安全问题上。如上面的示例所示,不完全理解此问题可能意味着破坏系统的安全性。

甚至许多编程语言中存在的类似于 push 和 pop 的概念也是基于内存分配操作的。能够很好地使用和掌握系统内存对于嵌入式系统编程和开发安全和优化的系统架构都是至关重要的。

如果您还想涉足 Linux 内核开发,请考虑首先掌握 C 编程语言。

综上所述,Linux 中的内存分配是一个需要注意和理解的重要问题,特别是对于程序员、内核开发人员和系统架构师而言。熟练掌握内存分配可以提高软件性能和安全性,并在嵌入式系统编程和系统架构方面提供更好的支持。同时,C 编程语言的掌握也是涉足 Linux 内核开发的关键。

以上是Linux 上記憶體分配的工作原理的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1664
14
CakePHP 教程
1423
52
Laravel 教程
1317
25
PHP教程
1268
29
C# 教程
1243
24
Linux體系結構:揭示5個基本組件 Linux體系結構:揭示5個基本組件 Apr 20, 2025 am 12:04 AM

Linux系統的五個基本組件是:1.內核,2.系統庫,3.系統實用程序,4.圖形用戶界面,5.應用程序。內核管理硬件資源,系統庫提供預編譯函數,系統實用程序用於系統管理,GUI提供可視化交互,應用程序利用這些組件實現功能。

git怎麼查看倉庫地址 git怎麼查看倉庫地址 Apr 17, 2025 pm 01:54 PM

要查看 Git 倉庫地址,請執行以下步驟:1. 打開命令行並導航到倉庫目錄;2. 運行 "git remote -v" 命令;3. 查看輸出中的倉庫名稱及其相應的地址。

notepad怎麼運行java代碼 notepad怎麼運行java代碼 Apr 16, 2025 pm 07:39 PM

雖然 Notepad 無法直接運行 Java 代碼,但可以通過借助其他工具實現:使用命令行編譯器 (javac) 編譯代碼,生成字節碼文件 (filename.class)。使用 Java 解釋器 (java) 解釋字節碼,執行代碼並輸出結果。

sublime寫好代碼後如何運行 sublime寫好代碼後如何運行 Apr 16, 2025 am 08:51 AM

在 Sublime 中運行代碼的方法有六種:通過熱鍵、菜單、構建系統、命令行、設置默認構建系統和自定義構建命令,並可通過右鍵單擊項目/文件運行單個文件/項目,構建系統可用性取決於 Sublime Text 的安裝情況。

Linux的主要目的是什麼? Linux的主要目的是什麼? Apr 16, 2025 am 12:19 AM

Linux的主要用途包括:1.服務器操作系統,2.嵌入式系統,3.桌面操作系統,4.開發和測試環境。 Linux在這些領域表現出色,提供了穩定性、安全性和高效的開發工具。

laravel安裝代碼 laravel安裝代碼 Apr 18, 2025 pm 12:30 PM

要安裝 Laravel,需依序進行以下步驟:安裝 Composer(適用於 macOS/Linux 和 Windows)安裝 Laravel 安裝器創建新項目啟動服務訪問應用程序(網址:http://127.0.0.1:8000)設置數據庫連接(如果需要)

git軟件安裝 git軟件安裝 Apr 17, 2025 am 11:57 AM

安裝 Git 軟件包括以下步驟:下載安裝包運行安裝包驗證安裝配置 Git安裝 Git Bash(僅限 Windows)

VSCode怎麼用 VSCode怎麼用 Apr 15, 2025 pm 11:21 PM

Visual Studio Code (VSCode) 是一款跨平台、開源且免費的代碼編輯器,由微軟開發。它以輕量、可擴展性和對眾多編程語言的支持而著稱。要安裝 VSCode,請訪問官方網站下載並運行安裝程序。使用 VSCode 時,可以創建新項目、編輯代碼、調試代碼、導航項目、擴展 VSCode 和管理設置。 VSCode 適用於 Windows、macOS 和 Linux,支持多種編程語言,並通過 Marketplace 提供各種擴展。它的優勢包括輕量、可擴展性、廣泛的語言支持、豐富的功能和版

See all articles