由于本書寫于1990年代,CEF還是cisco最新的黑科技. 是以其中很多關于作業系統的内容已經不太正确.Cisco的作業系統也從最開始的IOS一種形式到後來的Linux做control plane的IOS,IOS-XR,IOS-XE,NX-OS 等等等. 我相信書中提到的很多玩意已經不再使用,或者起碼有所變化,但是由于沒有更新的版本的書講新的作業系統的内部,是以還是隻能從這本書上了解.從學習的角度來看,從一個比較原始的形态學習也有助于一步步了解更複雜的系統. 是以不要過分糾結書的年代和細節内容.
作業系統
首先書中複習了下大學作業系統的基本概念,作業系統本質是用來抽象硬體和做資源配置設定的.
由于要講CPU的資源配置設定,繼續複習了大學作業系統中的線程,程序,核心的概念.根據CPU配置設定資源的情況排隊政策不同,分類為FIFO,有優先級的FIFO,可搶占的多任務系統.各種不同排隊政策的優劣勢大概大家可以想出來,比如實時性無法滿足,霸占CPU資源,切換的多了又會出現因為CPU要不停的切換現場帶來的資源浪費等等一堆廢話,有興趣的可以複習下大學課本.
除了CPU資源,另外一個很重要的資源就是記憶體了. 再次幫你複習一下什麼是作業系統配置設定的記憶體和虛拟記憶體.然後畫風一轉,說了一句大廢話.IOS系統由于為了保證性能,是以沒有完全實作虛拟記憶體.
IOS作業系統
IOS系統曆史久遠,那個時代大家為了省系統資源基本什麼事情都做的出來. 更何況IOS這種系統開始隻是為了轉發,後來功能是越加越多.是以缺失了一些其他作業系統最基本的功能,比如程序之間連記憶體的保護都沒有.
從圖上你可以看到系統中的幾部分,很有意思的是他不像日常我們現在接觸的linux,區分使用者态和核心态.看上去更像是一堆功能堆在一起的,我一直以為路由的計算等等功能應該是在使用者态實作之後然後通過類似于system call的東西傳送給核心态,但是從這個圖來看早起的IOS來看應該是根本沒有的.
名字就代表了基本功能,還算明顯,process應該對應到裝置上面應該就是所謂的主要卡所執行的大多數任務.packet buffer就是接口收到所有要轉發的包的集合,需要注意的是一些網工(其實就是我)會思考硬體上面的具體某個東西(比如queue)來和這個對應.但是從作業系統的角度來看,永遠是CPU和記憶體在交換資料,所謂的硬體queue之類的東西在這個圖裡面其實是在device driver層面的東西. 核心就是更多作業系統的基本功能了,CPU和記憶體資源的排程. 快速轉發這一塊,下一章再說.
記憶體
記憶體這一塊,IOS基本沒有用虛拟記憶體來擴充記憶體空間.是以他對記憶體的使用上面也是直接使用,沒有抽象成傳統操作的記憶體頁再提供給應用程式.這樣目的應該還是為了省出來一些記憶體資源.
IOS把記憶體區分不同的區域,稱為regions. 這個regions基本就和實體記憶體是一一對應的關系.其中的DRAM基本就是用來做日常我們接觸到的功能,比如用來跑IOS,留給程序存取變量之類的.SRAM是用來做packet buffer做快速轉發. (由于大學作業系統也沒有學的很好,還是搜了下DRAM和SRAM的差別,簡單可以了解為DRAM便宜,SRAM貴,SRAM比較塊.)
現在在IOS的路由器上面還是可以用show region指令看到具體IOS的記憶體配置設定情況.
這個圖就是記憶體region的劃分.
你真的特别想搞明白具體是幹嘛的.我推薦你複習下大學作業系統的課本.簡單的可以了解是main裡面跑了IOS和IOS運作起來需要的動态的記憶體空間.PCI和IO就是PCI總線上面和IO裝置要用的記憶體空間.從整個記憶體的角度大概是這麼個情況.
但是一般我們會用到一個show memory的指令,看IOS記憶體空間使用情況.這個指令就是具體更具體的顯示了每一部分記憶體的使用情況,不過這個指令的輸出真的很長.
程序
IOS其實是用了一個非搶占的排程CPU的模式.看上去有點蠢,因為網絡裝置本質是要快速處理來的包,如果不能搶占,包來了你的CPU不能及時轉發.這是個非常傻X的事情.我們會在第二章講包交換架構的時候提到這個事情是怎麼解決的. 非搶占的優勢還是有的,CPU不用來回儲存現場切換來去,效率高了一點,其次對程式員來說程式設計容易.(這段基本純翻譯,看到最後一句的時候我都驚呆了….)
程序的一生
其實在IOS裡面有一個paser程序,基本負責了大多數建立.paser程序就是在你敲完指令之後分析配置檔案,然後根據配置檔案做相關的事情.比如你剛敲了router eigrp.他就起了個eigrp程序.你no掉這個eigrp程序的時候,這個parser就會幹掉這個程序.
圖其實已經比較清楚簡單的解釋了一個程序的一生,其中modification這個狀态應該指的是說這個程序建立的時候需要的一些參數,我可以想象到的就是比如你在配置OSPF的時候router id這些參數是這在這個狀态被添加到程序當中的,當然這是我的了解,可能完全是錯的.
show process這個指令可以看到具體程序的具體資訊. IOS當中程序的優先級分4個,Critical,High,Medium,Low.
- Ciritical: 主要是系統必須要用的基礎服務
- High: 重要的必須要快速響應的.比如端口收到了一個包
- Medium: 大多數系統程序都在這.比如我們用的路由協定
- Low: 最不重要的,比如log
對于show process更細緻的解釋,請自行搜尋.或者參見inside Cisco IOS software architecture的相關内容.
CPU資源管理
在核心當中用來配置設定CPU資源的就是scheduler, 所有的程序被配置設定到6個queue當中.6個queue分為三個大類.
- idle queue: 空閑的queue,等待别的事件讓他active
- dead queue: 程序結束了,但是記憶體相關資源還沒有被作業系統回收
- ready queue: 就是可以執行的程序。他們又将程序分為不同的優先級
- Critical
- High
- medium
- low
配置設定資源算法簡單說起來就是在每執行一個程序之後,都要去看有沒有優先級更高的程序應該被執行用來. 如果有,一定保證優先級更好的程序被執行.
通過show process cpu可以看到CPU的使用情況
其中圖中的百分之90和百分之82表示了前五秒CPU的被程序的總消耗和其中具體進行中斷的消耗,這裡百分之8的內插補點主要指的是互相程序之間切換導緻的損耗.最後剩下的百分之10,就是scheduler本身所消耗掉的CPU資源.
我們之前提到過IOS是通過一個非搶占的方式配置設定CPU資源,這樣就有一個很常見的問題.一個資源如果霸占着CPU不放手,那要怎麼辦. 在IOS當中有個玩意叫watchdog timer來解決這個問題. 工作原理就是一個程序啟動之後,開始對這個程序計時,當過了2秒之後,這個程序還是占着CPU資源.他就把CPU的控制權還給scheduler,如果scheduler還是把CPU給這個程式,而且這個資源繼續霸占CPU2秒.這個程序就會被幹掉.
記憶體資源管理
這裡就是之前提到過的region manager把實體記憶體劃分成不同的region. pool manager就是配置設定動态是記憶體資源.系統最開始啟動的時候是一塊大的記憶體資源,當不同程序申請釋放之後.記憶體塊就會變得多個小塊,pool manager就是盡量保證釋放後的記憶體能有盡量大單塊資源. show memory和show memory free可以看到具體程序使用記憶體的情況.
pool manager有一個缺點就是每個管理的block都有一個32byte的overhead,當記憶體block很大的時候,這點overhead無所謂.當有多個小block的時候,這個overhead就很要命了.這裡IOS就有一個chunk manager來解決這個問題. chunk manager其實就是把一個大的block分成N個大小固定的chunk,當程序申請記憶體的時候,chunk manager就會把幾個chunk給這個程序.這個chunk manager整個block才有一個32byte的overhead.是以比pool manager每個block多一個32byte的overhead省了不少記憶體空間.
記憶體配置設定問題
之前都提到的都是配置設定成功的.記憶體也有配置設定不成功的時候,主要有兩個原因.一個就是記憶體空間不夠了.還有一種可能就是記憶體空間雖然夠,但是最大的block不滿足程序的需求. show memory可以看到目前最大的記憶體block是多少.如果有程序需求比這個block要大,就會導緻程序無法建立.
Packet Buffer 管理
IOS系統會在記憶體建立一塊區域專門存放要轉發的資料包.在IOS系統内部管理packet buffer的是buffer pool manager.
IOS系統當中通過packet buffer manager會建立不同種類的packet buffer pool,其實這個pool也就是一塊記憶體區域.它根據不同的類型可能是靜态的,動态的.所有程序都可以通路的,或者是某個程序才能通路的.
系統Buffer
IOS作業系統有一個公共的buffer叫系統buffer.這個buffer就是用來處理收到的資料包,也存放裝置自己産生的資料包.通過show buffer指令可以看到具體的資訊.
系統buffer會根據MTU的不同,又分為不同的隊列(具體這樣處理是不是比較快,我也不能确定,可能是因為CPU處理固定長度的會有很大的優勢,起碼直接根據長度直接提取出相應的位元組). 具體show出來的内容解釋就需要參考書了.
一個簡單的例子說明下buffer的工作原理.
這是一個初始狀态的用來放104byte包大小的buffer.
在前8個包進入buffer的時候隻會簡單的占用8個,剩下8個.此時請注意,剩下的buffer數量已經等于min buffer的大小.此時,如果還有包進入buffer.系統會嘗試保持最小buffer,換句話說,如果這個時候進來了4個包,也就是一共12個包進入buffer.這時buffer會從16漲到20.請注意,這裡并非無限增長的.如果繼續有包進入buffer,buffer就會停止漲下去.多餘的包就會被丢棄.(這裡為什麼是從16漲到20,書上也并非說的特别清楚,隻是舉例說show出來buffer不同的狀态.根據我的猜測,應該是在一個時間間隔内嘗試滿足buffer的需求,即使這樣,應該會也有個上限.書中完全沒有提到,在次我們隻能做大概了解)
最終狀态的buffer樣子:
其中可以看到此時buffer大小其實是20,永久buffer是16,最後會釋放多餘的記憶體空間.20 hits指的就是最後buffer能接受資料包的數量.13 miss這個計數器是當buffer小于min buffer的時候他就會增長.4 created就是動态建立了4個buffer.最後有一個包被丢棄标示為1 failure. 如果覺得此處解釋的不清楚.請參考書上例子,有圖解.
裝置驅動
毋庸置疑,所有硬體裝置都需要驅動.IOS也不例外,不過值得一提的就是IOS網卡驅動分為兩大塊.一個是控制部分,比如shut down端口.另外一部分是流量轉發.第二章會講到網卡驅動會和包轉發緊密聯系在一起.
IOS的驅動通過非常特殊的方式(interface descriptor block)和其他部分溝通(我也不知道一般作業系統通過什麼方式). IDB裡面存儲了接口的IP位址,接口狀态,接口相關統計等等等.
總結
IOS作業系統其實和其他作業系統差別不大,隻有兩個是需要很注意的,記憶體資源有限,對于轉發的要求.(我相信現在對于記憶體的要求變化差距應該很大了,曾經是很缺記憶體,現在情況并非這樣了).
其中IOS比較奇葩的就是把記憶體平鋪起來,所有程序随便用.此處注意,IOS程序相當于别的系統的線程(可能是由于記憶體可以随便通路是以才這麼說?當年也沒有多核CPU啊).