www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁 > > 充電吧
[導(dǎo)讀]Linux 內(nèi)存 在 Linux 中,用戶內(nèi)存和內(nèi)核內(nèi)存是獨(dú)立的,在各自的地址空間實(shí)現(xiàn)。地址空間是虛擬的,就是說地址是從物理內(nèi)存中抽象出來的(通過一個(gè)簡短描述的過程)。由于地址空間是虛擬的,所以可以存

Linux 內(nèi)存

在 Linux 中,用戶內(nèi)存和內(nèi)核內(nèi)存是獨(dú)立的,在各自的地址空間實(shí)現(xiàn)。地址空間是虛擬的,就是說地址是從物理內(nèi)存中抽象出來的(通過一個(gè)簡短描述的過程)。由于地址空間是虛擬的,所以可以存在很多。事實(shí)上,內(nèi)核本身駐留在一個(gè)地址空間中,每個(gè)進(jìn)程駐留在自己的地址空間。這些地址空間由虛擬內(nèi)存地址組成,允許一些帶有獨(dú)立地址空間的進(jìn)程指向一個(gè)相對(duì)較小的物理地址空間(在機(jī)器的物理內(nèi)存中)。不僅僅是方便,而且更安全。因?yàn)槊總€(gè)地址空間是獨(dú)立且隔離的,因此很安全。

但是與安全性相關(guān)聯(lián)的成本很高。因?yàn)槊總€(gè)進(jìn)程(和內(nèi)核)會(huì)有相同地址指向不同的物理內(nèi)存區(qū)域,不可能立即共享內(nèi)存。幸運(yùn)的是,有一些解決方案。用戶進(jìn)程可以通過 Portable Operating System Interface for UNIX? (POSIX) 共享的內(nèi)存機(jī)制(shmem)共享內(nèi)存,但有一點(diǎn)要說明,每個(gè)進(jìn)程可能有一個(gè)指向相同物理內(nèi)存區(qū)域的不同虛擬地址。

虛擬內(nèi)存到物理內(nèi)存的映射通過頁表完成,這是在底層軟件中實(shí)現(xiàn)的(見圖 1)。硬件本身提供映射,但是內(nèi)核管理表及其配置。注意這里的顯示,進(jìn)程可能有一個(gè)大的地址空間,但是很少見,就是說小的地址空間的區(qū)域(頁面)通過頁表指向物理內(nèi)存。這允許進(jìn)程僅為隨時(shí)需要的網(wǎng)頁指定大的地址空間。


圖 1. 頁表提供從虛擬地址到物理地址的映射

由于缺乏為進(jìn)程定義內(nèi)存的能力,底層物理內(nèi)存被過度使用。通過一個(gè)稱為 paging(然而,在 Linux 中通常稱為 swap)的進(jìn)程,很少使用的頁面將自動(dòng)移到一個(gè)速度較慢的存儲(chǔ)設(shè)備(比如磁盤),來容納需要被訪問的其它頁面(見圖 2 )。這一行為允許,在將很少使用的頁面遷移到磁盤來提高物理內(nèi)存使用的同時(shí),計(jì)算機(jī)中的物理內(nèi)存為應(yīng)用程序更容易需要的頁面提供服務(wù)。注意,一些頁面可以指向文件,在這種情況下,如果頁面是臟(dirty)的,數(shù)據(jù)將被沖洗,如果頁面是干凈的(clean),直接丟掉。


圖 2. 通過將很少使用的頁面遷移到速度慢且便宜的存儲(chǔ)器,交換使物理內(nèi)存空間得到了更好的利用

MMU-less 架構(gòu)

不是所有的處理器都有 MMU。因此,uClinux 發(fā)行版(微控制器 Linux)支持操作的一個(gè)地址空間。該架構(gòu)缺乏 MMU 提供的保護(hù),但是允許 Linux 運(yùn)行另一類處理器。關(guān)于 uClinux 的詳細(xì)信息見 參考資料。

