當前位置:首頁 » 操作系統 » linux文件機制

linux文件機制

發布時間: 2023-01-07 02:41:52

linux cgroup機制

Cgroup是control group的縮寫,是Linux內核提供的一種用於限制,記錄,隔離進程組所使用物理資源(cpu,memory,io等)的機制。

cgroup提供了一系列的功能用於對Linux系統資源進行管理和限制,主要功能包括如下

1:限制進程組可以使用的資源數量,例如進程組對內存的使用上限。

2:進程組的執行優先順序限制。

3:記錄進程組所使用的資源數量,例如進程組所使用的cpu時間。

4:進程組隔離的能力。

在cgroup中有一些基本定義或概念

1:Task,理解為系統中需要被控制的進程。

2:Subsystem,可以被控制的資源系統,例如cpu,IO,內存等。

3:Cgroup,按照某種控制標准而劃分而成的控制族。

4:hierarchy,Cgroup可以組織成樹狀結構,子節點繼承父節點的控制標准。

在系統中創建新的hierarchy時,系統中的所有任務都屬於該層級的默認cgroup(root group)的成員。

一個子系統只能附加到一個層級上。

一個層級可以附加多個子系統。

一個任務可以是cgroup的成員,但這些cgroup必須在不同的hierarchy中。

任務創建的子任務(進程),子進程自動成為父進程cgroup的成員。

關系圖如下:

blkio -- 這個子系統為塊設備設定輸入/輸出限制,比如物理設備(磁碟,固態硬碟,USB 等等)。

cpu -- 這個子系統使用調度程序提供對 CPU 的 cgroup 任務訪問

cpuacct -- 這個子系統自動生成 cgroup 中任務所使用的 CPU 報告。

cpuset -- 這個子系統為 cgroup 中的任務分配獨立 CPU(在多核系統)和內存節點。

devices -- 這個子系統可允許或者拒絕 cgroup 中的任務訪問設備。

freezer -- 這個子系統掛起或者恢復 cgroup 中的任務。

memory -- 這個子系統設定 cgroup 中任務使用的內存限制,並自動生成由那些任務使用的內存資源報告。

net_cls -- 這個子系統使用等級識別符(classid)標記網路數據包,可允許 Linux 流量控製程序(tc)識別從具體 cgroup 中生成的數據包。

ns -- 名稱空間子系統。

Linux系統中最多可以建12棵cgroup層級樹(每棵樹關聯一個子系統),也可以最少建一顆cgroup層級樹(關聯所有12個控制子系統)

可以通過mount命令完成

1.掛載一顆和所有subsystem關聯的cgroup樹到/sys/fs/cgroup

mount -t cgroup

xxx /sys/fs/cgroup

2.掛載一顆和cpuset

subsystem關聯的cgroup樹到/sys/fs/cgroup/cpuset

mkdir

/sys/fs/cgroup/cpuset

mount -t cgroup -o

cpuset xxx /sys/fs/cgroup/cpuset

3.掛載一顆與cpu和cpuacct

subsystem關聯的cgroup樹到/sys/fs/cgroup/cpu,cpuacct

mkdir

/sys/fs/cgroup/cpu,cpuacct

mount -t cgroup -o

cpu,cpuacct xxx /sys/fs/cgroup/cpu,cpuacct

4.掛載一棵cgroup樹,但不關聯任何subsystem

mkdir

/sys/fs/cgroup/systemd

mount -t cgroup -o

none,name=systemd xxx /sys/fs/cgroup/system

通過mount可以查看到cgroup的默認掛載點

每個目錄下,其中的文件描述了如何對資源進行限制。

在每個進程的/proc/$pid/cgroup文件中,描述了進程於cgroup的關系:

第一列描述cgroup的樹ID(該ID可以在/proc/cgroups中一一對應);第二列描述綁定的所有子系統;第三列描述進程在cgroup中的路徑。

當我們對某個任務需要進行限制時,不推薦直接在cgroup的各個子系統的root下修改配置,而是在對應的層級下建立單獨的控制節點。

例如如下,在cpu目錄下建立我們自己的子目錄:

進入我們創建的子目錄後,會看到系統已經創建好了資源控制文件,此時只需要修改這些配置文件滿足要求既可以。

要控制我們的進程,只需要將進程ID添加到tasks配置文件中即可以。

Ⅱ [轉]淺談Linux下的零拷貝機制

維基上是這么描述零拷貝的:零拷貝描述的是CPU不執行拷貝數據從一個存儲區域到另一個存儲區域的任務,這通常用於通過網路傳輸一個文件時以減少CPU周期和內存帶寬。

減少甚至完全避免不必要的CPU拷貝,從而讓CPU解脫出來去執行其他的任務
減少內存帶寬的佔用
通常零拷貝技術還能夠減少用戶空間和操作系統內核空間之間的上下文切換

從Linux系統上看,除了引導系統的BIN區,整個內存空間主要被分成兩個部分: 內核空間(Kernel space) 用戶空間(User space) 。「用戶空間」和「內核空間」的空間、操作許可權以及作用都是不一樣的。
內核空間是Linux自身使用的內存空間,主要提供給程序調度、內存分配、連接硬體資源等程序邏輯使用;
用戶空間則是提供給各個進程的主要空間。用戶空間不具有訪問內核空間資源的許可權,因此如果應用程序需要使用到內核空間的資源,則需要通過系統調用來完成:從用戶空間切換到內核空間,然後在完成相關操作後再從內核空間切換回用戶空間。

