固態硬盤(SSD)突破了傳統硬盤的速度瓶頸,并且工作穩定、無噪音、耗電少,隨著成本的下降,大有取代傳統硬盤的勢頭。使用SSD的人大多聽說過TRIM,操作系統一定要支持TRIM才能讓SSD的性能實現最優化,那么TRIM到底是什么東西,為什么SSD需要TRIM而傳統硬盤卻不需要呢?
TRIM的出現,實際上是由于SSD在執行數據刪除、覆蓋操作時和傳統硬盤在原理上的差異所造成的。我們知道,存儲設備(無論是SSD還是傳統硬盤)只負責最底層的物理存儲,并不知道所存儲的數據到底有什么意義,反正操作系統讓我讀或寫什么數據我照辦就可以了,而將物理設備中的數據組織成目錄、文件并賦予它們意義的,是文件系統(File System)負責的工作。文件系統是操作系統的一部分,由操作系統負責管理,不同的操作系統支持的文件系統不一樣,例如較古老的FAT16/32、Windows的NTFS、OS X的HFS+、Linux的ext(ext2/3/4)等等。
那么為什么說問題出在數據的刪除和覆蓋上面呢?我們來看一下刪除文件的時候操作系統是如何處理的吧。首先,一個文件在物理設備上是存放在多個數據塊中的,這些塊可以是不連續的,文件系統中會有一張表(例如FAT中的文件分配表)來管理每個文件的數據所對應的存儲位置。那么,在刪除的文件的時候,操作系統只要將該文件所對應的數據塊在文件系統中標記為“空閑”就可以了,根本不需要實際去清除數據塊中存放的數據。
結果:存儲設備只知道哪些地方存了數據,但不知道這個數據到底還有沒有用(因為文件刪除之后,數據實際上可能還留在數據塊中),數據有沒有用只有操作系統才知道。
當我們需要存放新文件時,那些已經標記為“空閑”的數據塊就會被當作空的數據塊來使用(盡管里面實際上不是空的),對于操作系統來說,它們和原本就沒有內容的空數據塊是完全一樣的。但這樣的設計必須建立在一個前提下:
對于物理存儲設備來說,“寫入空白數據塊”和“覆蓋已有內容的數據塊”所需要的操作是完全相同的。
上述前提對于傳統硬盤來說是完全成立的,傳統硬盤的工作方式跟磁帶差不多,數據的記錄是根據介質上某個記錄單元的磁化方向來完成的。也就是說,在寫入數據時,磁頭只要將指定的記錄單元(扇區)磁化為所需的狀態即可,完全不必關心這個單元原本是怎樣的狀態。
然而,上述前提在SSD上卻是不能成立的!為什么呢?因為在SSD中,只有空數據塊才能直接執行寫入操作;而對于非空數據塊,需要先執行擦除操作之后才能進行寫入。
乍看之下,SSD和傳統硬盤的區別僅僅是多了一步擦除操作而已,但實際上并非如此,更要命的還在后頭。在SSD中,數據存儲的最小單位是頁面(page),一個頁面的大小一般是4KB,若干個頁面又被組合成塊(block),一個塊的大小一般是512KB。由于硬件方面的限制,SSD單獨對某個頁面進行讀/寫的操作,但擦除操作卻只能對整個塊進行,也就是說,一旦擦除就必須一次性擦除整個塊。想想看,如果操作系統要讓SSD改寫某個頁面的數據,SSD需要執行怎樣的操作呢:
將要改寫的目標頁面所在的整個塊的數據讀取到緩存。
在緩存中修改目標頁面的數據。
對整個塊執行擦除操作。
將緩存中的數據重新寫入整個塊中。
這就意味著,如果我要修改某個4KB大小的頁面,就必須把512KB大小的整個塊都折騰一遍,大家應該可以想象出這將帶來何等巨大的性能和壽命上的損失。
正是出于上述原因,SSD中提供了一個TRIM命令,操作系統在刪除文件時可以通過向SSD發送TRIM命令告訴它哪些數據塊中的數據已經不再使用了。SSD在收到TRIM命令后,通常會在定期的垃圾收集操作中重新組織這些區塊,為將來寫入數據做好準備,不過每一款SSD在底層對TRIM命令的執行機制都不盡相同,但無論如何,通過TRIM能夠顯著改善SSD的性能和壽命。當然,大家可能已經發現了,有了TRIM,刪除的文件數據會被SSD自動回收,這意味著以往在傳統硬盤上能夠使用的一些數據恢復(反刪除)軟件,在SSD上可能就不再管用了。
既然TRIM如此重要,我應該如何啟用呢?一般來說,只要你所使用的操作系統支持TRIM,就無需額外的操作。支持TRIM的操作系統:Windows 7及后續版本、OS X 10.6.8及后續版本、Linux內核版本2.6.33及后續版本。
下面我們就來看一下Mac OS上用命令行開啟SSD trim的方法,非常簡單:
在終端里面運行下面四條命令。
1.
sudo cp /System/Library/Extensions/IOAHCIFamily.kext/Contents/PlugIns/IOAHCIBlockStorage.kext/Contents/MacOS/IOAHCIBlockStorage /System/Library/Extensions/IOAHCIFamily.kext/Contents/PlugIns/IOAHCIBlockStorage.kext/Contents/MacOS/IOAHCIBlockStorage.bak
2.
sudo perl -pi -e 's|\x00\x41\x50\x50\x4c\x45\x20\x53\x53\x44\x00|\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00|' /System/Library/Extensions/IOAHCIFamily.kext/Contents/PlugIns/IOAHCIBlockStorage.kext/Contents/MacOS/IOAHCIBlockStorage
3.
sudo touch /System/Library/Extensions
4.
sudo kextcache -prelinked-kernel /System/Library/Caches/com.apple.kext.cache/Startup/kernelcache -K /System/Library/Kernels/kernel /System/Library/Extensions