選擇一個(gè)頁面來交換存儲(chǔ)的過程被稱為一個(gè)頁面置換算法,可以通過使用許多算法(至少是最近使用的)來實(shí)現(xiàn)。該進(jìn)程在請(qǐng)求存儲(chǔ)位置時(shí)發(fā)生,存儲(chǔ)位置的頁面不在存儲(chǔ)器中(在存儲(chǔ)器管理單元 [MMU] 中無映射)。這個(gè)事件被稱為一個(gè)頁面錯(cuò)誤 并被硬件(MMU)刪除,出現(xiàn)頁面錯(cuò)誤中斷后該事件由防火墻管理。該棧的詳細(xì)說明見 圖 3。

Linux 提供一個(gè)有趣的交換實(shí)現(xiàn),該實(shí)現(xiàn)提供許多有用的特性。Linux 交換系統(tǒng)允許創(chuàng)建和使用多個(gè)交換分區(qū)和優(yōu)先權(quán),這支持存儲(chǔ)設(shè)備上的交換層次結(jié)構(gòu),這些存儲(chǔ)設(shè)備提供不同的性能參數(shù)(例如,固態(tài)磁盤 [SSD] 上的一級(jí)交換和速度較慢的存儲(chǔ)設(shè)備上的較大的二級(jí)交換)。為 SSD 交換附加一個(gè)更高的優(yōu)先級(jí)使其可以使用直至耗盡;直到那時(shí),頁面才能被寫入優(yōu)先級(jí)較低的交換分區(qū)。


圖 3. 地址空間和虛擬 - 物理地址映射的元素

并不是所有的頁面都適合交換。考慮到響應(yīng)中斷的內(nèi)核代碼或者管理頁表和交換邏輯的代碼,顯然,這些頁面決不能被換出,因此它們是固定的,或者是永久地駐留在內(nèi)存中。盡管內(nèi)核頁面不需要進(jìn)行交換,然而用戶頁面需要,但是它們可以被固定,通過 mlock(或 mlockall)函數(shù)來鎖定頁面。這就是用戶空間內(nèi)存訪問函數(shù)的目的。如果內(nèi)核假設(shè)一個(gè)用戶傳遞的地址是有效的且是可訪問的,最終可能會(huì)出現(xiàn)內(nèi)核嚴(yán)重錯(cuò)誤(kernel panic)(例如,因?yàn)橛脩繇撁姹粨Q出,而導(dǎo)致內(nèi)核中的頁面錯(cuò)誤)。該應(yīng)用程序編程接口(API)確保這些邊界情況被妥善處理。


內(nèi)核 API

現(xiàn)在,讓我們來研究一下用戶操作用戶內(nèi)存的內(nèi)核 API。請(qǐng)注意,這涉及內(nèi)核和用戶空間接口,而下一部分將研究其他的一些內(nèi)存 API。用戶空間內(nèi)存訪問函數(shù)在表 1 中列出。


表 1. 用戶空間內(nèi)存訪問 API
函數(shù) 描述 access_ok 檢查用戶空間內(nèi)存指針的有效性 get_user 從用戶空間獲取一個(gè)簡單變量 put_user 輸入一個(gè)簡單變量到用戶空間 clear_user 清除用戶空間中的一個(gè)塊,或者將其歸零。 copy_to_user 將一個(gè)數(shù)據(jù)塊從內(nèi)核復(fù)制到用戶空間 copy_from_user 將一個(gè)數(shù)據(jù)塊從用戶空間復(fù)制到內(nèi)核 strnlen_user 獲取內(nèi)存空間中字符串緩沖區(qū)的大小 strncpy_from_user 從用戶空間復(fù)制一個(gè)字符串到內(nèi)核

正如您所期望的,這些函數(shù)的實(shí)現(xiàn)架構(gòu)是獨(dú)立的。例如在 x86 架構(gòu)中,您可以使用 ./linux/arch/x86/lib/usercopy_32.c 和 usercopy_64.c 中的源代碼找到這些函數(shù)以及在 ./linux/arch/x86/include/asm/uaccess.h 中定義的字符串。

當(dāng)數(shù)據(jù)移動(dòng)函數(shù)的規(guī)則涉及到復(fù)制調(diào)用的類型時(shí)(簡單 VS. 聚集),這些函數(shù)的作用如圖 4 所示。


