只有程式設計師才能讀懂的三國演義(二)

劉超的通俗雲端計算發表於2020-03-11

這是透過三國演義串起作業系統的原理,之前寫過五篇小馬創業篇,這次改編為三國演義篇。

上一篇,我們講到,劉備三顧茅廬請來諸葛亮,從而戰略,戰術,政務全方位體系都建立了。


第八回:諸葛陣法複合多變,程式同步方法多樣


自從諸葛亮當軍師以來,排兵佈陣便開始使用複合式戰法,往往是多個將軍帶著多隻部隊配合作戰。


諸葛亮排兵佈陣風格一,可見於赤壁大戰後對於華容道的安排。


孔明便與玄德、劉琦升帳坐定,謂趙雲曰:“子龍可帶三千軍馬,渡江徑取烏林小路,揀樹木蘆葦密處埋伏。今夜四更已後,曹操必然從那條路奔走。等他軍馬過,就半中間放起火來。雖然不殺他盡絕,也殺一半。”雲曰:“烏林有兩條路:一條通南郡,一條取荊州。不知向那條路來?”孔明曰:“南郡勢迫,曹操不敢往;必來荊州,然後大軍投許昌而去。”雲領計去了。又喚張飛曰:“翼德可領三千兵渡江,截斷彝陵這條路,去葫蘆谷口埋伏。曹操不敢走南彝陵,必望北彝陵去。來日雨過,必然來埋鍋造飯。只看煙起,便就山邊放起火來。雖然不捉得曹操,翼德這場功料也不小。”飛領計去了。


對於關羽,孔明曰:“昔日曹操待足下甚厚,足下當有以報之。今日操兵敗,必走華容道;若令足下去時,必然放他過去。因此不敢教去。”雲長曰:“願依軍法!”雲長曰:“若曹操不從那條路上來,如何?”孔明曰:“我亦與你軍令狀。雲長大喜。孔明曰:“雲長可於華容小路高山之處,堆積柴草,放起一把火煙,引曹操來。”雲長曰:“曹操望見煙,知有埋伏,如何肯來?”孔明笑曰:“豈不聞兵法虛虛實實之論?操雖能用兵,只此可以瞞過他也。他見煙起,將謂虛張聲勢,必然投這條路來。將軍休得容情。”雲長領了將令,引關平、周倉並五百校刀手,投華容道埋伏去了。


只有程式設計師才能讀懂的三國演義(二)


對於這次的排兵佈陣,諸葛亮採用的是串聯式,也即在敵人的必經之路上,依次埋伏將領,每個將領處理一批敵人,剩下的交給下一個環節。


在Linux裡面,有一種類似的程式間通訊機制,就是管道。


所謂的管道,就是在兩個程式之間建立一條單向的通道,其實是一段快取,它會將前一個命令的輸出,作為後一個命令的輸入。


只有程式設計師才能讀懂的三國演義(二)


管道的方式比較簡單,缺點是必須事先全部安排好,如果有變動比較難靈活處理,需要依賴神機妙算,比如曹操如果沒有按計劃走華容道的話,也來不及通知關羽了。


軍隊之間通訊的第二種方式就是靠人,也即靠信使。就是我們常聽到的,報!!!大事不好!!!再探!!!


只有程式設計師才能讀懂的三國演義(二)


例如在夷陵之戰的時候,信使將劉備聯營七百里的圖本傳給諸葛亮看,可是已經晚了。所以這種方式的實時性也不好。


在Linux裡面,和管道將資訊一股腦兒地從一個程式,倒給另一個程式不同,訊息佇列有點兒像郵件,傳送資料時,會分成一個一個獨立的資料單元,也就是訊息體,每個訊息體都是固定大小的儲存塊,在位元組流上不連續。


在Linux裡面還有非常實時的一種模式,就是共享記憶體+訊號量。


程式間通訊的共享記憶體模型的原理是這樣的。前面我們們講記憶體管理的時候,知道每個程式都有自己獨立的虛擬記憶體空間,不同的程式的虛擬記憶體空間對映到不同的實體記憶體中去。這個程式訪問A地址和另一個程式訪問A地址,其實訪問的是不同的實體記憶體地址,對於資料的增刪查改互不影響。

 

但是,我們們是不是可以變通一下,拿出一塊虛擬地址空間來,對映到相同的實體記憶體中。這樣這個程式寫入的東西,另外一個程式馬上就能看到了,都不需要複製來複製去,傳來傳去。

 

