久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

Linux系統(tǒng)內存知識點有哪些

141次閱讀
沒有評論

共計 6908 個字符,預計需要花費 18 分鐘才能閱讀完成。

這篇文章主要介紹 Linux 系統(tǒng)內存知識點有哪些,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!

一、走進 linux 內存

1、內存是什么?

1) 內存又稱主存,是 CPU 能直接尋址的存儲空間,由半導體器件制成

2) 內存的特點是存取速率快

Linux 系統(tǒng)內存知識點有哪些

2、內存的作用

1) 暫時存放 cpu 的運算數(shù)據(jù)

2) 硬盤等外部存儲器交換的數(shù)據(jù)

3) 保障 cpu 計算的穩(wěn)定性和高性能

Linux 系統(tǒng)內存知識點有哪些

二、linux 內存地址空間

1、linux 內存地址空間 Linux 內存管理全貌

Linux 系統(tǒng)內存知識點有哪些

2、內存地址 mdash; mdash; 用戶態(tài) 內核態(tài)

  用戶態(tài):Ring3 運行于用戶態(tài)的代碼則要受到處理器的諸多

  內核態(tài):Ring0 在處理器的存儲保護中,核心態(tài)

  用戶態(tài)切換到內核態(tài)的 3 種方式:系統(tǒng)調用、異常、外設中斷

  區(qū)別:每個進程都有完全屬于自己的,獨立的,不被干擾的內存空間;用戶態(tài)的程序就不能隨意操作內核地址空間,具有一定的安全保護作用;內核態(tài)線程共享內核地址空間;

Linux 系統(tǒng)內存知識點有哪些

3、內存地址 mdash; mdash;MMU 地址轉換

 MMU 是一種硬件電路,它包含兩個部件,一個是分段部件,一個是分頁部件

  分段機制把一個邏輯地址轉換為線性地址

  分頁機制把一個線性地址轉換為物理地址

Linux 系統(tǒng)內存知識點有哪些

4、內存地址 mdash; mdash; 分段機制

1) 段選擇符

  為了方便快速檢索段選擇符,處理器提供了 6 個分段寄存器來緩存段選擇符,它們是:cs,ss,ds,es,fs 和 gs

  段的基地址 (Base Address):在線性地址空間中段的起始地址

  段的界限 (Limit):在虛擬地址空間中,段內可以使用的最大偏移量

2) 分段實現(xiàn)

  邏輯地址的段寄存器中的值提供段描述符,然后從段描述符中得到段基址和段界限,然后加上邏輯地址的偏移量,就得到了線性地址

Linux 系統(tǒng)內存知識點有哪些

5、內存地址 mdash; mdash; 分頁機制(32 位)

  分頁機制是在分段機制之后進行的,它進一步將線性地址轉換為物理地址

 10 位頁目錄,10 位頁表項,12 位頁偏移地址

  單頁的大小為 4KB

Linux 系統(tǒng)內存知識點有哪些

6、用戶態(tài)地址空間

Linux 系統(tǒng)內存知識點有哪些

 TEXT:代碼段可執(zhí)行代碼、字符串字面值、只讀變量

 DATA:數(shù)據(jù)段,映射程序中已經(jīng)初始化的全局變量

 BSS 段:存放程序中未初始化的全局變量

 HEAP:運行時的堆,在程序運行中使用 malloc 申請的內存區(qū)域

 MMAP:共享庫及匿名文件的映射區(qū)域

 STACK:用戶進程棧

7、內核態(tài)地址空間

Linux 系統(tǒng)內存知識點有哪些

  直接映射區(qū):線性空間中從 3G 開始最大 896M 的區(qū)間,為直接內存映射區(qū)

  動態(tài)內存映射區(qū):該區(qū)域由內核函數(shù) vmalloc 來分配

  永久內存映射區(qū):該區(qū)域可訪問高端內存

  固定映射區(qū):該區(qū)域和 4G 的頂端只有 4k 的隔離帶,其每個地址項都服務于特定的用途,如:ACPI_BASE 等

8、進程內存空間

  用戶進程通常情況只能訪問用戶空間的虛擬地址,不能訪問內核空間虛擬地址

  內核空間是由內核負責映射,不會跟著進程變化;內核空間地址有自己對應的頁表,用戶進程各自有不同額頁表

Linux 系統(tǒng)內存知識點有哪些

三、Linux 內存分配算法

內存管理算法 mdash; mdash; 對討厭自己管理內存的人來說是天賜的禮物

1、內存碎片