① 直接 I/O:對於這種數據傳輸方式來說,應用程序可以直接訪問硬體存儲,操作系統內核只是輔助數據傳輸。這種方式依舊存在用戶空間和內核空間的上下文切換,但是硬體上的數據不會拷貝一份到內核空間,而是直接拷貝至了用戶空間,因此直接I/O不存在內核空間緩沖區和用戶空間緩沖區之間的數據拷貝。

② 在數據傳輸過程中,避免數據在用戶空間緩沖區和系統內核空間緩沖區之間的CPU拷貝,以及數據在系統內核空間內的CPU拷貝。本文主要討論的就是該方式下的零拷貝機制。

③ -on-write(寫時復制技術):在某些情況下,Linux操作系統的內核空間緩沖區可能被多個應用程序所共享,操作系統有可能會將用戶空間緩沖區地址映射到內核空間緩存區中。當應用程序需要對共享的數據進行修改的時候,才需要真正地拷貝數據到應用程序的用戶空間緩沖區中,並且對自己用戶空間的緩沖區的數據進行修改不會影響到其他共享數據的應用程序。所以,如果應用程序不需要對數據進行任何修改的話,就不會存在數據從系統內核空間緩沖區拷貝到用戶空間緩沖區的操作。

下面我們通過一個Java非常常見的應用場景:將系統中的文件發送到遠端(該流程涉及:磁碟上文件 ——> 內存(位元組數組) ——> 傳輸給用戶/網路)來詳細展開傳統I/O操作和通過零拷貝來實現的I/O操作。

① 發出read系統調用:導致用戶空間到內核空間的上下文切換(第一次上下文切換)。通過DMA引擎將文件中的數據從磁碟上讀取到內核空間緩沖區(第一次拷貝: hard drive ——> kernel buffer)。
② 將內核空間緩沖區的數據拷貝到用戶空間緩沖區(第二次拷貝: kernel buffer ——> user buffer),然後read系統調用返回。而系統調用的返回又會導致一次內核空間到用戶空間的上下文切換(第二次上下文切換)。
③ 發出write系統調用:導致用戶空間到內核空間的上下文切換(第三次上下文切換)。將用戶空間緩沖區中的數據拷貝到內核空間中與socket相關聯的緩沖區中(即,第②步中從內核空間緩沖區拷貝而來的數據原封不動的再次拷貝到內核空間的socket緩沖區中。)(第三次拷貝: user buffer ——> socket buffer)。
④ write系統調用返回,導致內核空間到用戶空間的再次上下文切換(第四次上下文切換)。通過DMA引擎將內核緩沖區中的數據傳遞到協議引擎(第四次拷貝: socket buffer ——> protocol engine),這次拷貝是一個獨立且非同步的過程。

Q: 你可能會問獨立和非同步這是什麼意思?難道是調用會在數據被傳輸前返回?
A: 事實上調用的返回並不保證數據被傳輸;它甚至不保證傳輸的開始。它只是意味著將我們要發送的數據放入到了一個待發送的隊列中,在我們之前可能有許多數據包在排隊。除非驅動器或硬體實現優先順序環或隊列,否則數據是以先進先出的方式傳輸的。

總的來說,傳統的I/O操作進行了4次用戶空間與內核空間的上下文切換,以及4次數據拷貝。其中4次數據拷貝中包括了2次DMA拷貝和2次CPU拷貝。

Q: 傳統I/O模式為什麼將數據從磁碟讀取到內核空間緩沖區,然後再將數據從內核空間緩沖區拷貝到用戶空間緩沖區了?為什麼不直接將數據從磁碟讀取到用戶空間緩沖區就好?
A: 傳統I/O模式之所以將數據從磁碟讀取到內核空間緩沖區而不是直接讀取到用戶空間緩沖區,是為了減少磁碟I/O操作以此來提高性能。因為OS會根據局部性原理在一次read()系統調用的時候預讀取更多的文件數據到內核空間緩沖區中,這樣當下一次read()系統調用的時候發現要讀取的數據已經存在於內核空間緩沖區中的時候只要直接拷貝數據到用戶空間緩沖區中即可,無需再進行一次低效的磁碟I/O操作(注意:磁碟I/O操作的速度比直接訪問內存慢了好幾個數量級)。

Q: 既然系統內核緩沖區能夠減少磁碟I/O操作,那麼我們經常使用的BufferedInputStream緩沖區又是用來幹啥的?
A: BufferedInputStream的作用是會根據情況自動為我們預取更多的數據到它自己維護的一個內部位元組數據緩沖區中,這樣做能夠減少系統調用的次數以此來提供性能。

總的來說內核空間緩沖區的一大用處是為了減少磁碟I/O操作,因為它會從磁碟中預讀更多的數據到緩沖區中。而BufferedInputStream的用處是減少「系統調用」。

DMA(Direct Memory Access) ———— 直接內存訪問 :DMA是允許外設組件將I/O數據直接傳送到主存儲器中並且傳輸不需要CPU的參與,以此將CPU解放出來去完成其他的事情。
而用戶空間與內核空間之間的數據傳輸並沒有類似DMA這種可以不需要CPU參與的傳輸工具,因此用戶空間與內核空間之間的數據傳輸是需要CPU全程參與的。所有也就有了通過零拷貝技術來減少和避免不必要的CPU數據拷貝過程。