共享記憶體也有問題呀。如果兩個程式使用同一個共享記憶體,大家都往裡面寫東西,很有可能就衝突了。例如兩個程式都同時寫一個地址,那先寫的那個程式會發現內容被別人覆蓋了。

 

當然,和共享記憶體配合的,有另一種保護機制,使得同一個共享的資源,同時只能被一個程式訪問叫訊號量。

 

訊號量其實是一個計數器,主要用於實現程式間的互斥與同步,而不是用於儲存程式間通訊資料。

 

我們可以將訊號量初始化為一個數值,來代表某種資源的總體數量。對於訊號量來講,會定義兩種原子操作,一個是P操作,我們稱為申請資源操作。這個操作會申請將訊號量的數值減去N,表示這些數量被他申請使用了,其他人不能用了。另一個是V操作,我們稱為歸還資源操作,這個操作會申請將訊號量加上M,表示這些數量已經還給訊號量了,其他人可以使用了。

 

例如,你有100元錢,就可以將訊號量設定為100。其中A向你借80元,就會呼叫P操作,申請減去80。如果同時B向你借50元,但是B的P操作比A晚,那就沒有辦法,只好等待A歸還錢的時候,B的P操作才能成功。之後,A呼叫V操作,申請加上30元,也就是還給你30元,這個時候訊號量有50元了,這時候B的P操作才能成功,才能借走這50元。

 

所謂原子操作(Atomic Operation),就是任何一塊錢,都只能透過P操作借給一個人,不能同時借給兩個人。也就是說,當A的P操作(借80)和B的P操作(借50),幾乎同時到達的時候,不能因為大家都看到賬戶裡有100就都成功,必須分個先來後到。


只有程式設計師才能讀懂的三國演義(二)


共享記憶體+訊號量這種模式類似八門金鎖陣,好處是配合緊密,不是和一個人戰鬥,而是和所有人。但是訊號量的控制非常重要,要有個人站在最高處控制,在極端場景下,訊號量設計不好容易死鎖。比如趙雲破陣,如從東南角上生門擊人,往正西景門而出,其陣必亂。



上面的這些機制,基本常規狀態下的工作模式,如果發生了異常怎麼辦?例如出現線上系統故障,這個時候,什麼流程都來不及了,不可能發郵件,也來不及開會,所有的架構師、開發、運維都要被通知緊急出動。所以,7乘24小時不間斷執行的系統都需要有告警系統,一旦出事情,就要通知到人,哪怕是半夜,也要電話叫起來,處理故障。是不是應該還有一種異常情況下的工作模式。


當然應該有,我們可以建立像作業系統裡面的訊號機制。訊號沒有特別複雜的資料結構,就是用一個代號一樣的數字。Linux提供了幾十種訊號,分別代表不同的意義。訊號之間依靠它們的值來區分。這就像我們們看警匪片,對於緊急的行動,都是說,‘1號作戰任務’開始執行,警察就開始行動了。情況緊急,不能囉裡囉嗦了。

 

訊號可以在任何時候傳送給某一程式,程式需要為這個訊號配置訊號處理函式。當某個訊號發生的時候,就預設執行這個函式就可以了。這就相當於我們們運維一個系統應急手冊,當遇到什麼情況,做什麼事情,都事先準備好,出了事情照著做就可以了。


只有程式設計師才能讀懂的三國演義(二)


這種訊號模式,諸葛亮經常使用,例如火燒博望坡的時候,諸葛亮是這樣佈置的。孔明令曰:“博望之左有山,名曰豫山;右有林,名曰安林:可以埋伏軍馬。雲長可引一千軍往豫山埋伏,等彼軍至,放過休敵;其輜重糧草,必在後面,但看南面火起,可縱兵出擊,就焚其糧草。翼德可引一千軍去安林背後山谷中埋伏,只看南面火起,便可出,向博望城舊屯糧草處縱火燒之。關平、劉封可引五百軍,預備引火之物,於博望坡後兩邊等候,至初更兵到,便可放火矣。”又命:“於樊城取回趙雲,令為前部,不要贏,只要輸,主公自引一軍為後援。各須依計而行,勿使有失。”


只有程式設計師才能讀懂的三國演義(二)


第九回:孫劉聯盟赤壁破曹,網路通訊多機合作


諸葛亮輔佐劉備打了幾個勝仗,但是曹操實力太強,還是敵不過,最終要按照隆中對中計劃的一樣,和孫權聯合攻抗曹操。


但是兩個集團的合作能否成功呢?這依賴於雙方的合作協議是如何談的。


