2009年6月22日 星期一

善用檔案系統的 Extended Attributes

Standard
檔案系統(Filesystem)的技術對資訊科技產業貢獻極大,只要是提到檔案儲存,就不能沒有檔案系統的存在,廣義來說,只要是能夠提供格式使一筆筆檔案資料正確存入和取出,都可以稱做為一種檔案系統。而就一般人而言,對檔案系統(Filesystem)的認知,主要在於處理檔案名稱、權限、資料存取方法以及排列架構,其中偶爾也會討論到效能的問題。先不論效能優劣的問題,事實上,現今大多數檔案系統,都有著良好且先進的設計,不少的擴充性和功能都已經被支援,我們可以來細細探討其帶來的益處和便利性。

檔案系統範疇甚廣,有許多領域的技術可討論,在短短的篇幅中也無法交代完整,有興趣者可以自行在網路上搜尋到大批文獻和論文。本文重點將在於討論檔案系統的 Extended Attributes(延伸屬性),該屬性又稱 xattrs,這是一個可供 User-Space 應用程式存取的屬性,其提供『鍵/值(key/Value)』機制,且鍵值資料可被關聯到指定的檔案上。換言之,我們可以為檔案添加一些附屬的資料和性質,而不需要更動到檔案內部資料,或是另外設計一個資料庫以記錄這些檔案的關聯資料。

由於 Extended Attributes 被實作於檔案系統演算法的層面,當然並不是所有的檔案系統都有支援,像是有悠久歷史的 FAT 就缺少這類實作。而 Linux 上使用的 ext3,實作方式是將 Extended Attributes 記錄在目標檔案 inode 裡的可用空間之中,使讀取 Extended Attributes 的資料相當快速,我們不用擔心要許多的 I/O 操作才能達到存取的目的。

以下是幾個操作 Extended Attributes 的函式:
/* 取得目標檔案之『鍵/值』 */
ssize_t getxattr(const char *path, const char *name, void *value, size_t size)
/* 設定目標檔案之『鍵/值』 */
int setxattr(const char *path, const char *name, const void *value, size_t size, int flags)
/* 列出目標檔案之所有延伸屬性 */
ssize_t listxattr(const char *path, char *list, size_t size)
/* 刪除目標檔案之『鍵/值』 */
int removexattr(const char *path, const char *name)

以下是相同功能,但是針對 File Description 的函數:
ssize_t fgetxattr(int filedes, const char *name, void *value, size_t size)
int fsetxattr(int filedes, const char *name, const void *value, size_t size, int flags)
ssize_t flistxattr(int filedes, char *list, size_t size)
int fremovexattr(int filedes, const char *name)

一個實際 Extended Attributes 的應用,就是用在 MIME Types 的 cache 機制。不像 MS Windows,Unix-like 系統裡許多檔案是不能用副檔名判別檔案類型,導致一些 File Manager 都會去預讀檔案標頭和部份內容以判別類型,但這是一個很沒有效率的手段,因為有大量的 I/O 產生。因此,這問題逼迫各家 File Manager 都會去實作一套資料庫,對這些檔案類型做 cache,以便第二次開啟時能有效率的判別檔案類型。事實上,可以使用 Extended Attributes ,儲存目標檔案的類型,有效率的實作 cache 機制,只不過因為需要考慮到當下檔案系統是否支援,或許兩種方法並行才能解決此問題。