① 發出sendfile系統調用,導致用戶空間到內核空間的上下文切換(第一次上下文切換)。通過DMA引擎將磁碟文件中的內容拷貝到內核空間緩沖區中(第一次拷貝: hard drive ——> kernel buffer)。然後再將數據從內核空間緩沖區拷貝到內核中與socket相關的緩沖區中(第二次拷貝: kernel buffer ——> socket buffer)。
② sendfile系統調用返回,導致內核空間到用戶空間的上下文切換(第二次上下文切換)。通過DMA引擎將內核空間socket緩沖區中的數據傳遞到協議引擎(第三次拷貝: socket buffer ——> protocol engine)

總的來說,通過sendfile實現的零拷貝I/O只使用了2次用戶空間與內核空間的上下文切換,以及3次數據的拷貝。其中3次數據拷貝中包括了2次DMA拷貝和1次CPU拷貝。

Q: 但通過是這里還是存在著一次CPU拷貝操作,即,kernel buffer ——> socket buffer。是否有辦法將該拷貝操作也取消掉了?
A: 有的。但這需要底層操作系統的支持。從Linux 2.4版本開始,操作系統底層提供了scatter/gather這種DMA的方式來從內核空間緩沖區中將數據直接讀取到協議引擎中,而無需將內核空間緩沖區中的數據再拷貝一份到內核空間socket相關聯的緩沖區中。

從Linux 2.4版本開始,操作系統底層提供了帶有scatter/gather的DMA來從內核空間緩沖區中將數據讀取到協議引擎中。這樣一來待傳輸的數據可以分散在存儲的不同位置上,而不需要在連續存儲中存放。那麼從文件中讀出的數據就根本不需要被拷貝到socket緩沖區中去,只是需要將緩沖區描述符添加到socket緩沖區中去,DMA收集操作會根據緩沖區描述符中的信息將內核空間中的數據直接拷貝到協議引擎中。

① 發出sendfile系統調用,導致用戶空間到內核空間的上下文切換(第一次上下文切換)。通過DMA引擎將磁碟文件中的內容拷貝到內核空間緩沖區中(第一次拷貝: hard drive ——> kernel buffer)。
② 沒有數據拷貝到socket緩沖區。取而代之的是只有相應的描述符信息會被拷貝到相應的socket緩沖區當中。該描述符包含了兩方面的信息:a)kernel buffer的內存地址;b)kernel buffer的偏移量。
③ sendfile系統調用返回,導致內核空間到用戶空間的上下文切換(第二次上下文切換)。DMA gather 根據socket緩沖區中描述符提供的位置和偏移量信息直接將內核空間緩沖區中的數據拷貝到協議引擎上(第二次拷貝: kernel buffer ——> protocol engine),這樣就避免了最後一次CPU數據拷貝。

總的來說,帶有DMA收集拷貝功能的sendfile實現的I/O只使用了2次用戶空間與內核空間的上下文切換,以及2次數據的拷貝,而且這2次的數據拷貝都是非CPU拷貝。這樣一來我們就實現了最理想的零拷貝I/O傳輸了,不需要任何一次的CPU拷貝,以及最少的上下文切換。

在linux2.6.33版本之前 sendfile指支持文件到套接字之間傳輸數據,即in_fd相當於一個支持mmap的文件,out_fd必須是一個socket。但從linux2.6.33版本開始,out_fd可以是任意類型文件描述符。所以從linux2.6.33版本開始sendfile可以支持「文件到文件」和「文件到套接字」之間的數據傳輸。

Q: 對於上面的第三點,如果我們需要對數據進行操作該怎麼辦了?
A: Linux提供了mmap零拷貝來實現我們的需求。

mmap(內存映射)是一個比sendfile昂貴但優於傳統I/O的方法。

① 發出mmap系統調用,導致用戶空間到內核空間的上下文切換(第一次上下文切換)。通過DMA引擎將磁碟文件中的內容拷貝到內核空間緩沖區中(第一次拷貝: hard drive ——> kernel buffer)。
② mmap系統調用返回,導致內核空間到用戶空間的上下文切換(第二次上下文切換)。接著用戶空間和內核空間共享這個緩沖區,而不需要將數據從內核空間拷貝到用戶空間。因為用戶空間和內核空間共享了這個緩沖區數據,所以用戶空間就可以像在操作自己緩沖區中數據一般操作這個由內核空間共享的緩沖區數據。
③ 發出write系統調用,導致用戶空間到內核空間的上下文切換(第三次上下文切換)。將數據從內核空間緩沖區拷貝到內核空間socket相關聯的緩沖區(第二次拷貝: kernel buffer ——> socket buffer)。
④ write系統調用返回,導致內核空間到用戶空間的上下文切換(第四次上下文切換)。通過DMA引擎將內核空間socket緩沖區中的數據傳遞到協議引擎(第三次拷貝: socket buffer ——> protocol engine)

總的來說,通過mmap實現的零拷貝I/O進行了4次用戶空間與內核空間的上下文切換,以及3次數據拷貝。其中3次數據拷貝中包括了2次DMA拷貝和1次CPU拷貝。