圖 4. 使用 User Space Memory Access API 進(jìn)行數(shù)據(jù)移動(dòng)

access_ok 函數(shù)

您可以使用 access_ok 函數(shù)在您想要訪問的用戶空間檢查指針的有效性。調(diào)用函數(shù)提供指向數(shù)據(jù)塊的開始的指針、塊大小和訪問類型(無論這個(gè)區(qū)域是用來讀還是寫的)。函數(shù)原型定義如下:

access_ok( type, addr, size );

type 參數(shù)可以被指定為 VERIFY_READVERIFY_WRITE。VERIFY_WRITE 也可以識(shí)別內(nèi)存區(qū)域是否可讀以及可寫(盡管訪問仍然會(huì)生成 -EFAULT)。該函數(shù)簡單檢查地址可能是在用戶空間,而不是內(nèi)核。

get_user 函數(shù)

要從用戶空間讀取一個(gè)簡單變量,可以使用 get_user 函數(shù),該函數(shù)適用于簡單數(shù)據(jù)類型,比如,charint,但是像結(jié)構(gòu)體這類較大的數(shù)據(jù)類型,必須使用 copy_from_user 函數(shù)。該原型接受一個(gè)變量(存儲(chǔ)數(shù)據(jù))和一個(gè)用戶空間地址來進(jìn)行 Read 操作:

get_user( x, ptr );

get_user 函數(shù)將映射到兩個(gè)內(nèi)部函數(shù)其中的一個(gè)。在系統(tǒng)內(nèi)部,這個(gè)函數(shù)決定被訪問變量的大?。ǜ鶕?jù)提供的變量存儲(chǔ)結(jié)果)并通過 __get_user_x 形成一個(gè)內(nèi)部調(diào)用。成功時(shí)該函數(shù)返回 0,一般情況下,get_userput_user 函數(shù)比它們的塊復(fù)制副本要快一些,如果是小類型被移動(dòng)的話,應(yīng)該用它們。

put_user 函數(shù)

您可以使用 put_user 函數(shù)來將一個(gè)簡單變量從內(nèi)核寫入用戶空間。和 get_user 一樣,它接受一個(gè)變量(包含要寫的值)和一個(gè)用戶空間地址作為寫目標(biāo):

put_user( x, ptr );

get_user 一樣,put_user 函數(shù)被內(nèi)部映射到 put_user_x 函數(shù),成功時(shí),返回 0,出現(xiàn)錯(cuò)誤時(shí),返回 -EFAULT

clear_user 函數(shù)

clear_user 函數(shù)被用于將用戶空間的內(nèi)存塊清零。該函數(shù)采用一個(gè)指針(用戶空間中)和一個(gè)型號(hào)進(jìn)行清零,這是以字節(jié)定義的:

clear_user( ptr, n );

在內(nèi)部,clear_user 函數(shù)首先檢查用戶空間指針是否可寫(通過 access_ok),然后調(diào)用內(nèi)部函數(shù)(通過內(nèi)聯(lián)組裝方式編碼)來執(zhí)行 Clear 操作。使用帶有 repeat 前綴的字符串指令將該函數(shù)優(yōu)化成一個(gè)非常緊密的循環(huán)。它將返回不可清除的字節(jié)數(shù),如果操作成功,則返回 0。

copy_to_user 函數(shù)

copy_to_user 函數(shù)將數(shù)據(jù)塊從內(nèi)核復(fù)制到用戶空間。該函數(shù)接受一個(gè)指向用戶空間緩沖區(qū)的指針、一個(gè)指向內(nèi)存緩沖區(qū)的指針、以及一個(gè)以字節(jié)定義的長度。該函數(shù)在成功時(shí),返回 0,否則返回一個(gè)非零數(shù),指出不能發(fā)送的字節(jié)數(shù)。

copy_to_user( to, from, n );