1)    基本原理

  產(chǎn)生原因:內存分配較小,并且分配的這些小的內存生存周期又較長,反復申請后將產(chǎn)生內存碎片的出現(xiàn)

  優(yōu)點:提高分配速度,便于內存管理,防止內存泄露

  缺點:大量的內存碎片會使系統(tǒng)緩慢,內存使用率低,浪費大

2) 如何避免內存碎片

  少用動態(tài)內存分配的函數(shù) (盡量使用棧空間)

  分配內存和釋放的內存盡量在同一個函數(shù)中

  盡量一次性申請較大的內存,而不要反復申請小內存

  盡可能申請大塊的 2 的指數(shù)冪大小的內存空間

  外部碎片避免 mdash; mdash; 伙伴系統(tǒng)算法

  內部碎片避免 mdash; mdash;slab 算法

  自己進行內存管理工作,設計內存池

2、伙伴系統(tǒng)算法 mdash; mdash; 組織結構

1)    概念

  為內核提供了一種用于分配一組連續(xù)的頁而建立的一種高效的分配策略,并有效的解決了外碎片問題

  分配的內存區(qū)是以頁框為基本單位的

2)    外部碎片

  外部碎片指的是還沒有被分配出去(不屬于任何進程),但由于太小了無法分配給申請內存空間的新進程的內存空閑區(qū)域 3)    組織結構

  把所有的空閑頁分組為 11 個塊鏈表,每個塊鏈表分別包含大小為 1,2,4,8,16,32,64,128,256,512 和 1024 個連續(xù)頁框的頁塊。最大可以申請 1024 個連續(xù)頁,對應 4MB 大小的連續(xù)內存

Linux 系統(tǒng)內存知識點有哪些

3、伙伴系統(tǒng)算法 mdash; mdash; 申請和回收

1)    申請算法

  申請 2^i 個頁塊存儲空間,如果 2^i 對應的塊鏈表有空閑頁塊,則分配給應用

  如果沒有空閑頁塊,則查找 2^(i 1) 對應的塊鏈表是否有空閑頁塊,如果有,則分配 2^i 塊鏈表節(jié)點給應用,另外 2^i 塊鏈表節(jié)點插入到 2^i 對應的塊鏈表中

  如果 2^(i 1) 塊鏈表中沒有空閑頁塊,則重復步驟 2,直到找到有空閑頁塊的塊鏈表

  如果仍然沒有,則返回內存分配失敗

2)    回收算法

  釋放 2^i 個頁塊存儲空間,查找 2^i 個頁塊對應的塊鏈表,是否有與其物理地址是連續(xù)的頁塊,如果沒有,則無需合并

Linux 系統(tǒng)內存知識點有哪些

  如果有,則合并成 2^(i 1)的頁塊,以此類推,繼續(xù)查找下一級塊鏈接,直到不能合并為止

Linux 系統(tǒng)內存知識點有哪些

3)    條件

  兩個塊具有相同的大小

  它們的物理地址是連續(xù)的

  頁塊大小相同

4、如何分配 4M 以上內存?

1)    為何限制大塊內存分配

  分配的內存越大, 失敗的可能性越大

  大塊內存使用場景少

2)    內核中獲取 4M 以上大內存的方法

  修改 MAX_ORDER, 重新編譯內核

  內核啟動選型傳遞 mem= 參數(shù), 如 mem=80M,預留部分內存;然后通過

 request_mem_region 和 ioremap_nocache 將預留的內存映射到模塊中。需要修改內核啟動參數(shù), 無需重新編譯內核. 但這種方法不支持 x86 架構, 只支持 ARM, PowerPC 等非 x86 架構

  在 start_kernel 中 mem_init 函數(shù)之前調用 alloc_boot_mem 函數(shù)預分配大塊內存, 需要重新編譯內核

 vmalloc 函數(shù),內核代碼使用它來分配在虛擬內存中連續(xù)但在物理內存中不一定連續(xù)的內存

5、伙伴系統(tǒng) mdash; mdash; 反碎片機制

1)    不可移動頁

  這些頁在內存中有固定的位置,不能夠移動,也不可回收

  內核代碼段,數(shù)據(jù)段,內核 kmalloc() 出來的內存,內核線程占用的內存等

2)    可回收頁

  這些頁不能移動,但可以刪除。內核在回收頁占據(jù)了太多的內存時或者內存短缺時進行頁面回收 3)    可移動頁

  這些頁可以任意移動,用戶空間應用程序使用的頁都屬于該類別。它們是通過頁表映射的

  當它們移動到新的位置,頁表項也會相應的更新

6、slab 算法 mdash; mdash; 基本原理