FileChannel中大量使用了我們上面所提及的零拷貝技術。
FileChannel的map方法會返回一個MappedByteBuffer。MappedByteBuffer是一個直接位元組緩沖器,該緩沖器的內存是一個文件的內存映射區域。map方法底層是通過mmap實現的,因此將文件內存從磁碟讀取到內核緩沖區後,用戶空間和內核空間共享該緩沖區。
MappedByteBuffer內存映射文件是一種允許Java程序直接從內存訪問的一種特殊的文件。我們可以將整個文件或者整個文件的一部分映射到內存當中,那麼接下來是由操作系統來進行相關的頁面請求並將內存的修改寫入到文件當中。我們的應用程序只需要處理內存的數據,這樣可以實現非常迅速的I/O操作。

只讀模式來說,如果程序試圖進行寫操作,則會拋出ReadOnlyBufferException異常

讀寫模式表明,對結果對緩沖區所做的修改將最終廣播到文件。但這個修改可能會也可能不會被其他映射了相同文件程序可見。

私有模式來說,對結果緩沖區的修改將不會被廣播到文件並且也不會對其他映射了相同文件的程序可見。取而代之的是,它將導致被修改部分緩沖區獨自拷貝一份到用戶空間。這便是OS的「 on write」原則。

如果操作系統底層支持的話transferTo、transferFrom也會使用相關的零拷貝技術來實現數據的傳輸。所以,這里是否使用零拷貝必須依賴於底層的系統實現。

轉自: https://www.jianshu.com/p/e76e3580e356

Ⅲ Linux的內存管理機制是什麼樣的

,程序是直接運行在物理內存上的。換句話說,就是程序在運行的過程中訪問的都是物理地址。如果這個系統只運行一個程序

Ⅳ Handler消息機制(一):Linux的epoll機制

在linux 沒有實現epoll事件驅動機制之前,我們一般選擇用select或者poll等IO多路復用的方法來實現並發服務程序。在linux新的內核中,有了一種替換它的機制,就是epoll。

相比select模型, poll使用鏈表保存文件描述符,因此沒有了監視文件數量的限制 ,但其他三個缺點依然存在。

假設我們的伺服器需要支持100萬的並發連接,則在__FD_SETSIZE 為1024的情況下,則我們至少需要開辟1k個進程才能實現100萬的並發連接。除了進程間上下文切換的時間消耗外,從內核/用戶空間大量的無腦內存拷貝、數組輪詢等,是系統難以承受的。因此,基於select模型的伺服器程序,要達到10萬級別的並發訪問,是一個很難完成的任務。

由於epoll的實現機制與select/poll機制完全不同,上面所說的 select的缺點在epoll上不復存在。

設想一下如下場景:有100萬個客戶端同時與一個伺服器進程保持著TCP連接。而每一時刻,通常只有幾百上千個TCP連接是活躍的(事實上大部分場景都是這種情況)。如何實現這樣的高並發?

在select/poll時代,伺服器進程每次都把這100萬個連接告訴操作系統(從用戶態復制句柄數據結構到內核態),讓操作系統內核去查詢這些套接字上是否有事件發生,輪詢完後,再將句柄數據復制到用戶態,讓伺服器應用程序輪詢處理已發生的網路事件,這一過程資源消耗較大,因此,select/poll一般只能處理幾千的並發連接。

epoll的設計和實現與select完全不同。epoll通過在Linux內核中申請一個簡易的文件系統(文件系統一般用什麼數據結構實現?B+樹)。把原先的select/poll調用分成了3個部分:

1)調用epoll_create()建立一個epoll對象(在epoll文件系統中為這個句柄對象分配資源)

2)調用epoll_ctl向epoll對象中添加這100萬個連接的套接字

3)調用epoll_wait收集發生的事件的連接

如此一來,要實現上面說是的場景,只需要在進程啟動時建立一個epoll對象,然後在需要的時候向這個epoll對象中添加或者刪除連接。同時,epoll_wait的效率也非常高,因為調用epoll_wait時,並沒有一股腦的向操作系統復制這100萬個連接的句柄數據,內核也不需要去遍歷全部的連接。

當某一進程調用epoll_create方法時,Linux內核會創建一個eventpoll結構體,這個結構體中有兩個成員與epoll的使用方式密切相關。eventpoll結構體如下所示:

每一個epoll對象都有一個獨立的eventpoll結構體,用於存放通過epoll_ctl方法向epoll對象中添加進來的事件。這些事件都會掛載在紅黑樹中,如此,重復添加的事件就可以通過紅黑樹而高效的識別出來(紅黑樹的插入時間效率是lgn,其中n為樹的高度)。

而所有 添加到epoll中的事件都會與設備(網卡)驅動程序建立回調關系,也就是說,當相應的事件發生時會調用這個回調方法 。這個回調方法在內核中叫ep_poll_callback,它會將發生的事件添加到rdlist雙鏈表中。

在epoll中,對於每一個事件,都會建立一個epitem結構體,如下所示:

當調用epoll_wait檢查是否有事件發生時,只需要檢查eventpoll對象中的rdlist雙鏈表中是否有epitem元素即可。如果rdlist不為空,則把發生的事件復制到用戶態,同時將事件數量返回給用戶。