在Linux裡面,伺服器之間的協作要靠網路協議。


這其實就像機器與機器之間合作,一臺機器將自己想要表達的內容,按照某種約定好的格式傳送出去。當另外一臺機器收到這些資訊後,也能夠按照約定好的格式解析出來,從而準確、可靠地獲得傳送方想要表達的內容。這種約定好的格式就是網路協議。

 

現在業內知名的有兩種網路協議模型,一種是OSI的標準七層模型,一種是業界標準的TCP/IP模型。它們的對應關係如下圖所示:


只有程式設計師才能讀懂的三國演義(二)


下面我們來解析一下網路協議。


我們先從第三層網路層開始,因為這一層有我們熟悉的IP地址,所以這一層我們也叫IP層。

 

連線到網路上的每一個裝置都至少有一個IP地址,用於定位這個裝置。無論是近在咫尺的、你旁邊同學的電腦,還是遠在天邊的電商網站,都可以透過IP地址進行定位。因此,IP地址類似網際網路上的郵寄地址,是有全域性定位功能的。

 

就算你要訪問美國的一個地址,也可以從你身邊的網路出發,透過不斷地打聽道兒,經過多個網路,最終到達目的地址,和快遞員送包裹的過程差不多。打聽道兒的協議也在第三層,我們稱為路由協議。將網路包從一個網路轉發給另一個網路的裝置,我們稱為路由器。

 

總而言之,第三層乾的事情,就是網路包從一個起始的IP地址,沿著路由協議指的道兒,經過多個網路,透過多次路由器轉發,到達目標IP地址。


IP層是網路協議裡面的核心層,承上啟下。


對於劉備集團和孫權集團來講,首先雙方建立聯絡的,就是諸葛亮和魯肅。這兩個人都是雙方中流砥柱的人才,也是制定戰略的人才。就像兩臺機器要通訊事先雙方知道對方的IP地址一樣,諸葛亮和魯肅互相聞名已久。


魯子敬願親到江夏,搬請諸葛亮共議破曹大計。孫權因劉備兩次打敗曹操,急於摸清曹軍兵力,同意魯肅去江夏探聽虛實。諸葛亮於是決定隻身入吳,要憑三寸不爛之舌,去說孫、曹兩家互相吞併。


只有程式設計師才能讀懂的三國演義(二)


從第三層,我們往下看。第二層是資料鏈路層。有時候我們簡稱為二層或者MAC層。所謂MAC,就是每個網路卡都有的唯一的硬體地址(不絕對唯一,相對大機率唯一即可,類比UUID)。這雖然也是一個地址,但是這個地址是沒有全域性定位功能的。

 

就像給你送外賣的小哥,不可能根據手機尾號找到你家,但是手機尾號有本地定位功能的,只不過這個定位主要靠“吼“。外賣小哥到了你的樓層就開始大喊:“尾號xxxx的,你外賣到了!“

 

MAC地址的定位功能侷限在一個網路裡面,也即同一個網路號下的IP地址之間,可以透過MAC進行定位和通訊。從IP地址獲取MAC地址要透過ARP協議,是透過在本地傳送廣播包,也就是“吼“,獲得的MAC地址。

 

由於同一個網路內的機器數量有限,透過MAC地址的好處就是簡單。匹配上MAC地址就接收,匹配不上就不接收,沒有什麼所謂路由協議這樣複雜的協議。當然壞處就是,MAC地址的作用範圍不能出本地網路,所以一旦跨網路通訊,雖然IP地址保持不變,但是MAC地址每經過一個路由器就要換一次。

 

所以第二層乾的事情,就是網路包在本地網路中的伺服器之間定位及通訊的機制。


我們再往下看第一層,物理層。這一層就是物理裝置。例如,連著電腦的網線,我們能連上的WiFi。


魯肅和諸葛亮各管各的屬下,這不消說。到了東吳的地盤,諸葛亮也是一切聽魯肅安排,因為江東的地理,人物,政治,權力格局,也是隻有魯肅最清楚的。


只有程式設計師才能讀懂的三國演義(二)


到了東吳,諸葛亮也是遍訪東吳人物,摸清各自主戰主和,最終敲定關鍵要勸說的人物——周瑜。這就相當於ARP透過廣播獲取目標MAC了。


從第三層往上看,第四層是傳輸層,這裡面有兩個著名的協議,TCP和UDP。尤其是TCP,更是廣泛使用,在IP層的程式碼邏輯中,僅僅負責資料從一個IP地址傳送給另一個IP地址,丟包、亂序、重傳、擁塞,這些IP層都不管。處理這些問題的程式碼邏輯寫在了傳輸層的TCP協議裡面。

 