檢查了向用戶緩沖區(qū)寫入的功能之后(通過 access_ok),內(nèi)部函數(shù) __copy_to_user 被調(diào)用,它反過來調(diào)用 __copy_from_user_inatomic(在 ./linux/arch/x86/include/asm/uaccess_XX.h 中。其中 XX 是 32 或者 64 ,具體取決于架構(gòu)。)在確定了是否執(zhí)行 1、2 或 4 字節(jié)復(fù)制之后,該函數(shù)調(diào)用 __copy_to_user_ll,這就是實(shí)際工作進(jìn)行的地方。在損壞的硬件中(在 i486 之前,WP 位在管理模式下不可用),頁表可以隨時(shí)替換,需要將想要的頁面固定到內(nèi)存,使它們?cè)谔幚頃r(shí)不被換出。i486 之后,該過程只不過是一個(gè)優(yōu)化的副本。

copy_from_user 函數(shù)

copy_from_user 函數(shù)將數(shù)據(jù)塊從用戶空間復(fù)制到內(nèi)核緩沖區(qū)。它接受一個(gè)目的緩沖區(qū)(在內(nèi)核空間)、一個(gè)源緩沖區(qū)(從用戶空間)和一個(gè)以字節(jié)定義的長度。和 copy_to_user 一樣,該函數(shù)在成功時(shí),返回 0 ,否則返回一個(gè)非零數(shù),指出不能復(fù)制的字節(jié)數(shù)。

copy_from_user( to, from, n );

該函數(shù)首先檢查從用戶空間源緩沖區(qū)讀取的能力(通過 access_ok),然后調(diào)用 __copy_from_user,最后調(diào)用 __copy_from_user_ll。從此開始,根據(jù)構(gòu)架,為執(zhí)行從用戶緩沖區(qū)到內(nèi)核緩沖區(qū)的零拷貝(不可用字節(jié))而進(jìn)行一個(gè)調(diào)用。優(yōu)化組裝函數(shù)包含管理功能。

strnlen_user 函數(shù)

strnlen_user 函數(shù)也能像 strnlen 那樣使用,但前提是緩沖區(qū)在用戶空間可用。strnlen_user 函數(shù)帶有兩個(gè)參數(shù):用戶空間緩沖區(qū)地址和要檢查的最大長度。

strnlen_user( src, n );

strnlen_user 函數(shù)首先通過調(diào)用 access_ok 檢查用戶緩沖區(qū)是否可讀。如果是 strlen 函數(shù)被調(diào)用,max length 參數(shù)則被忽略。

strncpy_from_user 函數(shù)

strncpy_from_user 函數(shù)將一個(gè)字符串從用戶空間復(fù)制到一個(gè)內(nèi)核緩沖區(qū),給定一個(gè)用戶空間源地址和最大長度。

strncpy_from_user( dest, src, n );

由于從用戶空間復(fù)制,該函數(shù)首先使用 access_ok 檢查緩沖區(qū)是否可讀。和 copy_from_user 一樣,該函數(shù)作為一個(gè)優(yōu)化組裝函數(shù)(在 ./linux/arch/x86/lib/usercopy_XX.c 中)實(shí)現(xiàn)。


內(nèi)存映射的其他模式

上面部分探討了在內(nèi)核和用戶空間之間移動(dòng)數(shù)據(jù)的方法(使用內(nèi)核初始化操作)。Linux 還提供一些其他的方法,用于在內(nèi)核和用戶空間中移動(dòng)數(shù)據(jù)。盡管這些方法未必能夠提供與用戶空間內(nèi)存訪問函數(shù)相同的功能,但是它們?cè)诘刂房臻g之間映射內(nèi)存的功能是相似的。

在用戶空間,注意,由于用戶進(jìn)程出現(xiàn)在單獨(dú)的地址空間,在它們之間移動(dòng)數(shù)據(jù)必須經(jīng)過某種進(jìn)程間通信機(jī)制。Linux 提供各種模式(比如,消息隊(duì)列),但是最著名的是 POSIX 共享內(nèi)存(shmem)。該機(jī)制允許進(jìn)程創(chuàng)建一個(gè)內(nèi)存區(qū)域,然后同一個(gè)或多個(gè)進(jìn)程共享該區(qū)域。注意,每個(gè)進(jìn)程可能在其各自的地址空間中映射共享內(nèi)存區(qū)域到不同地址。因此需要相對(duì)的尋址偏移(offset addressing)。