epoll結構示意圖

通過紅黑樹和雙鏈表數據結構,並結合回調機制,造就了epoll的高效。

events可以是以下幾個宏的集合:
EPOLLIN:觸發該事件,表示對應的文件描述符上有可讀數據。(包括對端SOCKET正常關閉);
EPOLLOUT:觸發該事件,表示對應的文件描述符上可以寫數據;
EPOLLPRI:表示對應的文件描述符有緊急的數據可讀(這里應該表示有帶外數據到來);
EPOLLERR:表示對應的文件描述符發生錯誤;
EPOLLHUP: 表示對應的文件描述符被掛斷;
EPOLLET:將EPOLL設為邊緣觸發(EdgeTriggered)模式,這是相對於水平觸發(Level Triggered)來說的。
EPOLLONESHOT: 只監聽一次事件,當監聽完這次事件之後,如果還需要繼續監聽這個socket的話,需要再次把這個socket加入到EPOLL隊列里。
示例:

ET(EdgeTriggered) :高速工作模式,只支持no_block(非阻塞模式)。在此模式下,當描述符從未就緒變為就緒時,內核通過epoll告知。然後它會假設用戶知道文件描述符已經就緒,並且不會再為那個文件描述符發送更多的就緒通知,直到某些操作導致那個文件描述符不再為就緒狀態了。(觸發模式只在數據就緒時通知一次,若數據沒有讀完,下一次不會通知,直到有新的就緒數據)

LT(LevelTriggered) :預設工作方式,支持blocksocket和no_blocksocket。在LT模式下內核會告知一個文件描述符是否就緒了,然後可以對這個就緒的fd進行IO操作。如果不作任何操作,內核還是會繼續通知!若數據沒有讀完,內核也會繼續通知,直至設備數據為空為止!

1.我們已經把一個用來從管道中讀取數據的文件句柄(RFD)添加到epoll描述符
2. 這個時候從管道的另一端被寫入了2KB的數據
3. 調用epoll_wait(2),並且它會返回RFD,說明它已經准備好讀取操作
4. 然後我們讀取了1KB的數據
5. 調用epoll_wait(2)……

ET工作模式:
如果我們在第1步將RFD添加到epoll描述符的時候使用了EPOLLET標志,在第2步執行了一個寫操作,第三步epoll_wait會返回同時通知的事件會銷毀。因為第4步的讀取操作沒有讀空文件輸入緩沖區內的數據,因此我們在第5步調用epoll_wait(2)完成後,是否掛起是不確定的。epoll工作在ET模式的時候,必須使用非阻塞套介面,以避免由於一個文件句柄的阻塞讀/阻塞寫操作把處理多個文件描述符的任務餓死。

只有當read(2)或者write(2)返回EAGAIN時(認為讀完)才需要掛起,等待。但這並不是說每次read()時都需要循環讀,直到讀到產生一個EAGAIN才認為此次事件處理完成,當read()返回的讀到的數據長度小於請求的數據長度時(即小於sizeof(buf)),就可以確定此時緩沖中已沒有數據了,也就可以認為此事讀事件已處理完成。

LT工作模式:
LT方式調用epoll介面的時候,它就相當於一個速度比較快的poll(2),並且無論後面的數據是否被使用,因此他們具有同樣的職能。

當調用 epoll_wait檢查是否有發生事件的連接時,只是檢查 eventpoll對象中的 rdllist雙向鏈表是否有 epitem元素而已,如果 rdllist鏈表不為空,則把這里的事件復制到用戶態內存中,同時將事件數量返回給用戶。因此,epoll_wait的效率非常高。epoll_ctl在向 epoll對象中添加、修改、刪除事件時,從 rbr紅黑樹中查找事件也非常快,也就是說,epoll是非常高效的,它可以輕易地處理百萬級別的並發連接。

1.減少用戶態和內核態之間的文件句柄拷貝;

2.減少對可讀可寫文件句柄的遍歷。

https://cloud.tencent.com/developer/information/linux%20epoll%E6%9C%BA%E5%88%B6
https://blog.csdn.net/u010657219/article/details/44061629
https://jiahao..com/s?id=1609322251459722004&wfr=spider&for=pc

Ⅳ Linux內存機制(swap)

我們知道,直接從物理內存讀寫數據要比從硬碟讀寫數據要快的多,因此,我們希望所有數據的讀取和寫入都在內存完成,而內存是有限的,這樣就引出了物理內存與虛擬內存的概念。

物理內存就是系統硬體提供的內存大小,是真正的內存,相對於物理內存,在linux下還有一個虛擬內存的概念,虛擬內存就是為了滿足物理內存的不足而提出的策略,它是利用磁碟空間虛擬出的一塊邏輯內存,用作虛擬內存的磁碟空間被稱為交換空間(Swap Space)。

作為物理內存的擴展,linux會在物理內存不足時,使用交換分區的虛擬內存,更詳細的說,就是內核會將暫時不用的內存塊信息寫到交換空間,這樣以來,物理內存得到了釋放,這塊內存就可以用於其它目的,當需要用到原始的內容時,這些信息會被重新從交換空間讀入物理內存。

Linux的內存管理採取的是分頁存取機制,為了保證物理內存能得到充分的利用,內核會在適當的時候將物理內存中不經常使用的數據塊自動交換到虛擬內存中,而將經常使用的信息保留到物理內存。