我們常說,TCP是可靠傳輸協議,也是難為它了。因為從第一層到第三層都不可靠,網路包說丟就丟,是TCP這一層透過各種編號、重傳等機制,讓本來不可靠的網路對於更上層來講,變得“看起來”可靠。哪有什麼應用層的歲月靜好,只不過是TCP層在負重前行。


對於東吳來講,兩個比魯肅更加重要的兩個人物,就是張昭和周瑜,這兩個一個主戰,主張和劉備達成協作,是周瑜,是TCP,也即定向建立連線,一個主和,主張投降曹操,是張昭,是UDP,也即和誰通訊都行。


只有程式設計師才能讀懂的三國演義(二)


接下來,諸葛亮要和周瑜建立TCP連線了,也即三次握手,智激周瑜。


只有程式設計師才能讀懂的三國演義(二)


傳輸層再往上就是應用層,例如,我們們在瀏覽器裡面輸入的HTTP,Java服務端寫的Servlet,都是這一層的。


孫權就是應用層了。


只有程式設計師才能讀懂的三國演義(二)


 

二層到四層都是在Linux核心裡面處理的,應用層例如瀏覽器、Nginx、Tomcat都是使用者態的。核心裡面對於網路包的處理是不區分應用的。

 

從四層再往上,就需要區分網路包發給哪個應用。在傳輸層的TCP和UDP協議裡面,都有埠的概念,不同的應用監聽不同的埠。例如,服務端Nginx監聽80、Tomcat監聽8080;再如客戶端瀏覽器監聽一個隨機埠,FTP客戶端監聽另外一個隨機埠。

 

應用層和核心互通的機制,就是透過Socket系統呼叫。所以經常有人會問,Socket屬於哪一層,其實它哪一層都不屬於,它屬於作業系統的概念,而非網路協議分層的概念。

 

作業系統對於網路協議的實現模式是這樣的:二到四層的處理程式碼在核心裡面,七層的處理程式碼讓應用自己去做。兩者需要跨核心態和使用者態通訊,就需要一個系統呼叫完成這個銜接,這就是Socket。

 

如果公司想要和其他公司溝通,我們將請求封裝為HTTP協議,透過Socket傳送到核心。核心的網路協議棧裡面,在TCP層建立用於維護連線、序列號、重傳、擁塞控制的資料結構,將HTTP包加上TCP頭,傳送給IP層,IP層加上IP頭,傳送給MAC層,MAC層加上MAC頭,從硬體網路卡發出去。

 

最終網路包會被轉發到目標伺服器,它發現MAC地址匹配,就將MAC頭取下來,交給上一層。IP層發現IP地址匹配,將IP頭取下來,交給上一層。TCP層會根據TCP頭中的序列號等資訊,發現它是一個正確的網路包,就會將網路包快取起來,等待應用層的讀取。

 

應用層透過Socket監聽某個埠,因而讀取的時候,核心會根據TCP頭中的埠號,將網路包發給相應的應用。


只有程式設計師才能讀懂的三國演義(二)


第十回:赤壁大勝又得荊益,裝置眾多統一管理


聯合了孫權之後,果真赤壁大勝曹操,諸葛亮趁機佔領了荊州,並以荊州為根基,進一步佔領了益州,隆中對中的計劃算是完成了一半。


還記得隆中對怎麼說的嘛?


若跨有荊、益,保其巖阻,西和諸戎,南撫夷越,外結好孫權,內修政理;天下有變,則命一上將將荊州之軍以向宛、洛,將軍身率益州之眾出於秦川,百姓孰敢不簞食壺漿,以迎將軍者乎?誠如是,則霸業可成,漢室可興矣。


現在“跨有荊、益,保其巖阻”問題解決了,接下來就是“西和諸戎,南撫夷越,外結好孫權,內修政理”,由於劉備算是從夾縫裡面打出一片自己的天下,所以導致面臨的環境比較複雜,周圍各個方面的關係都要照顧好。


這有點像一家公司要做To B的生意,發現客戶多種多樣,眾口難調,不同的地域不一樣,不同的行業不一樣。如果你不懂某個地方的規矩,根本賣不出去東西;如果你不懂某個具體行業的使用場景,也無法滿足客戶的需求。怎麼辦呢?一般公司採取的策略就是建立生態,設定很多代理商,讓各個地區和各個行業的代理商幫你遮蔽這些差異化。你和代理商之間只要進行簡單的標準產品交付就可以了。