1)    基本概念

 Linux 所使用的 slab 分配器的基礎是 Jeff Bonwick 為 SunOS 操作系統(tǒng)首次引入的一種算法

  它的基本思想是將內核中經(jīng)常使用的對象放到高速緩存中,并且由系統(tǒng)保持為初始的可利用狀態(tài)。比如進程描述符,內核中會頻繁對此數(shù)據(jù)進行申請和釋放

2)    內部碎片

  已經(jīng)被分配出去的的內存空間大于請求所需的內存空間 3)    基本目標

  減少伙伴算法在分配小塊連續(xù)內存時所產(chǎn)生的內部碎片

  將頻繁使用的對象緩存起來,減少分配、初始化和釋放對象的時間開銷

  通過著色技術調整對象以更好的使用硬件高速緩存

7、slab 分配器的結構

  由于對象是從 slab 中分配和釋放的,因此單個 slab 可以在 slab 列表之間進行移動

 slabs_empty 列表中的 slab 是進行回收(reaping)的主要備選對象

 slab 還支持通用對象的初始化,從而避免了為同一目而對一個對象重復進行初始化

Linux 系統(tǒng)內存知識點有哪些

8、slab 高速緩存

1)    普通高速緩存

 slab 分配器所提供的小塊連續(xù)內存的分配是通過通用高速緩存實現(xiàn)的

  通用高速緩存所提供的對象具有幾何分布的大小,范圍為 32 到 131072 字節(jié)。

  內核中提供了 kmalloc() 和 kfree() 兩個接口分別進行內存的申請和釋放

2)    專用高速緩存

  內核為專用高速緩存的申請和釋放提供了一套完整的接口,根據(jù)所傳入的參數(shù)為具體的對象分配 slab 緩存

 kmem_cache_create() 用于對一個指定的對象創(chuàng)建高速緩存。它從 cache_cache 普通高速緩存中為新的專有緩存分配一個高速緩存描述符,并把這個描述符插入到高速緩存描述符形成的 cache_chain 鏈表中

 kmem_cache_alloc() 在其參數(shù)所指定的高速緩存中分配一個 slab。相反,kmem_cache_free() 在其參數(shù)所指定的高速緩存中釋放一個 slab

9、內核態(tài)內存池

1)    基本原理

  先申請分配一定數(shù)量的、大小相等 (一般情況下) 的內存塊留作備用

  當有新的內存需求時,就從內存池中分出一部分內存塊,若內存塊不夠再繼續(xù)申請新的內存

  這樣做的一個顯著優(yōu)點是盡量避免了內存碎片,使得內存分配效率得到提升

2)    內核 API

 mempool_create 創(chuàng)建內存池對象

 mempool_alloc 分配函數(shù)獲得該對象

 mempool_free 釋放一個對象

 mempool_destroy 銷毀內存池

Linux 系統(tǒng)內存知識點有哪些

10、用戶態(tài)內存池

1)    C++ 實例

Linux 系統(tǒng)內存知識點有哪些

11、DMA 內存

1)    什么是 DMA

  直接內存訪問是一種硬件機制,它允許外圍設備和主內存之間直接傳輸它們的 I/O 數(shù)據(jù),而不需要系統(tǒng)處理器的參與 2)    DMA 控制器的功能

  能向 CPU 發(fā)出系統(tǒng)保持(HOLD)信號,提出總線接管請求

  當 CPU 發(fā)出允許接管信號后,負責對總線的控制,進入 DMA 方式

  能對存儲器尋址及能修改地址指針,實現(xiàn)對內存的讀寫操作

  能決定本次 DMA 傳送的字節(jié)數(shù),判斷 DMA 傳送是否結束

  發(fā)出 DMA 結束信號,使 CPU 恢復正常工作狀態(tài)

2)    DMA 信號

 DREQ:DMA 請求信號。是外設向 DMA 控制器提出要求,DMA 操作的申請信號

 DACK:DMA 響應信號。是 DMA 控制器向提出 DMA 請求的外設表示已收到請求和正進行處理的信號

 HRQ:DMA 控制器向 CPU 發(fā)出的信號,要求接管總線的請求信號。

 HLDA:CPU 向 DMA 控制器發(fā)出的信號,允許接管總線的應答信號:

Linux 系統(tǒng)內存知識點有哪些

四、內存使用場景

out of memory 的時代過去了嗎?no,內存再充足也不可任性使用。

1、內存的使用場景

 page 管理

 slab(kmalloc、內存池)

  用戶態(tài)內存使用(malloc、relloc 文件映射、共享內存)

  程序的內存 map(棧、堆、code、data)

  內核和用戶態(tài)的數(shù)據(jù)傳遞(copy_from_user、copy_to_user)

  內存映射(硬件寄存器、保留內存)

 DMA 內存