要深入了解linux內存運行機制,需要知道下面提到的幾個方面:

Linux系統會不時的進行頁面交換操作,以保持盡可能多的空閑物理內存,即使並沒有什麼事情需要內存,Linux也會交換出暫時不用的內存頁面。這可以避免等待交換所需的時間。

Linux 進行頁面交換是有條件的,不是所有頁面在不用時都交換到虛擬內存,linux內核根據」最近最經常使用「演算法,僅僅將一些不經常使用的頁面文件交換到虛擬 內存,有時我們會看到這么一個現象:linux物理內存還有很多,但是交換空間也使用了很多。其實,這並不奇怪,例如,一個佔用很大內存的進程運行時,需 要耗費很多內存資源,此時就會有一些不常用頁面文件被交換到虛擬內存中,但後來這個佔用很多內存資源的進程結束並釋放了很多內存時,剛才被交換出去的頁面 文件並不會自動的交換進物理內存,除非有這個必要,那麼此刻系統物理內存就會空閑很多,同時交換空間也在被使用,就出現了剛才所說的現象了。關於這點,不 用擔心什麼,只要知道是怎麼一回事就可以了。

交換空間的頁面在使用時會首先被交換到物理內存,如果此時沒有足夠的物理內存來容納這些頁 面,它們又會被馬上交換出去,如此以來,虛擬內存中可能沒有足夠空間來存儲這些交換頁面,最終會導致linux出現假死機、服務異常等問題,linux雖 然可以在一段時間內自行恢復,但是恢復後的系統已經基本不可用了。

因此,合理規劃和設計Linux內存的使用,是非常重要的.

在Linux 操作系統中,當應用程序需要讀取文件中的數據時,操作系統先分配一些內存,將數據從磁碟讀入到這些內存中,然後再將數據分發給應用程序;當需要往文件中寫 數據時,操作系統先分配內存接收用戶數據,然後再將數據從內存寫到磁碟上。然而,如果有大量數據需要從磁碟讀取到內存或者由內存寫入磁碟時,系統的讀寫性 能就變得非常低下,因為無論是從磁碟讀數據,還是寫數據到磁碟,都是一個很消耗時間和資源的過程,在這種情況下,Linux引入了buffers和 cached機制。

buffers與cached都是內存操作,用來保存系統曾經打開過的文件以及文件屬性信息,這樣當操作系統需要讀取某些文件時,會首先在buffers 與cached內存區查找,如果找到,直接讀出傳送給應用程序,如果沒有找到需要數據,才從磁碟讀取,這就是操作系統的緩存機制,通過緩存,大大提高了操 作系統的性能。但buffers與cached緩沖的內容卻是不同的。

buffers是用來緩沖塊設備做的,它只記錄文件系統的元數據(metadata)以及 tracking in-flight pages,而cached是用來給文件做緩沖。更通俗一點說:buffers主要用來存放目錄裡面有什麼內容,文件的屬性以及許可權等等。而cached直接用來記憶我們打開過的文件和程序。

為了驗證我們的結論是否正確,可以通過vi打開一個非常大的文件,看看cached的變化,然後再次vi這個文件,感覺一下兩次打開的速度有何異同,是不是第二次打開的速度明顯快於第一次呢?接著執行下面的命令:

find / -name .conf 看看buffers的值是否變化,然後重復執行find命令,看看兩次顯示速度有何不同。

上面這個60代表物理內存在使用40%的時候才會使用swap(參考網路資料:當剩餘物理內存低於40%(40=100-60)時,開始使用交換空間) swappiness=0的時候表示最大限度使用物理內存,然後才是 swap空間,swappiness=100的時候表示積極的使用swap分區,並且把內存上的數據及時的搬運到swap空間裡面。

值越大表示越傾向於使用swap。可以設為0,這樣做並不會禁止對swap的使用,只是最大限度地降低了使用swap的可能性。

通常情況下:swap分區設置建議是內存的兩倍 (內存小於等於4G時),如果內存大於4G,swap只要比內存大就行。另外盡量的將swappiness調低,這樣系統的性能會更好。

B. 修改swappiness參數

永久性修改:

立即生效,重啟也可以生效。

一般系統是不會自動釋放內存的 關鍵的配置文件/proc/sys/vm/drop_caches。這個文件中記錄了緩存釋放的參數,默認值為0,也就是不釋放緩存。他的值可以為0~3之間的任意數字,代表著不同的含義:

0 – 不釋放 1 – 釋放頁緩存 2 – 釋放dentries和inodes 3 – 釋放所有緩存

前提:首先要保證內存剩餘要大於等於swap使用量,否則會宕機!根據內存機制,swap分區一旦釋放,所有存放在swap分區的文件都會轉存到物理內存上。通常通過重新掛載swap分區完成釋放swap。
a.查看當前swap分區掛載在哪?b.關停這個分區 c.查看狀態:d.查看swap分區是否關停,最下面一行顯示全 e.將swap掛載到/dev/sda5上 f.查看掛載是否成功

Ⅵ linux是什麼操作系統

Linux,全稱GNU/Linux,是一種免費使用和自由傳播的類UNIX操作系統,其內核由林納斯·本納第克特·托瓦茲於1991年10月5日首次發布,它主要受到Minix和Unix思想的啟發,是一個基於POSIX的多用戶、多任務、支持多線程和多CPU的操作系統。它能運行主要的Unix工具軟體、應用程序和網路協議。