諸葛亮自有一套自己的辦法,從他七擒孟獲就可以看出來。


只有程式設計師才能讀懂的三國演義(二)


作為Linux作業系統,需要管理的裝置也是複雜多樣的。我們能舉出來的,例如鍵盤、滑鼠、顯示器、網路卡、硬碟、印表機、CD/DVD等等,多種多樣。這樣,當然方便使用者使用了,但是對於作業系統來講,卻是一件複雜的事情,因為這麼多裝置,形狀、用法、功能都不一樣,怎麼才能統一管理起來呢?我們一層一層來看。


只有程式設計師才能讀懂的三國演義(二)


 

第一層,用裝置控制器遮蔽裝置差異。

 

CPU並不直接和裝置打交道,他們中間有一個叫作裝置控制器(Device Control Unit)的元件。例如,硬碟有磁碟控制器、USB有USB控制器、顯示器有影片控制器等。這些控制器就像代理商一樣,他們知道如何應對硬碟、滑鼠、鍵盤、顯示器的行為。

 

你的代理商往往是小公司。控制器其實有點兒像一臺小電腦。他有他的晶片,類似小CPU,執行自己的邏輯。他也有他的暫存器。這樣CPU就可以透過寫這些暫存器,對控制器下發指令,透過讀這些暫存器,檢視控制器對於裝置的操作狀態。

 

CPU對於暫存器的讀寫,可比直接控制硬體,要標準和輕鬆很多。這就相當於你和代理商的標準產品交付。

 

第二層,用驅動程式遮蔽裝置控制器差異。

 

雖然代理商機制能夠幫我們遮蔽很多裝置的細節,但是從上面的描述我們可以看出,由於每種裝置的控制器的暫存器、緩衝區等使用模式,指令都不同。對於我們們公司來講,就需要有個部門專門對接代理商,向其他部門遮蔽代理商的差異,成立公司的渠道管理部門。

 

那對於作業系統來講,渠道管理部門就是用來對接各個裝置控制器的裝置驅動程式。

 

這裡需要注意的是,裝置控制器不屬於作業系統的一部分,但是裝置驅動程式屬於作業系統的一部分。作業系統的核心程式碼可以像呼叫原生程式碼一樣呼叫驅動程式的程式碼,而驅動程式的程式碼需要發出特殊的面向裝置控制器的指令,才能操作裝置控制器。

 

裝置驅動程式中是一些面向特殊裝置控制器的程式碼。不同的裝置不同。但是對於作業系統其他部分的程式碼而言,裝置驅動程式應該有統一的介面。就像下面圖中的一樣,不同的裝置驅動程式,可以以同樣的方式接入作業系統,而作業系統的其他部分的程式碼,也可以無視不同裝置的區別,以同樣的介面呼叫裝置驅動程式。


只有程式設計師才能讀懂的三國演義(二)

 

 

第三,用中斷控制器統一外部事件處理。

 

馬哥聽了恍然大悟:“原來代理商也是五花八門,裡面有這麼多門道啊!”

 

魯肅說:“當我們們對接的代理商多了,代理商可能會有各種各樣的問題找到我們,例如代理商有了新客戶,客戶有了新需求,客戶交付完畢等事件,都需要有一種機制通知你們公司,這種通知機制就是中斷,那作業系統就需要有一個地方處理這個中斷,既然裝置驅動程式是用來對接裝置控制器的,中斷處理也應該在裝置驅動裡面完成。

 

然而,中斷的觸發最終會到達CPU,會中斷作業系統當前執行的程式,所以作業系統也要有一個統一的流程來處理中斷,使得不同裝置的中斷使用統一的流程。

 

一般的流程是,一個裝置驅動程式初始化的時候,要先註冊一個該裝置的中斷處理函式。我們們講程式切換的時候說過,中斷返回的那一刻是程式切換的時機。中斷的時候,觸發的函式是do_IRQ。這個函式是中斷處理的統一入口。在這個函式里面,我們可以找到裝置驅動程式註冊的中斷處理函式Handler,然後執行他進行中斷處理。


只有程式設計師才能讀懂的三國演義(二)


第四,用檔案系統介面遮蔽驅動程式的差異。

 

對接了這麼多代理商,如果我們們內部的工程師要和他們打交道,有沒有一種統一的方式呢?當然應該了,我們內部員工操作外部裝置,可以基於檔案系統的介面,制定一個統一的標準。

 

