編輯:關於android開發
文件系統的文件太多,而且是照搬的MINIX的文件系統,不想繼續分析下去了。緩沖區機制和文件系統密切相關,所以這裡就簡單分析一下緩沖區機制。
buffer.c 程序用於對高速緩沖區(池)進行操作和管理。高速緩沖區位於內核代碼塊和主內存區之間,見圖9-9 中所示。高速緩沖區在塊設備與內核其它程序之間起著一個橋梁作用。除了塊設備驅動程序以外,內核程序如果需要訪問塊設備中的數據,就都需要經過高速緩沖區來間接地操作。
因為讀取磁盤數據很耗費時間,所以緩沖區的作用就是存儲讀過的磁盤數據,下次有需求直接從緩沖區讀取,緩沖區是內存區域,讀取非常快速。
圖中高速緩沖區的起始位置從內核模塊末段end 標號開始,end 是內核模塊鏈接期間由鏈接程序(ld)設置的一個值,內核代碼中沒有定義這個符號。當在連接生成system 模塊時,ld 程序的digest_symbols()函數會產生此符號。該函數主要用於對全局變量進行引用賦值,並且計算每個被連接文件的其始和大小,其中也設置了end 的值,它等於data_start + datasize + bss_size,也即內核模塊的末段。
整個高速緩沖區被劃分成1024 字節大小的緩沖塊,正好與塊設備上的磁盤邏輯塊大小相同。高速緩沖采用hash 表和空閒緩沖塊隊列進行操作管理。在緩沖區初始化過程中,從緩沖區的兩端開始,同時分別設置緩沖塊頭結構和劃分出對應的緩沖塊。緩沖區的高端被劃分成一個個1024 字節的緩沖塊,低端則分別建立起對應各緩沖塊的緩沖頭結構buffer_head(include/linux/fs.h,68 行),用於描述對應緩沖塊的屬性和把所有緩沖頭連接成鏈表。直到它們之間已經不能再劃分出緩沖塊為止,見圖9-10 所示。而各個buffer_head 被鏈接成一個空閒緩沖塊雙向鏈表結構。詳細結構見圖9-11 所示。
緩沖區的大致結構可參照buffer.c的buffer_init函數:
extern int end; // 由連接程序ld 生成的表明程序末端的變量。[??] struct buffer_head *start_buffer = (struct buffer_head *) &end; struct buffer_head *hash_table[NR_HASH]; // NR_HASH = 307 項。 static struct buffer_head *free_list; //// 緩沖區初始化函數。 // 參數buffer_end 是指定的緩沖區內存的末端。對於系統有16MB 內存,則緩沖區末端設置為4MB。 // 對於系統有8MB 內存,緩沖區末端設置為2MB。 void buffer_init (long buffer_end) { struct buffer_head *h = start_buffer; void *b; int i; // 如果緩沖區高端等於1Mb,則由於從640KB-1MB 被顯示內存和BIOS 占用,因此實際可用緩沖區內存 // 高端應該是640KB。否則內存高端一定大於1MB。 if (buffer_end == 1 << 20) b = (void *) (640 * 1024); else b = (void *) buffer_end; // 這段代碼用於初始化緩沖區,建立空閒緩沖區環鏈表,並獲取系統中緩沖塊的數目。 // 操作的過程是從緩沖區高端開始劃分1K 大小的緩沖塊,與此同時在緩沖區低端建立描述該緩沖塊 // 的結構buffer_head,並將這些buffer_head 組成雙向鏈表。 // h 是指向緩沖頭結構的指針,而h+1 是指向內存地址連續的下一個緩沖頭地址,也可以說是指向h // 緩沖頭的末端外。為了保證有足夠長度的內存來存儲一個緩沖頭結構,需要b 所指向的內存塊 // 地址 >= h 緩沖頭的末端,也即要>=h+1。 while ((b -= BLOCK_SIZE) >= ((void *) (h + 1))) { h->b_dev = 0; // 使用該緩沖區的設備號。 h->b_dirt = 0; // 髒標志,也即緩沖區修改標志。 h->b_count = 0; // 該緩沖區引用計數。 h->b_lock = 0; // 緩沖區鎖定標志。 h->b_uptodate = 0; // 緩沖區更新標志(或稱數據有效標志)。 h->b_wait = NULL; // 指向等待該緩沖區解鎖的進程。 h->b_next = NULL; // 指向具有相同hash 值的下一個緩沖頭。 h->b_prev = NULL; // 指向具有相同hash 值的前一個緩沖頭。 h->b_data = (char *) b; // 指向對應緩沖區數據塊(1024 字節)。 h->b_prev_free = h - 1; // 指向鏈表中前一項。 h->b_next_free = h + 1; // 指向鏈表中下一項。 h++; // h 指向下一新緩沖頭位置。 NR_BUFFERS++; // 緩沖區塊數累加。 if (b == (void *) 0x100000) // 如果地址b 遞減到等於1MB,則跳過384KB, b = (void *) 0xA0000; // 讓b 指向地址0xA0000(640KB)處。 } h--; // 讓h 指向最後一個有效緩沖頭。 free_list = start_buffer; // 讓空閒鏈表頭指向頭一個緩沖區頭。 free_list->b_prev_free = h; // 鏈表頭的b_prev_free 指向前一項(即最後一項)。 h->b_next_free = free_list; // h 的下一項指針指向第一項,形成一個環鏈。 // 初始化hash 表(哈希表、散列表),置表中所有的指針為NULL。 for (i = 0; i < NR_HASH; i++) hash_table[i] = NULL; }
根據上面的理論知識,這段代碼很好分析,就不多做解釋了。
ListView初探,初探網一、ListView介紹 在Android開發中ListView是比較常用的控件,常用於以列表的形式顯示數據集及根據數據的長度自適應顯示。 L
EventBus簡單使用教程 大家好! 首先申明一下,本人是一名初級Android程序員,剛接觸EventBus(3.0的用法)有什麼說的不對的地方還請大神指點一二。
Android動態資源加載原理和應用 動態加載資源原理 通常我們調用getResources()方法獲取資源文件 public Resources getResourc
Android工程打包成jar文件,並且將工程中引用的jar一起打入新的jar文件中,androidjar前言: 關於.jar文件: 平時我們Android項目開發中經常
Android中使用ExpandableListView實現微信通訊錄界