mmap 函數(shù)允許一個(gè)用戶空間應(yīng)用程序在虛擬地址空間中創(chuàng)建一個(gè)映射,該功能在某個(gè)設(shè)備驅(qū)動(dòng)程序類中是常見的,允許將物理設(shè)備內(nèi)存映射到進(jìn)程的虛擬地址空間。在一個(gè)驅(qū)動(dòng)程序中,mmap 函數(shù)通過 remap_pfn_range 內(nèi)核函數(shù)實(shí)現(xiàn),它提供設(shè)備內(nèi)存到用戶地址空間的線性映射。


結(jié)束語

本文討論了 Linux 中的內(nèi)存管理主題,然后討論了使用這些概念的用戶空間內(nèi)存訪問函數(shù)。在用戶空間和內(nèi)核空間之間移動(dòng)數(shù)據(jù)并沒有表面上看起來那么簡單,但是 Linux 包含一個(gè)簡單的 API 集合,跨平臺(tái)為您管理這個(gè)復(fù)雜的任務(wù)。


參考資料

學(xué)習(xí)

Red Hat's Linux System Administration Primer 提供一個(gè)很好的虛擬內(nèi)存總結(jié)。

關(guān)于 Linux 交換空間的一切 討論了交換的目的、交換駐留的地方、以及用于管理交換空間的各種命令。

為了提高緩存性能,制定了一個(gè) 壓縮緩存模式。在這個(gè)模式中,交換磁盤事實(shí)上是一個(gè)快速內(nèi)存磁盤,頁面根據(jù)詞條進(jìn)行壓縮來提高存儲(chǔ)效率。

Linux 內(nèi)存管理的一個(gè)最好的來源是設(shè)備驅(qū)動(dòng)程序?qū)毜洌篖inux Device Drivers,第 3 版。

內(nèi)核和用戶空間頁面的一個(gè)不同是,內(nèi)核在內(nèi)存中是永久的,而用戶空間頁面可以被換出到一個(gè)存儲(chǔ)設(shè)備。通過使用 mlock()mlockall() 系統(tǒng)調(diào)用可以實(shí)現(xiàn)將一個(gè)進(jìn)程的部分虛擬空間鎖進(jìn)內(nèi)存。

并不是所有的處理器都有一個(gè) MMU。Linux 通過 uClinux 發(fā)行版來支持這些構(gòu)架。uClinux 是一個(gè)關(guān)注這些沒有 MMU 的架構(gòu)的項(xiàng)目,比如微控制器。

關(guān)于內(nèi)存管理主題,維基百科提供了很多有用的資源,其中包括 虛擬內(nèi)存、分頁、頁表、以及 頁面置換算法。

在 developerWorks Linux 專區(qū) 尋找為 Linux 開發(fā)人員(包括 Linux 新手入門)準(zhǔn)備的更多參考資料,查閱我們 最受歡迎的文章和教程。

在 developerWorks 上查閱所有 Linux 技巧 和 Linux 教程。

隨時(shí)關(guān)注 developerWorks 技術(shù)活動(dòng)和網(wǎng)絡(luò)廣播。

觀看 developerWorks 演示中心,包括面向初學(xué)者的產(chǎn)品安裝和設(shè)置演示,以及為經(jīng)驗(yàn)豐富的開發(fā)人員提供的高級(jí)功能。

在 Twitter 上關(guān)注 developerWorks,或者訂閱 Linux tweets on developerWorks 的提要。

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

CPU親和度通過限制進(jìn)程或線程可以運(yùn)行的CPU核心集合,使得它們只能在指定的CPU核心上執(zhí)行。這可以減少CPU緩存的失效次數(shù),提高緩存命中率,從而提升系統(tǒng)性能。

關(guān)鍵字: Linux 嵌入式

在Linux系統(tǒng)性能優(yōu)化中,內(nèi)存管理與網(wǎng)絡(luò)連接處理是兩大核心領(lǐng)域。vm.swappiness與net.core.somaxconn作為關(guān)鍵內(nèi)核參數(shù),直接影響系統(tǒng)在高負(fù)載場(chǎng)景下的穩(wěn)定性與響應(yīng)速度。本文通過實(shí)戰(zhàn)案例解析這兩個(gè)...