其實檔案系統的機制是一個非常好的機制,我們們公司應該定下這樣的規則,一切皆檔案。

 

所有裝置都在/dev/資料夾下面,建立一個特殊的裝置檔案。這個裝置特殊檔案也有inode,但是他不關聯到硬碟或任何其他儲存介質上的資料,而是建立了與某個裝置驅動程式的連線。

 

有了檔案系統介面之後,我們不但可以透過檔案系統的命令列操作裝置,也可以透過程式,呼叫read、write函式,像讀寫檔案一樣操作裝置。

 

對於塊裝置來講,在驅動程式之上,檔案系統之下,還需要一層通用裝置層。比如,我們們講的檔案系統,裡面的邏輯和磁碟裝置沒有什麼關係,可以說是通用的邏輯。在寫檔案的最底層,我們看到了BIO字眼的函式,但是好像和裝置驅動也沒有什麼關係。

 

是的,因為塊裝置型別非常多,而Linux作業系統裡面一切是檔案。我們也不想檔案系統以下,就直接對接各種各樣的塊裝置驅動程式,這樣會使得檔案系統的複雜度非常高。所以,我們在中間加了一層通用塊層,將與塊裝置相關的通用邏輯放在這一層,維護與裝置無關的塊的大小,然後通用塊層下面對接各種各樣的驅動程式。


只有程式設計師才能讀懂的三國演義(二)


第十一回:巧取漢中劉備稱王,虛擬化後更加靈活


公元209年,“劉備”奪取“荊南四郡”,再到214年拿下益州,219年將曹操打敗奪取漢中,從此蜀國進入最為鼎盛的時期。


只有程式設計師才能讀懂的三國演義(二)


建安二十四年(公元219年)秋,劉備在諸葛亮和文臣武將的推尊之下,於沔陽登壇受賀,晉位漢中王。並立公子劉禪為王世子。封諸葛亮為軍師,總理軍國重事。封關羽、張飛、趙雲、馬超、黃忠為五虎大將。


只有程式設計師才能讀懂的三國演義(二)


看似一帆風順的劉備集團,也暗藏危機。因為劉備創業可謂南征北戰,跑遍整個中國,所以蜀漢集團成分也比較複雜。


第一派:元老派,主要人員:關羽、張飛、趙雲、孫乾、簡雍、糜氏兄弟。特點:這是劉備最信任的一個派系,早期就跟隨劉備東奔西跑、顛簸流離,不論遇到什麼困難都不離不棄。他們來自北方各地,是蜀漢政權的元老勳臣。


第二派:荊州派,主要人員:諸葛亮、黃忠、魏延、蔣琬,費禕、馬氏兄弟。特點:這是劉備在荊州時招攬的一批人,特別是劉表去世後,許多荊州氏族加入劉備陣營,這些人組成蜀漢政權的荊州派系。這個派系以諸葛亮為首,文武均衡,掌握著蜀漢政權的核心力量,甚至可以說,荊州派系支撐著蜀漢執行。


第三派:東州派,主要人員:法正、李嚴、許靖、董和、孟達、董允。特點:這是劉焉入蜀時帶去益州的一批人,同時劉焉還把南陽、三輔一帶數萬戶入蜀的流民收編為“東州兵”。因為有較強的軍事力量,東州派在蜀漢的地位全面壓制益州派,他們成為蜀漢政權的中層權力掌握者。


第四派:益州派,主要人員:黃權、李恢、馬忠、譙周、王平。特點:這些人是益州本土豪族,是益州真正的主人。然而,因為蛋糕有限,益州派成為打壓的物件,特別是失去荊州後,矛盾更加嚴重。雖然這個派系處於最底層,但是強龍不壓地頭蛇,沒有人敢輕視他們的力量。


應該如何管理這麼複雜的一個體系呢?當然是要發揮各自的作用,每個派系找個代表人物了。


這在司馬懿五路伐蜀的時候,諸葛亮的應對可以看出來。


只有程式設計師才能讀懂的三國演義(二)


老臣先知西番國王軻比能引兵犯西平關。臣料馬超積祖西川人氏,素得羌人之心,羌人以超為神威天將軍。臣已先遣一人星夜馳檄,令馬超緊守西平關,伏四路奇兵,每日交換,以兵拒之。此一路不必憂矣。


只有程式設計師才能讀懂的三國演義(二)


