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 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系統實現安全機制的基本手段有哪些
實現安全機制主要有以下幾種:
系統層面:管訪問類別的防火牆、管目標文件安全上下文的SeLinux。
管理層面:密碼要復雜、三個月一次更新。
應用層面:用不到的別裝,時刻更新穩定版本,不要bata版本或類似版本。
個人層面:多看點安全方面的知識,安全手段先在沙盒中做好,然後再部署到真機上去。
❹ Linux的IPC機制(三):Binder
正如上一章所說, 跨進程通信是需要內核空間做支持的. 傳統的 IPC 機制如 管道, Socket, 都是內核的一部分, 因此通過內核支持來實現進程間通信自然是沒問題的.
但是 Binder 並不是 Linux 系統內核的一部分, 那怎麼辦呢, 這得益於 Linux 的動態內核可載入模塊 (Loadable Kernel Mole, LKM)的機制
這樣 Android 系統就可以通過動態添加一個內核模塊運行在內核空間, 用戶進程進程之間通過這個內核模塊作為橋梁來實現通信.
那麼在 Android 系統中用戶進程之間是如何通過這個內核模塊 (Binder Driver)來實現通信的呢? 顯然不是和上一章的傳統 IPC 通信一樣,進行兩次 了, 不然Binder 也不有在性能方面的優勢了.
Binder IPC 機制中設計到的內存映射通過 mmap() 來實現, mmap() 是操作系統中一種內存映射的方法.
內存映射能減少數據 的次數, 實現用戶空間和內核空間的高效互動. 兩個空間各自的修改也能直接反應在映射的內存區域, 從而被對方空間及時感知. 也正因為如此, 內存映射能夠提供對進程間通信的支持.
Binder IPC 正是基於內存映射( mmap() ) 來實現的, 但是 mmap() 通常是用在有物理介質的文件系統上的.
比如進程中的用戶區域是不能直接和物理設備打交道的, 如果想要把磁碟上的數據讀取到進程的用戶區域, 需要兩次 (磁碟 -> 內核空間 -> 用戶空間). 通常在這種場景下 mmap() 就能發揮作用, 通過在物理介質和用戶空間之間建立映射, 減少數據的 次數, 用內存讀寫代替 I/O 讀寫, 提高文件讀取效率.
而 Binder 並不存在物理介質, 因此 Binder 驅動使用 mmap() 並不是為了在物理介質和用戶空間之間映射, 而是用來在內核空間創建數據接收的緩存空間.
一次完整的 Binder IPC 通信過程通常是這樣:
這樣就完成了一次進程間通信
如下圖:
介紹完 Binder IPC 的底層通信原理, 接下來我們看看實現層面是如何設計的
一次完成的進程間通信必然至少包含兩個進程, 通常我們稱通信的雙方分別為客戶端進程(Client) 和服務端進程(Server), 由於進程隔離機制的存在, 通信雙方必然需要藉助 Binder 來實現.
BInder 是基於 C/S 架構. 是由一些列組件組成. 包括 Client, Server, ServiceManager, Binder 驅動.
Binder 驅動就如如同路由器一樣, 是整個通信的核心. 驅動負責進程之間 Binder 通信的建立 / 傳遞, Binder 引用計數管理, 數據包在進程之間的傳遞和交互等一系列底層支持.
ServiceManager 作用是將字元形式的 Binder 名字轉化成 Client 中對該 Binder 的引用, 使得 Client 能夠通過 Binder 的名字獲得對 Binder 實體的引用.
注冊了名字的 Binder 叫實名 Binder, 就像網站一樣除了 IP 地址以外還有自己的網址.
Server 創建了 Binder, 並為它起一個字元形式, 可讀易記的名字, 將這個 BInder 實體連同名字一起以數據包的形式通過 Binder 驅動 發送給 ServiceManager, 通知 ServiceManager 注冊一個名字為 "張三"的 Binder, 它位於某個 Server 中, 驅動為這個穿越進程邊界的 BInder 創建位於內核中的實體節點以及 ServiceManager 對實體的引用, 將名字以及新建的引用打包傳給 ServiceManager, ServiceManager 收到數據後從中取出名字和引用填入查找表.
ServiceManager 是一個進程, Server 又是一個另外的進程, Server 向 ServiceManager 中注冊 BInder 必然涉及到進程間通信. 當實現進程間通信又要用到進程間通信, 這就好像蛋可以孵出雞的前提確實要先找只雞下蛋! Binder 的實現比較巧妙, 就是預先創造一隻雞來下蛋. ServiceManager 和其他進程同樣採用 Binder 通信, ServiceManager 是 Server 端, 有自己的 Binder 實體, 其他進程都是 Client, 需要通過這個 Binder 的引用來實現 Binder 的注冊, 查詢和獲取. ServiceManager 提供的 Binder 比較特殊, 它沒有名字也不需要注冊. 當一個進程使用 BINDERSETCONTEXT_MGR 命令將自己注冊成 ServiceManager 時 Binder 驅動會自動為它創建 Binder 實體(這就是那隻預先造好的那隻雞). 其實這個 Binder 實體的引用在所有 Client 中都固定為 0 , 而無需通過其他手段獲得. 也就是說, 一個 Server 想要向 ServiceManager 注冊自己的 Binder 就必須通過這個 0 號引用和 ServiceManager 的 Binder 通信. 這里說的 Client 是相對於 ServiceManager 而言的, 一個進程或者應用程序可能是提供服務的 Server, 但是對於 ServiceManager 來說它仍然是個 Client.
Server 向 ServiceManager 中注冊了 Binder 以後, Client 就能通過名字獲得 Binder 的引用. Client 也利用保留的 0 號引用向 ServiceManager 請求訪問某個 Binder. 比如,Client 申請訪問名字叫"張三"的 Binder 引用. ServiceManager 收到這個請求後從請求數據包中取出 Binder 名稱, 在查找表裡找到對應的條目, 取出對應的 Binder 引用, 作為回復發送給發起請求的 Client. 從面相對象的角度看, Server 中的 Binder 實體現在有兩個引用: 一個位於 ServiceManager 中, 一個位於發起請求的 Client 中. 如果後面會有更多的 Client 請求該 Binder, 系統中就會有更多的引用指向這個 Binder, 就像 java 中一個對象有多個引用一樣.
我們已經解釋清楚 Client, Server 藉助 Binder 驅動完成跨進程通信的實現機制了, 但是還有個問題需要弄清楚, 比如 A 進程想要 B 進程中的某個對象(object) 是如何實現的呢, 畢竟它們屬於不同的進程, A 進程沒辦法直接使用 B 進程中的 object.
前面我們說過跨進程通信的過程都有 Binder 驅動的參與, 因此在數據流經 Binder 驅動的時候 Binder 驅動會對數據做一層轉換.
我們在 Client端,向 ServiceManager 獲取具體的 Server 端的 Binder 引用的時候,會首先進過 Binder 驅動,Binder 驅動它並不會把真正的 Server 的 Binder 引用返回給 Client 端,而是返回一個代理的 java 對象,該對象具有跟 Server 端的 Binder 引用相同的方法簽名,這個對象為 ProxyObject,他具有跟 Server 的 Binder 實例一樣的方法,只是這些方法並沒有 Server 端的能力,這些方法只需要把請求參數交給 Binder 驅動即可. 對於 Client 端來說和直接調用 Server 中的方法是一樣的.
了解了上面之後, 我們大致可以推算出 Binder 的通信過程
1. 注冊 ServiceManager
2. 注冊 Server
3. Client 獲取 Server 的 Binder 引用
4. Client 與 Server 通信
❺ Linux的內存管理機制是什麼樣的
,程序是直接運行在物理內存上的。換句話說,就是程序在運行的過程中訪問的都是物理地址。如果這個系統只運行一個程序
❻ linux下的幾種時鍾和定時器機制
1. RTC(Real Time Clock)
所有PC都有RTC. 它和CPU和其他晶元獨立。它在電腦關機之後還可以正常運行。RTC可以在IRQ8上產生周期性中斷. 頻率在2Hz--8192HZ.
Linux只是把RTC用來獲取時間和日期. 當然它允許進程通過對/dev/rtc設備來對它進行編程。Kernel通過0x70和0x71 I/O埠來訪問RTC。
2. TSC(Time Stamp Counter)
80x86上的微處理器都有CLK輸入針腳. 從奔騰系列開始. 微處理器支持一個計數器. 每當一個時鍾信號來的時候. 計數器加1. 可以通過匯編指令rdtsc來得到計數器的值。通過calibrate_tsc可以獲得CPU的頻率. 它是通過計算大約5毫秒里tsc寄存器裡面的增加值來確認的。或者可以通過cat /proc/cpuinfo來獲取cpu頻率。tsc可以提供比PIT更精確的時間度量。
3. PIT(Programmable internval timer)
除了RTC和TSC. IBM兼容機提供了PIT。PIT類似微波爐的鬧鍾機制. 當時間到的時候. 提供鈴聲. PIT不是產生鈴聲. 而是產生一種特殊中斷. 叫定時器中斷或者時鍾中斷。它用來告訴內核一個間隔過去了。這個時間間隔也叫做一個滴答數。可以通過編譯內核是選擇內核頻率來確定。如內核頻率設為1000HZ,則時間間隔或滴答為1/1000=1微秒。滴答月短. 定時精度更高. 但是用戶模式的時間更短. 也就是說用戶模式下程序執行會越慢。滴答的長度以納秒形式存在tick_nsec變數裡面。PIT通過8254的0x40--0x43埠來訪問。它產生中斷號為IRQ 0.
下面是關於pIT裡面的一些宏定義:
HZ:每秒中斷數。
CLOCK_TICK_RATE:值是1,193,182. 它是8254晶元內部振盪器頻率。
LATCH:代表CLOCK_TICK_RATE和HZ的比率. 被用來編程PIT。
setup_pit_timer()如下:
spin_lock_irqsave(&i8253_lock, flags);
outb_p(0x34,0x43);
udelay(10);
outb_p(LATCH & 0xff, 0x40);
udelay(10);
outb (LATCH >> 8, 0x40);
spin_unlock_irqrestore(&i8253_lock, flags);
4. CPU Local Timer
最近的80x86架構的微處理器上的local apic提供了cpu local timer.他和pit區別在於它提供了one-shot和periodic中斷。它可以使中斷發送到特定cpu。one-shot中斷常用在實時系統裡面。
❼ LINUX內存機制是什麼
C語言程序編寫、調試、優化都在Linux,那麼當Linux的操作系統中被C語言調用的某一個控制項的代碼文件沒了,Linux系統是能運行的但是C程序生存的"*.*"文件就不能執行了,得必須返回到C語言或反匯編中檢查調用調試系統文件情況。
比如在C++里有句dos語句"system("md
book")",在當前目錄建立"book"文件夾,那麼就是C++調用操作系統的dos模塊命令集中"md"建文件夾的命令,那麼加入某個Linux
操作系統內有dos模塊,那這句可以運行,那麼,問題來了,有些Windows操作系統已經把dos模塊優化了,當然"system("md
book")"這句在系統里找dos的"md"命令就是空命令了。該例子與內存機制無關,當然也有有關的。
總之,C語言編寫、調試、優化需要在多種系統內驗證,否則還是存在一些移植性的問題。
❽ 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內核同步機制之前,先要了解以下預備知識:(臨界資源與並發源)
在linux系統中,我們把對共享的資源進行訪問的代碼片段稱為臨界區。把導致出現多個進程對同一共享資源進行訪問的原因稱為並發源。
Linux系統下並發的主要來源有:
中斷處理:例如,當進程在訪問某個臨界資源的時候發生了中斷,隨後進入中斷處理程序,如果在中斷處理程序中,也訪問了該臨界資源。雖然不是嚴格意義上的並發,但是也會造成了對該資源的競態。
內核態搶占:例如,當進程在訪問某個臨界資源的時候發生內核態搶占,隨後進入了高優先順序的進程,如果該進程也訪問了同一臨界資源,那麼就會造成進程與進程之間的並發。
多處理器的並發:多處理器系統上的進程與進程之間是嚴格意義上的並發,每個處理器都可以獨自調度運行一個進程,在同一時刻有多個進程在同時運行 。