2、用戶態(tài)內存分配函數(shù)

 alloca 是向棧申請內存, 因此無需釋放

 malloc 所分配的內存空間未被初始化,使用 malloc() 函數(shù)的程序開始時 ( 內存空間還沒有被重新分配) 能正常運行,但經(jīng)過一段時間后 (內存空間已被重新分配) 可能會出現(xiàn)問題

 calloc 會將所分配的內存空間中的每一位都初始化為零

 realloc 擴展現(xiàn)有內存空間大小

a)      如果當前連續(xù)內存塊足夠 realloc 的話,只是將 p 所指向的空間擴大,并返回 p 的指針地址。這個時候 q 和 p 指向的地址是一樣的

b)      如果當前連續(xù)內存塊不夠長度,再找一個足夠長的地方,分配一塊新的內存,q,并將 p 指向的內容 copy 到 q,返回 q。并將 p 所指向的內存空間刪除

3、內核態(tài)內存分配函數(shù)

函數(shù)分配原理最大內存其他_get_free_pages 直接對頁框進行操作 4MB 適用于分配較大量的連續(xù)物理內存 kmem_cache_alloc 基于 slab 機制實現(xiàn) 128KB 適合需要頻繁申請釋放相同大小內存塊時使用 kmalloc 基于 kmem_cache_alloc 實現(xiàn) 128KB 最常見的分配方式,需要小于頁框大小的內存時可以使用 vmalloc 建立非連續(xù)物理內存到虛擬地址的映射物理不連續(xù),適合需要大內存,但是對地址連續(xù)性沒有要求的場合 dma_alloc_coherent 基于_alloc_pages 實現(xiàn) 4MB 適用于 DMA 操作 ioremap 實現(xiàn)已知物理地址到虛擬地址的映射適用于物理地址已知的場合,如設備驅動 alloc_bootmem 在啟動 kernel 時,預留一段內存,內核看不見小于物理內存大小,內存管理要求較高

4、malloc 申請內存

  調用 malloc 函數(shù)時,它沿 free_chuck_list 連接表尋找一個大到足以滿足用戶請求所需要的內存塊

Linux 系統(tǒng)內存知識點有哪些

 free_chuck_list 連接表的主要工作是維護一個空閑的堆空間緩沖區(qū)鏈表

  如果空間緩沖區(qū)鏈表沒有找到對應的節(jié)點,需要通過系統(tǒng)調用 sys_brk 延伸進程的棧空間

Linux 系統(tǒng)內存知識點有哪些

5、缺頁異常

  通過 get_free_pages 申請一個或多個物理頁面

  換算 addr 在進程 pdg 映射中所在的 pte 地址

  將 addr 對應的 pte 設置為物理頁面的首地址

  系統(tǒng)調用:Brk mdash; 申請內存小于等于 128kb,do_map mdash; 申請內存大于 128kb

Linux 系統(tǒng)內存知識點有哪些

6、用戶進程訪問內存分析

  用戶態(tài)進程獨占虛擬地址空間,兩個進程的虛擬地址可相同

  在訪問用戶態(tài)虛擬地址空間時,如果沒有映射物理地址,通過系統(tǒng)調用發(fā)出缺頁異常

  缺頁異常陷入內核,分配物理地址空間,與用戶態(tài)虛擬地址建立映射

Linux 系統(tǒng)內存知識點有哪些

7、共享內存

1)    原理

  它允許多個不相關的進程去訪問同一部分邏輯內存

  兩個運行中的進程之間傳輸數(shù)據(jù),共享內存將是一種效率極高的解決方案

  兩個運行中的進程共享數(shù)據(jù),是進程間通信的高效方法,可有效減少數(shù)據(jù)拷貝的次數(shù)

Linux 系統(tǒng)內存知識點有哪些

2)    shm 接口

 shmget 創(chuàng)建共享內存

 shmat 啟動對該共享內存的訪問,并把共享內存連接到當前進程的地址空間

 shmdt 將共享內存從當前進程中分離

五、內存使用那些坑

1、C 內存泄露

  在類的構造函數(shù)和析構函數(shù)中沒有匹配地調用 new 和 delete 函數(shù)    