又南蠻孟獲兵犯四郡,臣亦飛檄遣魏延領一軍左出右入,右出左入,為疑兵之計。蠻兵惟憑勇力,其心多疑,若見疑兵,必不敢進。此一路又不足憂矣。


只有程式設計師才能讀懂的三國演義(二)


又知孟達引兵出漢中。達與李嚴曾結生死之交,臣回成都時,留李嚴守永安宮。臣已作一書,只做李嚴親筆,令人送與孟達。達必然推病不出,以慢軍心。此一路又不足憂矣。


只有程式設計師才能讀懂的三國演義(二)


又知曹真引兵犯陽平關。此地險峻,可以保守。臣已調趙雲引一軍守把關隘,並不出戰。曹真若見我軍不出,不久自退矣。


只有程式設計師才能讀懂的三國演義(二)


只有東吳這一路兵,未必便動:如見四路兵勝,川中危急,必來相攻;若四路不濟,安肯動乎?臣料孫權想曹丕三路侵吳之怨,必不肯從其言。雖然如此,須用一舌辯之士,徑往東吳,以利害說之,則先退東吳,其四路之兵何足憂乎?鄧芝陳說吳、蜀、魏三國之勢,論證吳蜀聯合之利、吳魏聯合之弊。孫權從其言,決心與蜀結盟抗魏並遣使張溫入蜀答禮。


只有程式設計師才能讀懂的三國演義(二)


蜀國其實就是得了大公司病——不靈活。

 

這裡面的不靈活,就像Linux伺服器,越來越強大的時候,無論是計算、網路、儲存,都越來越牛。例如,記憶體動不動就是百G記憶體,網路裝置一個埠的頻寬就能有幾十G甚至上百G。儲存在資料中心至少是PB級別的,自然也有不靈活的毛病。

 

資源大小不靈活:有時候我們不需要這麼大規格的機器,可能只想嘗試一下某些新業務,申請個4核8G的伺服器試一下,但是不可能採購這麼小規格的機器。無論每個專案需要多大規格的機器,公司統一採購就限制幾種,全部是上面那種大規格的。

 

資源申請不靈活:規格定死就定死吧,可是每次申請機器都要重新採購,週期很長。

 

資源複用不靈活:反正我需要的資源不多,和別人共享一臺機器吧,這樣不同的程式可能會產生衝突,例如socket的埠衝突。另外就是別人用過的機器,不知道上面做過哪些操作,有很多的歷史包袱,如果重新安裝則代價太大。

 

按說,大事情流程嚴禁沒問題,很多小事情也要被拖累走整個流程,而且很容易出現資源衝突,每天跨部門的協調很累人,歷史包袱嚴重,創新沒有辦法輕裝上陣。

 

很多公司處理這種問題採取的策略是成立獨立的子公司,獨立決策,獨立運營。這種辦法往往會用在創新型的專案上。

 

Linux也採取了這樣的手段,就是在物理機上面建立虛擬機器。每個虛擬機器有自己單獨的作業系統、靈活的規格,一個命令就能啟動起來。每次建立都是新的作業系統,很好地解決了上面不靈活的問題。

 

在物理機上的作業系統看來,虛擬機器是一個普通的應用,他和Excel一樣,只能執行在使用者態。但是對於虛擬機器裡面的作業系統核心來講,執行在核心態,應該有高的許可權。

 

要做到這件事情,第一種方式,完全虛擬化。其實說白了,這是一種“騙人”的方式。虛擬化軟體會模擬假的CPU、記憶體、網路、硬碟給到虛擬機器,讓虛擬機器裡面的核心自我感覺良好,感覺他終於又像個核心了。在Linux上,一個叫作qemu的工具可以做到這一點。

 

qemu向虛擬機器裡面的客戶機作業系統模擬CPU和其他的硬體,騙客戶機,GuestOS認為自己和硬體直接打交道,其實是同qemu模擬出來的硬體打交道,qemu會將這些指令轉譯給真正的硬體。由於所有的指令都要從qemu裡面過一手,因而效能就會比較差。

 

第二種方式,硬體輔助虛擬化。可以使用硬體CPU的Intel-VT和AMD-V技術,需要CPU硬體開啟這個標誌位(一般在BIOS裡面設定)。當確認開始了標誌位之後,透過核心模組KVM,GuestOS的CPU指令將不用經過Qemu轉譯,直接執行,大大提高了速度。qemu和KVM融合以後,就是qemu-kvm。


只有程式設計師才能讀懂的三國演義(二)


 