Linux繼承了Unix以網路為核心的設計思想,是一個性能穩定的多用戶網路操作系統。Linux有上百種不同的發行版,如基於社區開發的debian、archlinux,和基於商業開發的Red Hat Enterprise Linux、SUSE、Oracle Linux等。

(6)linux文件機制擴展閱讀:

Linux不僅系統性能穩定,而且是開源軟體。其核心防火牆組件性能高效、配置簡單,保證了系統的安全。在很多企業網路中,為了追求速度和安全,Linux不僅僅是被網路運維人員當作伺服器使用,它還被當作伺服器,甚至當作網路防火牆,這是Linux的一大亮點。

Linux具有開放源碼、沒有版權、技術社區用戶多等特點,開放源碼使得用戶可以自由裁剪,靈活性高,功能強大,成本低。尤其系統中內嵌網路協議棧,經過適當的配置就可實現路由器的功能。這些特點使得Linux成為開發路由交換設備的理想開發平台。

Ⅶ Linux 內核的內存管理 - 概念

Concepts overview — The Linux Kernel documentation

Linux中的內存管理是一個復雜的系統,經過多年的發展,它包含越來越多的功能,以支持從 MMU-less microcontrollers 到 supercomputers 的各種系統。
沒有MMU內存管理的系統被稱為 nommu ,它值得寫一份專門的文檔進行描述。
盡管有些概念是相同的,這里我們假設MMU可用,CPU可以將虛擬地址轉換為物理地址。

計算機系統中的物理內存是有限資源,即便支持內存熱插拔,其可以安裝的內存也有限的。物理內存不一定必須是連續的;它可以作為一組不同的地址范圍被訪問。此外,不同的CPU架構,甚至同架構的不同實現對如何定義這些地址范圍都是不同的。

這使得直接處理物理內存異常復雜,為了避免這種復雜性,開發了 虛擬內存 (virtual memory) 的概念。

虛擬內存從應用軟體中抽象出物理內存的細節,只允許在物理內存中保留需要的信息 (demand paging) ,並提供一種機制來保護和控制進程之間的數據共享。

通過虛擬內存,每次內存訪問都訪問一個 虛擬地址 。當CPU對從系統內存讀取(或寫入)的指令進行解碼時,它將該指令中編碼的虛擬地址轉換為內存控制器可以理解的物理地址。

物理內存被切分為 頁幀 page frames 頁 pages 。頁的大小是基於架構的。一些架構允許從幾個支持的值中選擇頁大小;此選擇在內核編譯時設置到內核配置。

每個物理內存頁都可以映射為一個或多個 虛擬頁(virtual pages) 。映射關系描述在 頁表(page tables) 中,頁表將程序使用的虛擬地址轉換為物理內存地址。頁表以層次結構組織。

最底層的表包含軟體使用的實際內存頁的物理地址。較高層的表包含較低層表頁的物理地址。頂層表的指針駐留在寄存器中。
當CPU進行地址轉換的時候,它使用寄存器訪問頂級頁表。

虛擬地址的高位,用於頂級頁表的條目索引。然後,通過該條目訪問下級,下級的虛擬地址位又作為其下下級頁表的索引。虛擬地址的最低位定義實際頁內的偏移量。

地址轉換需要多次內存訪問,而內存訪問相對於CPU速度來說比較慢。為了避免在地址轉換上花費寶貴的處理器周期,CPU維護著一個稱為 TLB (Translation Lookaside Buffer)的用於地址轉換緩存(cache)。通常TLB是非常稀缺的資源,需要大內存工作應用程序會因為TLB未命中而影響性能。

很多現代CPU架構允許頁表的高層直接映射到內存頁。例如,x86架構,可以通過二級、三級頁表的條目映射2M甚至1G內存頁。在Linux中,這些內存頁稱為 大頁 (Huge) 。大頁的使用顯著降低了TLB的壓力,提高了TLB命中率,從而提高了系統的整體性能。

Linux提供兩種機制開啟使用大頁映射物理內存。

第一個是 HugeTLB 文件系統,即 hugetlbfs 。它是一個偽文件系統,使用RAM作為其存儲。在此文件系統中創建的文件,數據駐留在內存中,並使用大頁進行映射。
關於 HugeTLB Pages

另一個被稱為 THP (Transparent HugePages) ,後出的開啟大頁映射物理內存的機制。
hugetlbfs 不同,hugetlbfs要求用戶和/或系統管理員配置系統內存的哪些部分應該並可以被大頁映射;THP透明地管理這些映射並獲取名稱。
關於 Transparent Hugepage Support

通常,硬體對不同物理內存范圍的訪問方式有所限制。某些情況下,設備不能對所有可定址內存執行DMA。在其他情況下,物理內存的大小超過虛擬內存的最大可定址大小,需要採取特殊措施來訪問部分內存。還有些情況,物理內存的尺寸超過了虛擬內存的最大可定址尺寸,需要採取特殊措施來訪問部分內存。