Linux 系統(tǒng)內存知識點有哪些

  沒有正確地清除嵌套的對象指針

  沒有將基類的析構函數(shù)定義為虛函數(shù)

  當基類的指針指向子類對象時,如果基類的析構函數(shù)不是 virtual,那么子類的析構函數(shù)將不會被調用,子類的資源沒有得到正確釋放,因此造成內存泄露

  缺少拷貝構造函數(shù),按值傳遞會調用(拷貝)構造函數(shù),引用傳遞不會調用

  指向對象的指針數(shù)組不等同于對象數(shù)組,數(shù)組中存放的是指向對象的指針,不僅要釋放每個對象的空間,還要釋放每個指針的空間

  缺少重載賦值運算符,也是逐個成員拷貝的方式復制對象,如果這個類的大小是可變的,那么結果就是造成內存泄露

2、C 野指針

  指針變量沒有初始化

  指針被 free 或 delete 后,沒有設置為 NULL

  指針操作超越了變量的作用范圍,比如返回指向棧內存的指針就是野指針

  訪問空指針(需要做空判斷)

 sizeof 無法獲取數(shù)組的大小

  試圖修改常量,如:char p= 1234 p= 1

3、C 資源訪問沖突

  多線程共享變量沒有用 valotile 修飾

  多線程訪問全局變量未加鎖

  全局變量僅對單進程有效

  多進程寫共享內存數(shù)據(jù),未做同步處理

 mmap 內存映射,多進程不安全

4、STL 迭代器失效

  被刪除的迭代器失效

  添加元素(insert/push_back 等)、刪除元素導致順序容器迭代器失效

錯誤示例:刪除當前迭代器,迭代器會失效

Linux 系統(tǒng)內存知識點有哪些

正確示例:迭代器 erase 時,需保存下一個迭代器

Linux 系統(tǒng)內存知識點有哪些

5、C++ 11 智能指針

 auto_ptr 替換為 unique_ptr   

Linux 系統(tǒng)內存知識點有哪些

使用 make_shared 初始化一個 shared_ptr   

Linux 系統(tǒng)內存知識點有哪些

weak_ptr 智能指針助手(1)原理分析:   

Linux 系統(tǒng)內存知識點有哪些

(2)數(shù)據(jù)結構:

Linux 系統(tǒng)內存知識點有哪些

 (3)使用方法:a. lock() 獲取所管理的對象的強引用指針 b. expired() 檢測所管理的對象是否已經(jīng)釋放 c. get() 訪問智能指針對象

6、C++ 11 更小更快更安全

 std::atomic 原子數(shù)據(jù)類型 多線程安全

 std::array 定長數(shù)組開銷比 array 小和 std::vector 不同的是 array 的長度是固定的,不能動態(tài)拓展

 std::vector vector 瘦身 shrink_to_fit():將 capacity 減少為于 size() 相同的大小

 td::forward_list

forward_list 是單鏈表(std::list 是雙鏈表),只需要順序遍歷的場合,forward_list 能更加節(jié)省內存,插入和刪除的性能高于 list

 std::unordered_map、std::unordered_set 用 hash 實現(xiàn)的無序的容器,插入、刪除和查找的時間復雜度都是 O(1),在不關注容器內元素順序的場合,使用 unordered 的容器能獲得更高的性能六、如何查看內存

  系統(tǒng)中內存使用情況:/proc/meminfo 

Linux 系統(tǒng)內存知識點有哪些

  進程的內存使用情況:/proc/28040/status

  查詢內存總使用率:free

Linux 系統(tǒng)內存知識點有哪些

  查詢進程 cpu 和內存使用占比:top

Linux 系統(tǒng)內存知識點有哪些

  虛擬內存統(tǒng)計:vmstat

Linux 系統(tǒng)內存知識點有哪些

  進程消耗內存占比和排序:ps aux ndash;sort -rss

Linux 系統(tǒng)內存知識點有哪些

  釋放系統(tǒng)內存緩存:/proc/sys/vm/drop_caches 

以上是“Linux 系統(tǒng)內存知識點有哪些”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注丸趣 TV 行業(yè)資訊頻道!

正文完
 
丸趣
版權聲明:本站原創(chuàng)文章,由 丸趣 2023-08-25發(fā)表,共計6908字。
轉載說明:除特殊說明外本站除技術相關以外文章皆由網(wǎng)絡搜集發(fā)布,轉載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 新邵县| 平谷区| 德化县| 兰溪市| 安仁县| 新龙县| 白朗县| 乐清市| 乐安县| 沾化县| 义乌市| 四子王旗| 交城县| 湖北省| 绵阳市| 聂荣县| 金塔县| 攀枝花市| 澄迈县| 囊谦县| 句容市| 望城县| 永昌县| 乐昌市| 彰化县| 沂源县| 枣强县| 抚州市| 盐城市| 修文县| 马鞍山市| 屏南县| 穆棱市| 池州市| 沽源县| 托克托县| 青龙| 大邑县| 沁源县| 勐海县| 济宁市|