linux讀寫內存
❶ 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怎樣提升磁碟讀寫性能
關於頁面緩存的信息,可以用
cat /proc/meminfo
看到。其中的Cached 指用於pagecache的內存大小(diskcache-SwapCache)。隨著寫入緩存頁,Dirty 的值會增加。
一旦開始把緩存頁寫入硬碟,Writeback的值會增加直到寫入結束。
Linux 用pdflush進程把數據從緩存頁寫入硬碟,查看有多少個pdflush進程
cat /proc/sys/vm/nr_pdflush_threads
pdflush的行為受/proc/sys/vm中的參數的控制
/proc/sys/vm/dirty_writeback_centisecs (default 500):
1/100秒, 多長時間喚醒pdflush將緩存頁數據寫入硬碟。默認5秒喚醒2個(更多個)線程。
如果wrteback的時間長於dirty_writeback_centisecs的時間,可能會出問題。
pdflush的第一件事是讀取
/proc/sys/vm/dirty_expire_centiseconds (default 3000)
1/100秒。緩存頁里數據的過期時間(舊數據),在下一個周期內被寫入硬碟。默認30秒是一個很長的時間。
第二件事是判斷內存是否到了要寫入硬碟的限額,由參數決定:
/proc/sys/vm/dirty_background_ratio (default 10)
百分值,保留過期頁緩存(臟頁緩存)的最大值。是以MmeFree+Cached-Mapped的值為基準的
pdflush寫入硬碟看兩個參數:
1 數據在頁緩存中是否超出30秒,如果是,標記為臟頁緩存;
2 臟頁緩存是否達到工作內存的10%;
以下參數也會影響到pdflush
/proc/sys/vm/dirty_ratio (default 40)
總內存的最大百分比,系統所能擁有的最大臟頁緩存的總量。超過這個值,開啟pdflush寫入硬碟。如果cache增長快於pdflush,那麼整個系統在40%的時候遇到I/O瓶頸,所有的I/O都要等待cache被pdflush進硬碟後才能重新開始。
對於有高度寫入操作的系統
dirty_background_ratio: 主要調整參數。如果需要把緩存持續的而不是一下子大量的寫入硬碟,降低這個值。
dirty_ratio: 第二調整參數。
Swapping參數
/proc/sys/vm/swappiness
默認,linux傾向於從物理內存映射到硬碟緩存,保持硬碟緩存盡可能大。未用的頁緩存會被放進swap區。
數值為0,將會避免使用swapping
100,將會盡量使用swapping
少用swapping會增加程序的響應速度;多用swapping將會提高系統的可用性。
如果有大量的寫操作,為避免I/O的長時間等待,可以設置:
$ echo 5 > /proc/sys/vm/dirty_background_ratio
$ echo 10 > /proc/sys/vm/dirty_ratio
文件系統數據緩沖需要頻繁的內存分配。加大保留內存的值能提升系統速度和穩定。小於8G的內存,保留內存為64M,大於8G的設置為256M
$ echo 65536 > /proc/sys/vm/min_free_kbytes
I/O 調度器
cat /sys/block/[disk]/queue/scheler
4中調度演算法
noop anticipatory deadline [cfq]
deadline : deadline 演算法保證對既定的IO請求以最小的延遲時間。
anticipatory: 有個IO發生後,如果又有進程請求IO,則產生一個默認6ms猜測時間,猜測下一個進程請求IO是干什麼。這對於隨機讀取會造成較大的延時。
對資料庫應用很糟糕,而對於Web Server等則會表現不錯。
cfq: 對每個進程維護一個IO隊列,各個進程發來的IO請求會被cfq以輪循方式處理,對每一個IO請求都是公平。適合離散讀的應用。
noop: 對所有IO請求都用FIFO隊列形式處理。默認IO不會存在性能問題。
改變調度器
$ echo deadline > /sys/block/sdX/queue/scheler
對於資料庫伺服器,deadline演算法是推薦的。
提高調度器請求隊列的
$ echo 4096 > /sys/block/sdX/queue/nr_requests
有大量的讀請求,默認的請求隊列應付不過來,可以提高這個值。缺點是要犧牲一定的內存。
為了增加連續讀取的吞吐量,可以增加預讀數據量。預讀的實際值是自適應的,所以使用一個較高的值,不會降低小型隨機存取的性能。
$ echo 4096 > /sys/block/sdX/queue/read_ahead_kb
如果LINUX判斷一個進程在順序讀取文件,那麼它會提前讀取進程所需文件的數據,放在緩存中。伺服器遇到磁碟寫活動高峰,導致請求處理延遲非常大(超過3秒)。通過調整內核參數,將寫活動的高峰分布成頻繁的多次寫,每次寫入的數據比較少。這樣可以把尖峰的寫操作削平成多次寫操作。以這種方式執行的效率比較低,因為內核不太有機會組合寫操作。但對於繁忙的伺服器,寫操作將更一致地進行,並將極大地改進互動式性能。
/proc/sys/vm/dirty_ratio
控制文件系統的寫緩沖區的大小,單位是百分比,表示占系統內存的百分比,表示當寫緩沖使用到系統內存多少的時候,開始向磁碟寫出數據。增大之會使用更多系統內存用於磁碟寫緩沖,也可以極大提高系統的寫性能。但是,當你需要持續、恆定的寫入場合時,應該降低其數值。
/proc/sys/vm/dirty_background_ratio
控制文件系統的pdflush進程,在何時刷新磁碟。單位是百分比,表示系統內存的百分比,pdflush用於將內存中的內容和文件系統進行同步,比如說,當一個文件在內存中進行修改,pdflush負責將它寫回硬碟.每當內存中的垃圾頁(dirty page)超過10%的時候,pdflush就會將這些頁面備份回硬碟.增大之會使用更多系統內存用於磁碟寫緩沖,也可以極大提高系統的寫性能。但是,當你需要持續、恆定的寫入場合時,應該降低其數值:
/proc/sys/vm/dirty_writeback_centisecs
控制內核的臟數據刷新進程pdflush的運行間隔。單位是 1/100 秒。預設數值是500,也就是 5 秒。如果你的系統是持續地寫入動作,那麼實際上還是降低這個數值比較好,這樣可以把尖峰的寫操作削平成多次寫操作。
如果你的系統是短期地尖峰式的寫操作,並且寫入數據不大(幾十M/次)且內存有比較多富裕,那麼應該增大此數值。
該參數的設置應該小於dirty_expire_centisecs,但也不能太小,太小I/O太頻繁,反而
使系統性能下降。具體可能需要在生產環境上測試。據說1:6 (dirty_expire_centisecs : dirty_writeback_centisecs )的比例比較好。
/proc/sys/vm/dirty_expire_centisecs
聲明Linux內核寫緩沖區裡面的數據多「舊」了之後,pdflush進程就開始考慮寫到磁碟中去。單位是 1/100秒。預設是 30000,也就是 30 秒的數據就算舊了,將會刷新磁碟。對於特別重載的寫操作來說,這個值適當縮小也是好的,但也不能縮小太多,因為縮小太多也會導致IO提高太快。
當然,如果你的系統內存比較大,並且寫入模式是間歇式的,並且每次寫入的數據不大(比如幾十M),那麼這個值還是大些的好。
/proc/sys/vm/vfs_cache_pressure
表示內核回收用於directory和inode cache內存的傾向;預設值100表示內核將根據pagecache和swapcache,把directory和inode cache保持在一個合理的百分比;降低該值低於100,將導致內核傾向於保留directory和inode cache;增加該值超過100,將導致內核傾向於回收directory和inode cache
/proc/sys/vm/min_free_kbytes
表示強制Linux VM最低保留多少空閑內存(Kbytes)。
預設設置:724(512M物理內存)
/proc/sys/vm/nr_pdflush_threads
表示當前正在運行的pdflush進程數量,在I/O負載高的情況下,內核會自動增加更多的pdflush進程。
/proc/sys/vm/overcommit_memory
指定了內核針對內存分配的策略,其值可以是0、1、2。
0, 表示內核將檢查是否有足夠的可用內存供應用進程使用;如果有足夠的可用內存,內存申請允許;否則,內存申請失敗,並把錯誤返回給應用進程。
1, 表示內核允許分配所有的物理內存,而不管當前的內存狀態如何。
2, 表示內核允許分配超過所有物理內存和交換空間總和的內存(參照overcommit_ratio)。
預設設置:0
/proc/sys/vm/overcommit_ratio
如果overcommit_memory=2,可以過載內存的百分比,通過以下公式來計算系統整體可用內存。系統可分配內存=交換空間+物理內存*overcommit_ratio/100
預設設置:50(%)
/proc/sys/vm/page-cluster
表示在寫一次到swap區的時候寫入的頁面數量,0表示1頁,1表示2頁,2表示4頁。
預設設置:3(2的3次方,8頁)
/proc/sys/vm/swapiness
表示系統進行交換行為的程度,數值(0-100)越高,越可能發生磁碟交換。
更改:
/etc/sysctl.conf
vm.dirty_ratio=40
sysctl -p
查看:
find /proc/sys/vm -name dirty* -print | while read name; do echo $name ;cat ${name}; done
❸ linux中查看物理內存和配置空間的命令是什麼
linux中查看物理內存的命令是:dmidecode -t memory | grep Size。(如果沒有安裝dmidecode 需要先執行yum -y install dmidecode)
物理內存是沒辦法配置的,只能配置虛擬內存,在Linux系統即Swap分區,查看Swap分區的命令是:free -k 或者 free -m。m代表以MB為單位,k代表以KB為單位。
(3)linux讀寫內存擴展閱讀
dmidecode命令介紹
使用方法:
dmidecode [OPTIONS]
參數介紹:
-d, --dev-mem FILE 從設備文件讀取內存(默認: /dev/mem)
-h, --help顯示此幫助文本並退出。
-q, --quiet 減少詳細輸出。
-t, --type TYPE 僅顯示給定類型的條目。
-V, --version 查看版本號。
❹ Linux C 怎麼實現兩個線程同步讀取兩個內存的數據
在Linux系統中使用C/C++進行多線程編程時,我們遇到最多的就是對同一變數的多線程讀寫問題,大多情況下遇到這類問題都是通過鎖機制來處理,但這對程序的性能帶來了很大的影響,當然對於那些系統原生支持原子操作的數據類型來說,我們可以使用原子操作來處理,這能對程序的性能會得到一定的提高。那麼對於那些系統不支持原子操作的自定義數據類型,在不使用鎖的情況下如何做到線程安全呢?本文將從線程局部存儲方面,簡單講解處理這一類線程安全問題的方法。
一、數據類型
在C/C++程序中常存在全局變數、函數內定義的靜態變數以及局部變數,對於局部變數來說,其不存在線程安全問題,因此不在本文討論的范圍之內。全局變數和函數內定義的靜態變數,是同一進程中各個線程都可以訪問的共享變數,因此它們存在多線程讀寫問題。在一個線程中修改了變數中的內容,其他線程都能感知並且能讀取已更改過的內容,這對數據交換來說是非常快捷的,但是由於多線程的存在,對於同一個變數可能存在兩個或兩個以上的線程同時修改變數所在的內存內容,同時又存在多個線程在變數在修改的時去讀取該內存值,如果沒有使用相應的同步機制來保護該內存的話,那麼所讀取到的數據將是不可預知的,甚至可能導致程序崩潰。
如果需要在一個線程內部的各個函數調用都能訪問、但其它線程不能訪問的變數,這就需要新的機制來實現,我們稱之為Static memory local to a thread (線程局部靜態變數),同時也可稱之為線程特有數據(TSD: Thread-Specific Data)或者線程局部存儲(TLS: Thread-Local Storage)。這一類型的數據,在程序中每個線程都會分別維護一份變數的副本(),並且長期存在於該線程中,對此類變數的操作不影響其他線程。如下圖:
二、一次性初始化
在講解線程特有數據之前,先讓我們來了解一下一次性初始化。多線程程序有時有這樣的需求:不管創建多少個線程,有些數據的初始化只能發生一次。列如:在C++程序中某個類在整個進程的生命周期內只能存在一個實例對象,在多線程的情況下,為了能讓該對象能夠安全的初始化,一次性初始化機制就顯得尤為重要了。——在設計模式中這種實現常常被稱之為單例模式(Singleton)。Linux中提供了如下函數來實現一次性初始化:
#include <pthread.h>
// Returns 0 on success, or a positive error number on error
int pthread_once (pthread_once_t *once_control, void (*init) (void));
利用參數once_control的狀態,函數pthread_once()可以確保無論有多少個線程調用多少次該函數,也只會執行一次由init所指向的由調用者定義的函數。init所指向的函數沒有任何參數,形式如下:
void init (void)
{
// some variables initializtion in here
}
另外,參數once_control必須是pthread_once_t類型變數的指針,指向初始化為PTHRAD_ONCE_INIT的靜態變數。在C++0x以後提供了類似功能的函數std::call_once (),用法與該函數類似。使用實例請參考https://github.com/ApusApp/Swift/blob/master/swift/base/singleton.hpp實現。
❺ linux 共享內存 可不可以不加鎖呢 系統有兩個進程,一個負責寫入,一個負責讀取
能.並且是"要"加鎖.可以使用信號量加鎖.