第三種方式稱為半虛擬化。對於網路或者硬碟的訪問,我們讓虛擬機器核心載入特殊的驅動,重新定位自己的身份。虛擬機器作業系統的核心知道自己不是物理機核心,沒那麼高的許可權。他很可能要和很多虛擬機器共享物理資源,所以學會了排隊。虛擬機器寫硬碟其實寫的是一個物理機上的檔案,那我的寫檔案的快取方式是不是可以變一下。我傳送網路包,根本就不是發給真正的網路裝置,而是給虛擬的裝置,我可不可以直接在記憶體裡面複製給它,等等等等。

 

網路半虛擬化方式是virtio_net,儲存是virtio_blk。客戶機需要安裝這些半虛擬化驅動。客戶機核心知道自己是虛擬機器,所以會直接把資料傳送給半虛擬化裝置,然後經過特殊處理(例如排隊、快取、批次處理等效能最佳化方式),最終傳送給真正的硬體。這在一定程度上提高了效能。


第十二回:夷陵大敗劉備託孤,資料中心作業系統


然而劉備的全盛時期持續太短了,並沒有像諸葛亮規劃的一樣,等到了統一全國的時機。


隨著關羽走麥城失荊州,劉備興兵伐吳兵敗夷陵,創業未半而中道崩出。後來,諸葛亮規劃的隆中對中局勢已經不存在,為了不負先帝託付,諸葛亮六出祁山,姜維九伐中原,終不能成功。


諸葛亮規劃的一統江山,也只有五丈原臨終的夢中實現了。


只有程式設計師才能讀懂的三國演義(二)


不過,我們的作業系統故事還需要寫下去。


對於單臺Linux伺服器,最重要的四種硬體資源是CPU、記憶體、儲存和網路。面對整個資料中心成千上萬臺機器,我們只要重點關注這四種硬體資源就可以了。如果運維資料中心依然像的運維一臺臺物理機的前輩一樣,天天關心哪個程式放在了哪臺機器上,使用多少記憶體、多少硬碟,每臺機器總共有多少記憶體、多少硬碟,還剩多少記憶體和硬碟,那頭就大了。

 

對於資料中心,我們需要一個排程器,將運維人員從指定物理機或者虛擬機器的痛苦中解放出來,實現對於物理資源的統一管理,這就是Kubernetes,也就是資料中心的作業系統。


只有程式設計師才能讀懂的三國演義(二)



對於CPU和記憶體這兩種計算資源的管理,我們可以透過Docker技術完成。

 

容器實現封閉的環境主要要靠兩種技術,一種是看起來是隔離的技術,稱為namespace。在每個namespace中的應用看到的,都是不同的 IP地址、使用者空間、程式ID等。另一種是用起來是隔離的技術,稱為cgroup,即明明整臺機器有很多的 CPU、記憶體,但是一個應用只能用其中的一部分。

 

另外,容器裡還有映象。也就是說,在你焊好集裝箱的那一刻,將集裝箱的狀態儲存下來的樣子。就像孫悟空說“定!”,集裝箱裡的狀態就被“定”在了那一刻。然後,這一刻的狀態會被儲存成一系列檔案。無論在哪裡執行這個映象,都能完整地還原當時的情況。

 

透過容器,我們可以將CPU和記憶體資源,從大的資源池裡面隔離出來,並透過映象技術,在資料中心裡面實現計算資源的自由漂移。

 

沒有作業系統的時候,彙編程式設計師需要指定程式執行的CPU和記憶體實體地址。同理,資料中心的管理員,原來也需要指定程式執行的伺服器以及使用的CPU和記憶體。現在,Kubernetes裡面有一個排程器Scheduler,你只需要告訴它,你想執行10個4核8G的Java程式,它會自動幫你選擇空閒的、有足夠資源的伺服器,去執行這些程式。

 

對於儲存,無論是分散式檔案系統和分散式塊儲存,需要對接到Kubernetes,讓Kubernetes管理它們。如何對接呢?Kubernetes會提供CSI介面。這是一個標準介面,不同的儲存可以實現這個介面來對接Kubernetes。是不是特別像裝置驅動程式呀?作業系統只要定義統一的介面,不同的儲存裝置的驅動實現這些介面,就能被作業系統使用了。

 

對於網路,也是類似的機制,Kubernetes同樣是提供統一的介面CNI。無論你用哪種方式實現網路模型,只要對接這個統一的介面,Kubernetes就可以管理容器的網路。


至此,整個作業系統的機制就講完了。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69940595/viewspace-2679672/,如需轉載,請註明出處,否則將追究法律責任。

相關文章