(轉)Linux中的位圖

原文:https://www.jianshu.com/p/74626c2d2916node

什麼是位圖

位圖(bitmap)的定義

  • 維基百科中關於位圖的介紹:

一種數據結構,表明了有限域中的稠集(dense set),每個元素至少出現一次,沒有其餘的數據和元素相關聯。在索引、數據壓縮等方面有普遍應用。linux

  • 本身的理解
    位圖就是按位(bit)來記錄、索引某個對象狀態的圖表(map),即用每一位(bit)來存放每個對象的某種狀態(例如分別用0和1表示的話,能夠表示同一對象的兩種狀態)。

這在數據規模大、而數據狀態又不是不少的狀況下,用來索引判斷某個數據的狀態(如存不存在、有沒有被使用等)很方便。數組

Linux內核中的位圖

位圖接口的聲明

位圖在Linux內核中被大量使用。下面的源代碼文件包含這些位圖結構的通用接口:數據結構

  • lib/bitmap.c
  • include/linux/bitmap.h

除了這兩個文件,還有一個特定的架構頭文件,對特定架構的位運算進行優化。對於x86_64架構,使用下面頭文件:架構

  • arch/x86/include/asm/bitops.h

在Linux內核中,位圖是一個unsigned long類型的數組。所以,一個位圖能夠簡單地聲明爲:ide

unsigned long my_bitmap[16]; /* 聲明一個16比特的位圖 */ 

它就像這個樣子:函數

 
位圖示例

將數據【5,1,7,15,0,4,6,10】存入後,結構變爲:優化


 
置位操做

實際上,在Linux內核中有一個專門的DECLARE_BITMAP宏來聲明位圖(該宏位於頭文件include/linux/types.h中):this

#define DECLARE_BITMAP(name,bits) unsigned long name[BITS_TO_LONGS(bits)] 

其中,參數name是位圖的名字,bits是位圖中比特的總數目。atom

Linux內核源碼中對位圖的介紹:

19 /* 20 * bitmaps provide an array of bits, implemented using an an 21 * array of unsigned longs. The number of valid bits in a 22 * given bitmap does _not_ need to be an exact multiple of 23 * BITS_PER_LONG. 24 * 25 * The possible unused bits in the last, partially used word 26 * of a bitmap are 'don't care'. The implementation makes 27 * no particular effort to keep them zero. It ensures that 28 * their value will not affect the results of any operation. 29 * The bitmap operations that return Boolean (bitmap_empty, 30 * for example) or scalar (bitmap_weight, for example) results 31 * carefully filter out these unused bits from impacting their 32 * results. 33 * 34 * These operations actually hold to a slightly stronger rule: 35 * if you don't input any bitmaps to these ops that have some 36 * unused bits set, then they won't output any set unused bits 37 * in output bitmaps. 38 * 39 * The byte ordering of bitmaps is more natural on little 40 * endian architectures. See the big-endian headers 41 * include/asm-ppc64/bitops.h and include/asm-s390/bitops.h 42 * for the best explanations of this ordering. 43 */ 

位圖的兩個重要操做

置位(set bit)和清零(clear bit)是位圖的兩種重要的操做,在頭文件arch/x86/include/asm/bitops.h實現了這些操做。在這兩類操做中,每一個函數分兩種類型:原子類型和非原子類型。非原子類型的實現比較簡單,介紹以下:

置位操做

/** * __set_bit - Set a bit in memory * @nr: the bit to set (位圖中的比特數目) * @addr: the address to start counting from (位圖中某個比特須要設值的地址) * * Unlike set_bit(), this function is non-atomic and may be reordered. * If it's called on the same region of memory simultaneously, the effect * may be that only one operation succeeds. */ static inline void __set_bit(long nr, volatile unsigned long *addr) { asm volatile("bts %1,%0" : ADDR : "Ir" (nr) : "memory"); } 

在該函數中,指令bts用來選擇位圖中的某個比特值 來做爲首個操做數,而後將已選擇的比特值 存入寄存器CF標籤中,並設置此比特位。

清零操做

static inline void __clear_bit(long nr, volatile unsigned long *addr) { asm volatile("btr %1,%0" : ADDR : "Ir" (nr)); } 

該函數用來清除某個地址的某個比特值。
指令btr與指令bts相似,選擇某個比特值做爲首個操做數,而後將其值存入寄存器CF標籤中,並清除位圖中的這個比特值,而且將位圖做爲指令的第二個操做數。

位圖在Ext2文件系統中的應用

Ext2文件系統結構圖示意以下:


 
ext2文件系統結構示意圖

在Ext2文件系統中,採用了位圖來存儲信息的結構有:

  • 組描述符表(GDT,Group Descriptor Table,可用df命令查看)
  • 塊位圖(Block Bitmap)
  • inode位圖(inode Bitmap)

各項具體含義參考文章

查找文件流程

以查找/home/slot目錄下的文件myfile爲例,該文件的完整路徑就是/home/slot/myfile,系統首先從根目錄/開始查找,根目錄/的inode編號固定爲2

 
根目錄的inode編號

在根目錄/下的目錄項中查找名字爲home的目錄:

 
根目錄下的文件信息

實際上目錄文件的結構很是簡單,就是一系列目錄項(dirent)的列表。每一個目錄項由如下幾部分組成:

  • 所包含文件的文件名;
  • 文件名對應的inode編號
  • 文件類型;
  • 記錄長度。

接下來根據文件名找到其對應的inode編號:

 
home對應的inode編號

(同理依次找到目錄slot下文件myfile的inode編號。)
再接下來,根據inode編號,查看inode table,找到具體的inode,inode中記錄了兩類信息:

  • 文件屬性;
  • 文件指針。

其中,文件指針指向磁盤上的數據塊(data block),文件的具體信息就存儲在這些block上。因此,最終根據這些文件指針找到文件內容。

注意:
最後三個文件指針都是間接指針,指向間接尋址塊(Indirect Block)(一級、二級、三級間接尋址),而非數據塊。

整個流程以下圖所示:


 
文件尋址流程

刪除文件流程

當使用命令 rm filename 刪除一個文件時,系統其實是刪除了其inode編號,具體是每調用一次 rm filename 命令,就將filename對應的inode編號的硬鏈接數減一(並刪除相應目錄下的目錄項),當硬鏈接數減爲0時系統才釋放該inode編號,以待分配給其它新的文件使用。

系統每次分配inode編號,是從全部可用的inode編號中選擇最小的那個。

固然,在刪除inode編號以前,系統要先釋放數據塊(即將bitmap中對應的位清零)。

因此,使用rm命令實際上只是刪除了文件的inode編號(這也是爲何通常刪除操做都很快),而文件數據仍然存放在磁盤上,只是沒法再查看到。所以,只要找到文件對應的inode信息,就能夠將文件內容恢復出來(前提是這些數據block沒有被後來的其它數據所覆蓋。因此在誤刪文件後,應當即中止全部寫操做,以防止原有數據被覆蓋)。

相關文章
相關標籤/搜索