核心日記 前些天讀“linux核心原始碼情景分析”(毛德操),覺得開始寫得還不錯,後面的講解過於細節,讓人不能從整體上有個把握(看了幾本國內寫的核心的書,好象都是給幾段編碼,加點註解)。我感覺,即然核心也是一個軟體,就應該以軟體工程的方法去理解它。用軟體工程設計方法當然是:需求,總體設計,詳細設計,編碼等等。我想老毛的書基本在編碼講解層次上,讓人不能有一種宏觀把握的清晰思路。我感覺要讀懂源碼,應該首先從總體上理解,即弄明白設計理念,其次才是具體的編碼理解。所以我這兩天轉向從總體上把握它。現在在讀
<深入理解linux核心>,它寫得很好,我已讀了中斷異常,時鐘中斷,進程幾章,它把中斷異常,時鐘中斷設計的思路講得非常清楚,我推薦大家讀一下此書。
我有個問題還沒想太清楚,請大家指點:
一個進程要進入TASK_INTERRUPTIBLE OR TASK_UNINTERRUPTIBLE狀態,這應該具備什麼條件,及如何喚醒(能不能醒就看進程能不能被放入就緒隊列)?
這個問題我想了又想,覺得:
進程要睡覺有自願和被迫兩種
自願,主要是調sleep_on()等,他們的喚醒靠掛在定時器上的函數,此函數會把相應的睡眠進程放入就緒隊列,從而喚醒了進程。
被迫方式主要是因為等待事件。等待事件我理解為等待某訊號量可用,當核心功能幫進程檢查某訊號量是否可用時,若發現不可用,核心功能就會把進程掛到等待隊列中(訊號量的隊列中,好象掛到訊號量的隊列中便沒必要掛到等待隊列中,只要不讓進程掛到運行隊列便可),不讓進程被調度。當某進程釋放訊號量指示的資源或發出某事件時,它會調用類似的PV操作的V操作函數,此V操作函數會把等待進程放入就緒隊列,從而喚醒了進程。
這便是我對進程睡覺和被喚醒的理解,不知正確於否?歡迎發表你讀核心的感受。
相互交流,共同進步
__________________
寶劍鋒從磨礪出,梅花香自苦寒來
跟蹤進程如何查被跟蹤進程的記憶體資料?
首先聲明一下,本人一不小心把貼子發錯位置了,放到了“核心原始碼學習”,所以我在這裡又放了一份。
所以你若回貼,請回到核心日記裡。很是抱歉。
今日日記:
我想再問一個問題:
進入TASK_INT..,TASK_UNINT..的是不是都必須處在某個等待隊列中?
我的理解是:有的進程進入睡眠態根本不掛入等待隊列,
理由是:比如定時睡眠(核心功能為:sleep_on_timeout(),
interruptible_sleep_on_timeout()),這些函數會為進程申請一個動態定時器,然後把定時器的data域設成進程的PID,這樣當定時器到時,便會把進程喚醒,這就沒有用到等待隊列。
不知理解正確於否,歡迎指正。
今天看了訊號量機制和記憶體管理(buddy演算法和slab分配器,還有點問題,不過等看完再提),還有就是跟蹤系統調用。
我想就跟蹤再提個問題:
硬體對跟蹤提供了兩種機制:eflags的IF標誌,調試寄存器組
linux在進程式控制製表中提供:PF_TRACESYS標誌用來中斷系統調用
(不知還有沒有別的方式?)
當A進程被B進程跟蹤時,B則為A的父進程(這點應該沒有問題吧),若此時A遇上斷點被中斷,它會進入TASK_STOPPED狀態,B會收到一個SIGCHLD訊號,從而被喚醒當B運行時,它會檢查A的狀態,無外乎是看 B的硬體上下文,B的某記憶體資料,或B的進程式控制製表中能體現的所有資訊。(還會不會看別的什嗎?)
我現在想問:B通過系統調用要求看這些資訊時,核心如何服務?
我把我的想法寫出,歡迎補充指正:
1。B要看A的寄存器和進程式控制製表中能體現的所有資訊,核心只需從進程式控制製表中提取便可。
2。B要看記憶體某記憶體資料,則應該給系統調用傳地址參數,核心就必須想法找到
A的地址空間中找到此資料,如何找呢?(這是問題的關鍵) 我想核心會利用A的頁全域目錄,採用計算方法找此資料的物理地址,然後利用核心的記憶體的固定映射方法得到在A空間的線性地址(此地址>3G),然後就可以訪問到此資料。
不知我的理解是否正確?
__________________
寶劍鋒從磨礪出,梅花香自苦寒來
| 2003.04.19讀核日記: 2003.04.19讀核日記: 今天看記憶體管理,深感知識面不夠! 在記憶體管理的3個主要資料結構:BUDDY演算法,SLAB分配器,vm_area分塊,其中slab最難理解。 現在有一點不太明白,提出來請大家指點: kmalloc,vmalloc,malloc有什麼區別? 核心通過buddy對大塊實體記憶體進行管理,通過slab分配器對零碎的資料結構提供 分配服務,這樣核心所需的記憶體無論大塊小塊都有函數可用了。 那使用者進程的記憶體空間如何管理?核心通過vm_area_struct技術實現使用者線性空間大塊記憶體配置,比如:代碼區,資料區,堆區,棧區。我現在想問,當進程需要小塊記憶體時,由誰來管理?我知道,一般使用者通過malloc來分配零碎的記憶體。 但malloc通過什麼方法來對得到零碎記憶體,是通過系統調用,還是不用系統調用?我查了系統調用,好象沒有相應的系統調用,我又沒有發現核心為使用者空間的零碎記憶體管理提供任何演算法。所以我懷疑malloc沒有用系統調用,可不用系統調用它又用什麼方法來實現呢?我想了以想,覺得若malloc不用系統調用,則它必須自己來管理,即它必須自己建立一個管理資料結構,那又用什麼資料結構呢,最簡單的方法就是用鏈把已指派的零碎塊串起來,複雜一點的話也可仿slab來管理。 不知大家誰對malloc的分配機理清楚?若大家誰有C庫源碼,不妨共用一下。 對了,還有一個問題? 對庫如何?反組譯碼? __________________ 寶劍鋒從磨礪出,梅花香自苦寒來 |
| |
|
再問malloc brk只能修改堆棧的大小,或著說是邊界,而且它是以頁為單位。
malloc肯定要利用brk,但是malloc必須實現頁內的小對象的管理,必須在頁內一小塊一小塊的割記憶體.而這是brk無法勝任的
所以我懷穎malloc要自己實現小對象的管理。
不過我還沒證實。我已下載到C庫的源碼,不過可能一時半會還看不懂。
__________________
寶劍鋒從磨礪出,梅花香自苦寒來
2003.04.20讀核日記--未來LINUX架構隨想
2003.04.20讀核日記--未來LINUX架構隨想
今日瀏覽了一下VFS,對它的設計思想很是佩服。它實現的思路我的理解就如
PCI插槽,插上不同的獨立設計的具體檔案系統,便可擴充功能。
所以與其說VFS是一個通用檔案系統的介面,不如說它是一個技術規範。
通過這種規範,可實現不同的軟體的無縫對接。
再聯想到POSIX,不也是OS設計的規範嗎,所以我想,會不會有一天能把linux
的各部分之間也設計能用規範相聯,就如同組裝PC機一樣。不過,令人心慰的是
VFS已經實現了檔案系統與具體檔案系統的規範。我想下一步應該把記憶體管理也設計成規範,linux其它部分只通過標準的函數介面就能完成從實體記憶體分配,回收
,進程空間的管理,還有緩衝的管理。說到緩衝的管理,我想linux核心的緩衝主要有兩大類:一是固定對象的分配回收的緩衝(或叫緩衝池),如通過SLAB進行的小對象分配機制。二是高速緩衝,如磁碟塊的預讀管理,頁面的老化等。應該把這兩種緩衝管理也標準化。 說不定到那時,我們也可象設計具體檔案系統那樣把記憶體管理單獨設計成一個模組,然後不用重編核心,就可以把原記憶體管理模組通過如INS_MM_MODE的函數換成自己設計的記憶體管理模組。我都想過了,在替換時,要實現舊新工作的交接,即要把舊模組的資料記錄轉換給新模組,以使新模組重繪核心記憶體配置圖景。我們的目標:LINUX要傻瓜式組裝,將有許多記憶體管理,進程管理,檔案系統的外掛程式可選,以適應自己具體情況的需要。
不過目前的目標:好好讀核,不要空談。(這兩天學習有點冒進的苗頭,書光想住後翻)
希望大家也在此談談你們的讀核經驗,以讓象我這樣的棒槌少走點彎路。
__________________
寶劍鋒從磨礪出,梅花香自苦寒來
2003.04.21讀核日記--發現linux在初始化BUDDY演算法的資料結構時很低效
今日讀BUDDY記憶體配置演算法,演算法確實很不錯,但LINUX在初始化BUDDY演算法的資料結構時很低效。
我先打個比喻:給你一個大碗,裡面裝滿了大米,現在讓你大米轉移到
另一個碗裡,你是把米從一個碗直接倒到另一個碗裡,還是把米一粒一粒從一個碗放到另一個碗裡?答案是明確的,直接倒。
而linux在初始化BUDDY演算法的資料結構時卻選擇了類似把米從一個碗一粒一粒放到另一個碗裡方法。
好了,看看系統是如何初始化BUDDY演算法的資料結構的。
BUDDY在回收頁面時一般用free_pages(),free_page(),它們都要實現夥伴的合并。而且最多9-order次合并。
在mem_init()中,通過對所有的動態記憶體進行逐頁掃描,並調用free_page()來把空頁一頁一頁的插入BUDDY中。
事實上,動態記憶體就那麼幾大塊,所以完全可以用一個遞迴函式用很少的
次數就可完成工作。
我寫了一個:
buddy_init( start_addr,end_addr, order)
//start_addr,end_addr為要釋放的記憶體塊首尾,order為要插入的BUDDY槽號
{unsigned long mask=(~0ul)<
page * start,end; //中間以order為邊界的大塊的首尾地址
if(order==0)
{free_page(start_addr); return; } //遞迴出口,即只有一頁要求釋放
//求出start,end;
start=(start_addr+(1< end= end_addr&mask;
for(tmp=start,tmp {free_pages(tmp,order); //中間以order為邊界的大塊的釋放
}
if(start_addr!=start) //若相等,則說明沒有左零頭,不用再遞迴
buddy_init(start_addr,start,order-1);
if(end_addr!=end) //若相等,則說明沒有右零頭,不用再遞迴
buddy_init(end,end_addr,order-1);
}
函數寫的不嚴密,但其思想是盡量用free_pages()來大塊大塊的插入,
因為這樣一次最多可釋放512頁,比一頁一頁效率高多了。
__________________
寶劍鋒從磨礪出,梅花香自苦寒來
2003.4.21讀核日記更正
因為是先寫到記事本裡,再粘上來,但不知為什麼資料沒粘全,所以再粘一遍
很抱歉
今日讀BUDDY記憶體配置演算法,演算法確實很不錯,但LINUX在初始化BUDDY演算法的資料結構時很低效。
我先打個比喻:給你一個大碗,裡面裝滿了大米,現在讓你大米轉移到
另一個碗裡,你是把米從一個碗直接倒到另一個碗裡,還是把米一粒一粒從一個碗放到另一個碗裡?答案是明確的,直接倒。
而linux在初始化BUDDY演算法的資料結構時卻選擇了類似把米從一個碗一粒一粒放到另一個碗裡方法。
好了,看看系統是如何初始化BUDDY演算法的資料結構的。
BUDDY在回收頁面時一般用free_pages(),free_page(),它們都要實現夥伴的合并。而且最多9-order次合并。
在mem_init()中,通過對所有的動態記憶體進行逐頁掃描,並調用free_page()來把空頁一頁一頁的插入BUDDY中。
事實上,動態記憶體就那麼幾大塊,所以完全可以用一個遞迴函式用很少的
次數就可完成工作。
我寫了一個:
buddy_init( start_addr,end_addr, order)
//start_addr,end_addr為要釋放的記憶體塊首尾,order為要插入的BUDDY槽號
{unsigned long mask=(~0ul)<
page * start,end; //中間以order為邊界的大塊的首尾地址
if(order==0)
{free_page(start_addr); return; } //遞迴出口,即只有一頁要求釋放
//求出start,end;
start=(start_addr+(1< end= end_addr&mask;
for(tmp=start;tmp {free_pages(tmp,order); //中間以order為邊界的大塊的釋放
}
if(start_addr!=start) //若相等,則說明沒有左零頭,不用再遞迴
buddy_init(start_addr,start,order-1);
if(end_addr!=end) //若相等,則說明沒有右零頭,不用再遞迴
buddy_init(end,end_addr,order-1);
}
函數寫的不嚴密,但其思想是盡量用free_pages()來大塊大塊的釋放,
因為這樣一次最多可釋放512頁,比一頁一頁效率高多了。
__________________
寶劍鋒從磨礪出,梅花香自苦寒來
我很久以前也看過buddy演算法,也用它寫過程式,只是沒看過它的初始化的情況,只是好像有一點你沒有注意(不知道是不是我記錯了),例如你的start=(start_addr+(1"<<"order)-1)&mask;是不是應該在1"<<"order)後面來個PAGE_SHIFT,當然這是小事.至於你說的低效的問題.也許是.對了,你看過他的初始化程式,那麼最初系統是不是全部按照order從9,8..開始往下排列.也就是先排9order的,零星的排8,再零星的排7...
ps:會不會是系統初始化的時候,怕某塊實體記憶體壞了,造成記憶體空間的不連續性,所以要一頁一頁的插入合并阿?
ps2:你說的打不出某些程式,那是因為這個社區大概是為了安全或者別的編碼之類的原因,把一些特殊字元解釋錯了吧,比如你在兩個>之外加一對引號就能正常輸入你的程式了.
__________________
依然記得從你口中說出再見堅決如鐵,昏暗中有種烈日灼身的錯覺;
依然記得從你眼中滑落的淚傷心欲絕,混亂中有種熱淚燒傷的錯覺....
此帖於 2003-04-22 09:18 被 blueflame 編輯.
blueflame:
還是你經驗豐富呀,把沒顯示出來的東西看到了。
我現在也明白過來了:用查看原始碼直接讀此頁的html文本,你是不是這樣做的?
free_page()釋放一頁時,它會從order0開始,改相應的map標記,然後看能不能向上合并(就是通過map的相應位來判斷其夥伴在不在),若不可以,它就插入order0,然後返回;若可以,它會和夥伴合并,再向order1裡試插入,若還可以合并,則以此推,直到order9,才算結束。
所以若用free_page()初始化化BUDDY時,會發生大量的合并,(因為此時的動態記憶體是大塊連續的,所以最後,除左右零頭外,都是屬於order9的塊)
但若用free_pages(),則因為直接把order9的塊分離出來插入order9,所以根本不存在合并現象.至於左右零頭,它們會再分解,插入相應的槽中,也不會發生合并現象,因為試圖合并,必然失敗。
至於說是檢查實體記憶體是否損壞,我想可以分離出來,不要因為要掃描每頁實體記憶體,就“順便”初始化BUDDY,總之,用free_page()代價太大,(不過確實很
省心,不用另寫代碼了)
__________________
寶劍鋒從磨礪出,梅花香自苦寒來
2003.04.22讀核日記--slad演算法的2.4核心版本更簡潔了
今天讀了<<深入理解linux核心>>(第一版,2.2核心)的slab分配器原理。
書中講的kmem_cache_t,kmem_slab_t原理都非常清楚,但一到
kmem_bufctl_t時,讓人弄不清它到底如何同前兩個結構配合。(當然,這不是作者的過,而是2.2版本對演算法實現的不完美)。
最後,我不得不看原始碼(2.4.18版本),發現對”對象描述符“的實現有了很大的改進:
1。若SLAB描述符在SLAB內部,它由2.2版本在SLAB的尾部改到首部,且後面緊跟對象描述符。
2。對象描述符原則上可在內部或外部,但linux只把它放在內部,不再放在外部,所以不用記錄對象描述符的地址,通過kmem_cache_t,kmem_slab_t,及對象的地址便可算出對象描述符的地址,而且對象描述符的作用更加簡單,只是把Null 物件鏈起來;已指派的對象的對象描述符沒有什麼作用了。
我為弄清它,還看了understanding linux kernel第2版,還有情景分析。發現情景分析基本上就是代碼,所以講的不好,書中只有兩個圖,圖2.8畫的是2.2版本的情況,圖2.9則不知它要表達什麼。所以我建議大家看buddy和slab演算法時,看understanding linux kernel 第一版和第2版,比較著看,真是講得很好,它中的圖做的很精細,對理解演算法很有協助。
看看不同版本,想想linux的成長過程,不也是很有啟發意義的嗎?
__________________
寶劍鋒從磨礪出,梅花香自苦寒來
對2003.04.22讀核日記--更正
昨天發了關於slab演算法的文章,晚上睡覺又想了想,發現有點問題,所以一大早就爬起來,又分析了原始碼。
所以做以下更正:
對象描述符在linux2.4中還是可內可外的,只是它和slab描述符如影隨形。即它總是緊跟在slab描述符後面,因此,只要知道slab描述符的地址,便可算出對象描述符的地址。
總之,slab描述符在外,它就在外,slab描述符在內,它就在內;
當slab描述符在內時,放在slab區的開始處,即跟在著色區的後面。
當slab描述符在外時,因為不同的cache的slab區放的對象個數不同,所以一個slab所需要的對象描述符的個數是不同的,通過計算可得到“slab描述符加對象描述符數組”所需的記憶體大小,這便是分配slab描述符時的真正大小。所以在外的slab描述符可能分布在cache_sizes的不同cache中。
__________________
寶劍鋒從磨礪出,梅花香自苦寒來
blueflame:
謝謝你的關心。其實過去的一個月我都在看linux,整天的看,有時也看得很煩,當煩的時候,我就下載一部電影看看,或睡上一覺,也就沒什麼了。
我把學習Linux分成三個階段:第一階段是從整體上把linux的各種重要資料結構
和各部分之間的關係及工作機理從思想上想通,再輔之以學習系統編程(我把它稱為完成linux的總體設計)就目前來看,到下學期開學就可完成;第二階段是把linux再從頭到尾過一遍,主要完成原始碼的分析(我把它稱為實體設計);我估計需2個月。第三階段基本上就是不斷跟蹤Linux核心的發展,並有能力做一點修改。
請問你網路方面參考了什麼書?
你打算怎麼攻克它?
(笑也不爭春,只把春來報,待到山花爛漫時,她在從中笑)
__________________
寶劍鋒從磨礪出,梅花香自苦寒來
2003.04.25讀核日記--感謝大家的關心
謝謝大家的關心.我會繼續讀下去,把感慨發下去的。其實我只是想休息一兩天,修整修整,看看電影,不亦樂乎.
通過這些天讀核心管理,我感覺無論是記憶體的分配還是緩衝的管理,用的資料結構不是鏈表就是數組。而且為了更加有效管理一群對象,採用的方式無外乎是
:1。通過增加索引級數。如slab分配器:就通過3級來管理,最高一級是kmem_cache_s,接下來是kmem_slab_t,再下來是kmem_bufctl_s,最後是對象本身.(試想它為什麼會用3級,其實本來可以用一級的,即用hash或一條鏈串起來便可它最終就是要取個對象,中間級對外是隱藏的)只要能想通了這個,以後一看到要講資料結構,我就首先看看它是用幾級索引。然後我就能推斷出它的基主要組織結構,即不同層級之間如何關聯。
2。在同一層級的組織,採用的形式也無外乎:要麼是用鏈表串起來,要麼是數組,要麼用hash,要麼用樹(如AVL)。前兩種是基本形式,後兩種只不過為了增加速度。
注意到數組和鏈表的不同效果沒有?比如串數組是用位移作指標,而鏈表卻只能用地址作指標啦。
3。對分配來的空間進行二次分割時,也有兩種基本策略,一種是管理空閑塊法,即把空間離散塊串起來,典型的就是buddy,slab,別一種是把分配出去的串起來,典型的就是vma_area_struct,vma_struct;
再說vfs吧,說白了,系統根本目的就是為了實現按名存取(為了提高效率那叫改進,linux為了提高效率都改進了好幾年啦,所以不要指望馬上就學會人家的效率,所以我感覺一個軟體能實現它是第一步,其次才是改進它,cpu本身不也改進了好多年嗎?還在改進中。看看linux以前的版本,你就知道linus也不是什麼神仙,他的以前的版本的演算法有許多也是很爛的,只不過後來才改進的),一句話,本來是一級管理的本質問題.但若用一級索引,那檔案不多如牛毛嗎,所以才有了,按目錄,按邏輯盤,按進程等等的多級層次。所以想通了它。那整個資料結構也就曆曆在目了。
請大家補充指正!
再次感謝大家對我的關心。
__________________
寶劍鋒從磨礪出,梅花香自苦寒來
2003.04.28讀核日記--快取的資料結構的理解
今天讀了<<深入理解linux核心>>第14章磁碟快取,對它的資料結構基本理解了。這使我對VFS這一塊的閱讀有了很大的信心。
現將理解表述如下(本來想畫一張圖,但覺得太費事)
1。快取主要有3種:目錄快取,緩衝區快取和頁快取。
其實我覺得書中稱“緩衝區“及緩衝首部(buffer_head)這個詞不好。我覺得應該換個名字更好:比如叫:塊對象(block object)和塊描述符(block descripter)。
2.緩衝區快取的整個資料結構
1)建立一塊”緩衝區”和“緩衝區首部”,兩個來源不同
緩衝區來源於BUDDY,即BUDDY給分一個頁框,它再把這個頁框分成幾個等大的緩衝區。而緩衝區首部來源於SLAB分配器。
每一個緩衝區都要有一個緩衝區首部來描述它。一個頁框中的這幾個緩衝區你可稱它為兄弟,它們用一個鏈串起來的。
2)建立完後,它們是閒置,就必須把它管理起來,用作”周轉資金“,如何管理呢?
因為不同的裝置可能定義不同的塊大小,所以緩衝區的塊大小是不統一的。方法是把相同大小的緩衝區的緩衝區描述符(即緩衝區首部,但我還是喜歡叫它緩衝區描述符)串成一條鏈,這樣因為塊大小的可能情況是:512,1024,2048,4096,8192,16384,32768,所以共產生7條鏈。但一個塊大小不能超過一頁,所以PC機只用前4條鏈。7條鏈的鏈頭用一個數組free_list統一存放。好啦,空閑塊已經管理起來了,以後用,就可先從這裡取,若不夠,再新建立。
3)把分配出去的管理起來:因為這些緩衝區可能是乾淨的,髒的,或正要寫入磁碟。就把它們分成3條鏈串起來。3個鏈頭放在一個數組lru_list中。好啦,分配出去的也管理起來了。但為了快速尋找,再給它加個hash表,表為:hash_table
用hash就必須提供鍵,緩衝區的檢索就是用裝置號和塊號來作鍵的。
至於那些函數,只要腦裡有這個資料結構架構,則一看就懂。
3。頁快取的資料結構很相對簡單。不說了,但要注意的是他是
用索引節點和檔案位移作hash鍵的.還有要注意的是緩衝頁最終要分割成幾個緩衝區,並給這些塊緩衝區分配緩衝區描述符,利用緩衝區的寫回和讀取函數來完成磁碟的操作。(因為磁碟只認塊,不認頁),書中有幾幅很好的圖。能促進人理解這些結構。
歡迎指正。
__________________
寶劍鋒從磨礪出,梅花香自苦寒來
我也有同感,有時,我什麼也沒做,硬碟就狂轉不停,我想肯定是在交換,可又好象沒必要,我沒做什麼呀。
光看核心講解的書,我感到有點累了,沒有實踐,那麼多資料結構總記不住。所以我有點想換換方式,想學一段系統和模組編程,從外部觀察linux核心的行為。同時,也想把以前學過的核心原理好好消化一下,再前進,我感到與裝置有關的這塊不好弄,前面的BH又忘的差不多了,所以看起來有點吃力。
哎,學核心真是苦呀。簡直就是對人的毅立的考驗。
__________________
寶劍鋒從磨礪出,梅花香自苦寒來
2003.04.30讀核日記--關於FAT檔案系統的結構
應blueflame的提問,我把FAT更詳細的一些資料結構寫出,供大家參考:
總體結構依次是:
IPL(引導區),fat表1,fat表2,根目錄,資料區。
fat表2與fat表1一樣,主要是起備份作用。資料區以簇為基本單位進行分配。
IPL即起引導系統作用,又含有類似超級塊的資料,所以應該從這裡取超級塊的資訊。
fat表有兩個作用,一個是起記錄空閑塊的作用,一個起檔案資料鏈指標的作用。fat其實是個數組,它的每一項(fat12是12位算一項,即1.5個位元組,fat16是2位元組一項),每一項記錄它對應的簇的使用方式。當它為0,表示此簇空閑,當不為0,表示檔案的下一簇的簇號(別外有幾個特殊的數有特殊意義,如
fat16時,0xffff表示檔案結束,即沒有下一簇了。)
在fat中的簇與ext2中的塊是一個意思,都為基本分配單位。
從fat的結構可見,它比ext2簡單多了。檔案的不同塊通過fat表聯起來,而不象
ext2,把它放在i節點,或檔案內部(指二級,三級索引所需的塊)
下面為各部具體的結構:
1。IPL(initial program loader)結構:
佔一個扇區
位移(16進位) 長度(位元組) 內容
======================================
00 3 短跳指令
03 8 OEM廠家名和版本
0b 2 每扇位元組數
0d 1 每簇扇數
0e 2 預約的扇區數
10 1 FAT的個數
11 2 根目錄項數
13 2 邏輯扇區數
15 1 介質描述符
16 2 每FAT的扇區數
18 2 每磁軌扇區數
1a 2 磁頭數
1c 2 隱含的扇區數
--------------
1e IPL引導程式
---------------
4個分區表
2。FAT表的數值含義(指12位和16位的)
簇值(0x) 內容
========================
000(fat12) 空閑簇
0000(fat16)
---------------------------------------
001 不用的代碼
0001
---------------------------------------
ff7 不良簇(即簇可能有壞區)
fff7
--------------------------------------
ff8--fff 檔案結束標誌
fff8-ffff
---------------------------------------
002--ff6 下一個簇號
0002--fff6
=======================
3。 目錄項的結構:每項32位元組
位移 位元組數 內容
========================
00-07 8 檔案名稱
08-0a 3 副檔名
0b 1 檔案屬性
0x-15 10 保留區
16-17 2 最終編輯時間
18-19 2 最終編輯日期
1a-1b 2 起始簇號
1c-1f 4 檔案大小
檔案名稱第一位元組含義
00表示此目錄未使用
e5表示此目錄項被刪
2e,若第2位元組也是2E,則表示為父目錄(..)
若第2位元組不是2E,則表示為本身目錄(.)
檔案屬性:
0 唯讀
1 隱含
2 系統
3 卷標
4 子目錄
5 存檔
4。一些資料的計算:
注意:簇號從2開始排
邏輯扇區號=(簇號-2)*簇長+資料區起始扇號
邏輯扇區數=預約扇區數+(扇數每FAT)*FAT表數+根目錄扇區數+簇數*(扇數每簇)
根目錄扇區數=(根目錄項數*32)/(位元組每扇區)
最大簇號=簇數+1
FAT簇數<=4085 :用FAT12
>=4086 :用FAT16
如有錯誤,歡迎指正
也請有知道fat32,ntfs結構的人補充。
__________________
寶劍鋒從磨礪出,梅花香自苦寒來
2003.04.28讀核日記--快取的資料結構的理解
你說的緩衝區快取,一個頁框中可能會有幾個緩衝區.還有那7條練,在我的印象中好像那是關於檔案緩衝用的.而你說第三種頁快取才是用於檔案快取.我對於這幾種緩衝的叫法一直比較模糊.緩衝區快取是不是buffer cache.那應該好像不會用於檔案緩衝的.這種頁的mapping結構應該是null.
__________________
依然記得從你口中說出再見堅決如鐵,昏暗中有種烈日灼身的錯覺;
依然記得從你眼中滑落的淚傷心欲絕,混亂中有種熱淚燒傷的錯覺....
buffer cache就指得是緩衝區高緩,page cache指得是頁高緩,也就是你所說的檔案高緩,因為檔案就是以頁為單位進行讀寫,所以檔案用的高緩就是指頁高緩。
這兩個名英文名詞,我感覺給人一個錯覺,比如buffer一般讓人理解為一個緩衝區,無論其大小,但此處的buffer cache中的buffer 強調的是磁碟塊大小了緩衝區,它直接與磁碟讀寫聯絡,即磁碟上一個盤塊通過DMA讀入後,就首先放在buffer cache的一個buffer中,所以我感覺把這個buffer cache理解block cache
更讓人好理解。
因為一個檔案的一頁,在磁碟上可能對應幾個磁碟塊(因為1頁>1塊),且這幾個塊可能不是連續的,所以當把這個檔案的一個頁讀入記憶體,就必須把這個頁框分成幾個塊(由頁劃分的塊顯然連續),當磁碟上此頁的幾個磁碟塊讀入記憶體後,就連續的放入到此頁中,即幾個連續塊中。所以完成了由不連續的磁碟塊到連續的記憶體塊的映射。同時完成了外存的一頁到記憶體的一頁的映射。
所以說頁高緩最終要利用buffer高緩,來完成外存的讀寫,或者說它層次是:
外存檔案的一頁(分解為幾塊,可能不連續)------外存的磁碟塊-----記憶體的buffer塊-------記憶體檔案的一頁(由一個頁框劃分的幾個連續buffer構成).----頁高緩系統
2.4中用的address_space其實並沒什麼新鮮的,它不過是把頁高緩的管理資料更加集中存放罷了。所以只要懂2.2版,再看2.4就沒什麼難的。
表達能力有限,總感覺說不清楚,understanding linux kernel的第一版(2.2核心)和第二版(2.4核心)吧,它講得比較透徹。
__________________
寶劍鋒從磨礪出,梅花香自苦寒來
我看了blueflame推薦的那篇文章,但好象有幾個地方是不是有問題: "我們知道越是靠磁碟外部的柱面,旋轉越快,而且每次旋轉時,磁碟讀寫頭可以覆蓋較多的地區,也就意味著靠外部的柱面可以得到較好的效能。所以在分區時,我們應該考慮將訪問頻率高的,對系統效能影響相對較大的分區置於磁碟的靠外部分" 1。硬碟的磁軌是從裡到外編號,還是從外到裡?我沒查過資料,但光碟片是從裡到外編號應該沒什麼問題吧,這從刻光碟片時就可看出來,所以我想誰能查一下資料證實一下。 (他講的好象是從外到裡,而我懷疑) 2。他那麼分區我認為沒有用。因為磁碟轉速並不是勻速的,而是當磁頭從裡到外移動時,為了保持基本不變的讀資料的線速,必須不斷的調整轉速,使讀資料的線速基本不變,所以我懷疑他說的在磁頭在外面時,讀速快,是一種想當然的認識,也請大家證實一下。3。他講到用軟raid技術,我認為這不能提高效能,最多是增加了磁碟的冗餘度,從而提高了可靠性而已。 因為把同一個盤劃成不同的區,這些區必然有內外之別(這與用不同的硬碟作raid是兩碼事,因為不同的硬碟可並行操作,而同一個盤劃成不同區,也只能串列尋道,而且為了找不同的區,還必須不停的尋道)。所以我懷疑效能有提高這種說法,也請大家證實一下。 __________________ 寶劍鋒從磨礪出,梅花香自苦寒來 |
| |
|
不要指望交換演算法能讓你滿意了,若讓你滿意了,別人就不滿意了。你若想讓自己滿意,就必須使演算法的天平向你傾斜。
我看了understanding the linux kernel,總算明白了這個道理:
”As a matter of fact,the hardest job of a developer working on the virtual memory subsystem consists of finding an algorithm that ensures acceptable performances both to desktop machines and to high-level machines like large database servers.
Unfortunately,finding a good page frame reclaiming algorithm is a rather empirical job,with very little support for theory.The situation is somewhat similar to evaluation the parameters that achieve good system performance,without asking too many questions about why it works well.Often,it's just a matter of "let's try this approach and see what happens..."An unpleasant side effect of this empirical approach is the code changes quickly,even in the evennumbered versions of Linux,which are supposed to be stable.
“
所以,應該用”let's try this approach and see what happens..."心態去
讀這一部分的演算法,理解作者的用意便可。你要是不服氣,改改它,讓它適合你的胃口。
比如:你上面不斷的寫檔案,顯然不要緩衝,只要寫迴文件到硬碟才是最佳的演算法。
__________________
寶劍鋒從磨礪出,梅花香自苦寒來