Linux根據內存頁的使用情況,將其組合為多個 zones 。比如, ZONE_DMA 包含設備用於DMA的內存, ZONE_HIGHMEM 包含未永久映射到內核地址空間的內存, ZONE_NORMAL 包含正常定址內存頁。
內存zones的實際層次架構取決於硬體,因為並非所有架構都定義了所有的zones,不同平台對DMA的要求也不同。

多處理器機器很多基於 NUMA (Non-Uniform Memory Access system - 非統一內存訪問系統 )架構。 在這樣的系統中,根據與處理器的「距離」,內存被安排成具有不同訪問延遲的 banks 。每個 bank 被稱為一個 node ,Linux為每個 node 構造一個獨立的內存管理子系統。 Node 有自己的zones集合、free&used頁面列表,以及各種統計計數器。
What is NUMA?
NUMA Memory Policy

物理內存易失,將數據放入內存的常見情況是讀取文件。讀取文件時,數據會放入 頁面緩存(page cache) ,可以在再次讀取時避免耗時的磁碟訪問。同樣,寫文件時,數據也會被放入 頁面緩存 ,並最終進入存儲設備。被寫入的頁被標記為 臟頁(dirty page) ,當Linux決定將其重用時,它會將更新的數據同步到設備上的文件。

匿名內存 anonymous memory 匿名映射 anonymous mappings 表示沒有後置文件系統的內存。這些映射是為程序的stack和heap隱式創建的,或調用mmap(2)顯式創建的。通常,匿名映射只定義允許程序訪問的虛擬內存區域。讀,會創建一個頁表條目,該條目引用一個填充有零的特殊物理頁。寫,則分配一個常規物理頁來保存寫入數據。該頁將被標記為臟頁,如果內核決定重用該頁,則臟頁將被交換出去 swapped out

縱貫整個系統生命周期,物理頁可用於存儲不同類型的數據。它可以是內核內部數據結構、設備驅動DMA緩沖區、讀取自文件系統的數據、用戶空間進程分配的內存等。
根據內存頁使用情況,Linux內存管理會區別處理。可以隨時釋放的頁面稱為 可回收(reclaimable) 頁面,因為它們把數據緩存到了其他地方(比如,硬碟),或者被swap out到硬碟上。
可回收頁最值得注意的是 頁面緩存 匿名頁面

在大多數情況下,存放內部內核數據的頁,和用作DMA緩沖區的頁無法重用,它們將保持現狀直到用戶釋放。這樣的被稱為 不可回收頁(unreclaimable)
然而,在特定情況下,即便是內核數據結構佔用的頁面也會被回收。
例如,文件系統元數據的緩存(in-memory)可以從存儲設備中重新讀取,因此,當系統存在內存壓力時,可以從主內存中丟棄它們。

釋放可回收物理內存頁並重新調整其用途的過程稱為 (surprise!) reclaim
Linux支持非同步或同步回收頁,取決於系統的狀態。
當系統負載不高時,大部分內存是空閑的,可以立即從空閑頁得到分配。
當系統負載提升後,空閑頁減少,當達到某個閾值( low watermark )時,內存分配請求將喚醒 kswapd 守護進程。它將以非同步的方式掃描內存頁。如果內存頁中的數據在其他地方也有,則釋放這些內存頁;或者退出內存到後置存儲設備(關聯 臟頁 )。

隨著內存使用量進一步增加,並達到另一個閾值- min watermark -將觸發回收。這種情況下,分配將暫停,直到回收到足夠的內存頁。

當系統運行時,任務分配並釋放內存,內存變得碎片化。
雖然使用虛擬內存可以將分散的物理頁表示為虛擬連續范圍,但有時需要分配大的連續的物理內存。這種需求可能會提升。例如,當設備驅動需要一個大的DMA緩沖區時,或當THP分配一個大頁時。
內存地址壓縮(compaction ) 解決了碎片問題。
該機制將佔用的頁從內存zone的下部移動到上部的空閑頁。壓縮掃描完成後,zone開始處的空閑頁就並在一起了,分配較大的連續物理內存就可行了。

reclaim 類似, compaction 可以在 kcompactd守護進程中非同步進行,也可以作為內存分配請求的結果同步進行。

在存在負載的機器上,內存可能會耗盡,內核無法回收到足夠的內存以繼續運行。
為了保障系統的其餘部分,引入了 OOM killer

OOM killer 選擇犧牲一個任務來保障系統的總體健康。選定的任務被killed,以期望在它退出後釋放足夠的內存以繼續正常的操作。

熱點內容
安卓定製版蘋果手機是什麼意思 發布:2025-05-14 04:26:27 瀏覽:378
如何搭建php環境虛擬伺服器免費 發布:2025-05-14 04:25:37 瀏覽:102
相冊加密怎麼看 發布:2025-05-14 04:24:53 瀏覽:572
怎麼壓縮郵件 發布:2025-05-14 04:16:51 瀏覽:497
雲伺服器搭建郵箱綁定郁悶 發布:2025-05-14 04:16:48 瀏覽:149
crc校驗c語言演算法 發布:2025-05-14 04:15:15 瀏覽:45
curl靜態編譯 發布:2025-05-14 04:09:52 瀏覽:160
壓縮久期 發布:2025-05-14 04:08:46 瀏覽:942
sql置疑 發布:2025-05-14 04:07:09 瀏覽:441
java面試的演算法題 發布:2025-05-14 04:06:18 瀏覽:467