關(guān)鍵字: Linux 內(nèi)存管理

對(duì)于LLM,我使用b谷歌Gemini的免費(fèi)層,所以唯一的成本是n8n托管。在使用了n8n Cloud的免費(fèi)積分后,我決定將其托管在Railway上(5美元/月)。然而,由于n8n是開源的,您可以在自己的服務(wù)器上托管它,而...

關(guān)鍵字: 人工智能 n8n Linux

在Linux系統(tǒng)管理中,權(quán)限控制是安全運(yùn)維的核心。本文通過解析/etc/sudoers文件配置與組策略的深度應(yīng)用,結(jié)合某金融企業(yè)生產(chǎn)環(huán)境案例(成功攔截98.7%的非法提權(quán)嘗試),揭示精細(xì)化權(quán)限管理的關(guān)鍵技術(shù)點(diǎn),包括命令別...

關(guān)鍵字: Linux 用戶權(quán)限 sudoers文件

Linux內(nèi)核中的信號(hào)量(Semaphore)是一種用于資源管理的同步原語,它允許多個(gè)進(jìn)程或線程對(duì)共享資源進(jìn)行訪問控制。信號(hào)量的主要作用是限制對(duì)共享資源的并發(fā)訪問數(shù)量,從而防止系統(tǒng)過載和數(shù)據(jù)不一致的問題。

關(guān)鍵字: Linux 嵌入式

在云計(jì)算與容器化技術(shù)蓬勃發(fā)展的今天,Linux網(wǎng)絡(luò)命名空間(Network Namespace)已成為構(gòu)建輕量級(jí)虛擬網(wǎng)絡(luò)的核心組件。某頭部互聯(lián)網(wǎng)企業(yè)通過命名空間技術(shù)將測(cè)試環(huán)境資源消耗降低75%,故障隔離效率提升90%。本...

關(guān)鍵字: Linux 云計(jì)算

在Linux內(nèi)核4.18+和主流發(fā)行版(RHEL 8/Ubuntu 20.04+)全面轉(zhuǎn)向nftables的背景下,某電商平臺(tái)通過遷移將防火墻規(guī)則處理效率提升40%,延遲降低65%。本文基于真實(shí)生產(chǎn)環(huán)境案例,詳解從ipt...

關(guān)鍵字: nftables Linux

在Linux設(shè)備驅(qū)動(dòng)開發(fā)中,等待隊(duì)列(Wait Queue)是實(shí)現(xiàn)進(jìn)程睡眠與喚醒的核心機(jī)制,它允許進(jìn)程在資源不可用時(shí)主動(dòng)放棄CPU,進(jìn)入可中斷睡眠狀態(tài),待資源就緒后再被喚醒。本文通過C語言模型解析等待隊(duì)列的實(shí)現(xiàn)原理,結(jié)合...

關(guān)鍵字: 驅(qū)動(dòng)開發(fā) C語言 Linux

在Unix/Linux進(jìn)程間通信中,管道(pipe)因其簡單高效被廣泛使用,但默認(rèn)的半雙工特性和無同步機(jī)制容易導(dǎo)致數(shù)據(jù)競爭。本文通過父子進(jìn)程雙向通信案例,深入分析互斥鎖與狀態(tài)機(jī)在管道同步中的應(yīng)用,實(shí)現(xiàn)100%可靠的數(shù)據(jù)傳...

關(guān)鍵字: 管道通信 父子進(jìn)程 Linux

RTOS :RTOS的核心優(yōu)勢(shì)在于其實(shí)時(shí)性。它采用搶占式調(diào)度策略,確保高優(yōu)先級(jí)任務(wù)能夠立即獲得CPU資源,從而在最短時(shí)間內(nèi)完成處理。RTOS的實(shí)時(shí)性是通過嚴(yán)格的時(shí)間管理和任務(wù)調(diào)度算法實(shí)現(xiàn)的,能夠滿足對(duì)時(shí)間敏感性要求極高的...

關(guān)鍵字: Linux RTOS
關(guān)閉