天天看點

Linux作業系統基礎解析之(二)——作業系統由來

  什麼是應用程式軟體?

  對于大多數人而言,軟體就是一個能夠完成某些功能的應用程式。我們在日常的生活和工作中,隻要使用計算機類的裝置,就不可避免的會使用各種各樣的軟體。尤其是現在手持智能終端裝置的廣泛流行,使得應用程式(APP)的概念更加的深入人心,甚至以前從來沒有接觸過程式設計的人也能很流暢的說出這樣的術語來。

  其實,軟體的的确确就是由程式員使用某種程式設計語言編寫出來的,但是程式編寫出來之後,是如何被使用的呢?這個恐怕就不是每個人都知道,也不是每個人都能說的清楚的事情了。大家可能會很納悶,标題不是《作業系統基礎》麼?怎麼說了這麼半天的軟體呢?大家莫着急,接下來,跟大家一起來聊一聊計算機應用程式的運作原理,進而引出作業系統的概念及其功能。

  首先,值得大家注意的是:程式是由指令和資料構成的。從另外一個角度來講,我們也可以認為程式是由算法和資料結構構成的。不管程式員使用何種程式設計語言編寫出來的程式,都是以最為簡易和原始的純文字檔案的形式存放于計算機或者類似裝置的外部存儲器之中的。而所謂的指令和資料是一并存儲在這些檔案中的。這些程式源代碼,是利用一種更加接近我們人類的自然語言的語言編寫的。軟體的運作離不開硬體建構和硬體環境,也就是說,軟體必須在某個特定架構的硬體系統上運作才可以。而所謂的軟體的運作,一般是指,将儲存軟體程式執行功能的檔案從磁盤或其他外部存儲器中加載至記憶體,分别存放在指令段和資料段,然後再由CPU調用指令短資訊,通過指令指針寄存器找到位于記憶體中某個位置的資料并對該資料實施運算操作,最終輸出結果的過程。整個軟體的運作都是在記憶體和CPU之間徘徊的。也就是說,想要一個程式運作起來,就必須得能夠讓程式加載到記憶體,并且能夠被CPU處理才行。

  而我們的計算機是數字裝置(所謂的數字裝置,大家可以簡單了解為能夠進行數字資訊的運算和處理的裝置,而且根據數字計算機隻能處理二進制的資料。),無法了解這些進階程式源代碼中所應用的人類的自然語言,是以,程式必須經過處理之後編碼成二進制流才能被底層硬體所執行。但是硬體裝置非常的底層,硬體所提供的功能也非常的底層,提供給使用者的接口也是非常的簡單和醜陋的,是以,為了友善大多數的程式員可以基于底層硬體進行程式開發,硬體制造商會把這些把這些醜陋的接口抽象成更加具體和容易使用的彙編接口。但是彙編接口仍然非常的底層,每個程式員想要将這些使用進階語言編寫的程式在硬體上運作起來,就必須對這些硬體程式再開發一個能夠順利完成彙編功能的程式——驅動程式。這無疑會加大程式員的開發負擔。而且,對于同一個硬體架構平台上的不同應用程式來說,其底層的支援應該是相同的,是以驅動程式也應該是相同的,是以,每個程式都需要單獨開發驅動程式就顯得多餘而且是完全沒有必要的。于是就有人站出來,專門為這些底層硬體開發驅動程式,然後共享出來,使得所有程式員在實施程式開發的時候,不需要自行編寫這段代碼,而隻是在需要的時候調用這些驅動程式就可以了。這樣一來,大大簡化了程式員開發的過程,縮短了程式開發的周期,也為程式的穩定運作提供了保證,畢竟不是每個程式員寫的驅動程式都是那麼穩定的。至此,程式員開發的程式,在調用了驅動程式之後,就可以通路硬體了,然後再彙編成二進制流就可以被CPU直接處理了。這樣一來,每個程式就是一個計算機的運作的基本機關,這個運作中的程式,我們不再稱呼他為程式,而是稱他為程序(Process)。

  但是,問題還沒有結束。在早期的Mainframe主機上,通常都是大家拿着自己的顯示器和鍵盤,連接配接到專用的終端接口上來使用計算機計算資源。而整個主機上也隻有一段連續的記憶體空間,通常也隻有一顆CPU,那麼如果多個使用者同時使用該主機,并且都發起了一個程序的話,計算機該如何處理呢?其實最核心的問題就是:多個程序是如何占有和使用記憶體和CPU資源的。其實,在早期的計算機上是不支援多任務的,是以,某個終端上啟動一個程式,如果這個時候計算機正在處理其他的程序,那麼剛剛計劃啟動的程序就隻能等到那個更早執行更早占用系統資源的其他程序的執行結束之後,才能被加載至記憶體,進而被CPU計算執行。是以我們稱這種程序處理的方式為單任務處理。

  但是這樣的程序處理方式,使得計算機執行效率太低,如果有某個終端發起了一個很大的程序,可能會占用非常長的CPU處理時間,那麼這段時間其他的程式就隻能等待,甚至都無法發起執行,無法載入記憶體。是以就有人提出"多任務"的設想,即:可以在一台計算機,利用有限的計算機系統資源,同時處理多個任務。但是,這樣一來就必須要将有限的系統記憶體和CPU計算資源劃分給多個程序才可以,而且為了保證各個程序之間互相不踩踏,互不傾軋,互不影響,就必須要有一套完善的資源配置設定和監控的程式來完成這個任務,而且這個監控程式應該是一個通用程式,必須是具有相當的公信度的程式,而這個程式就是後來我們大家所說的作業系統。但是這個所謂的作業系統并不是現在大家印象中的作業系統的概念,這隻是一個狹義的作業系統,我們通常将其稱之為kernel(核心)。

  kernel這個監控程式隻是負責把底層的硬體驅動起來,并且把底層硬體所提供的各種資源虛拟化(如:把記憶體空間切割成N段,分給多個程式使用,進而也實作了記憶體資源的複用,我們稱為空間複用;再比如把CPU的工作時間分片,供多個程式輪流使用,基于時序完成複用,我們稱為時序複用。),以期能夠将資源配置設定給多個程序并監控這些程序是如何使用這些資源的。同時,如何啟動一個程式,如何關閉一個程式等工作也都是由監控程式完成的。他取得了整個硬體的控制權,并且把硬體的本來的接口的面目虛拟成了軟體的樣子。

  這些資源複用所帶來的結果就是:能夠把一套獨立的完整的硬體系統資源切分成N個部分。站在這個角度來講,我們可以認為每一個程式都獨立占有計算機資源(CPU的計算資源和記憶體的存儲資源),隻不過每個程式都隻是占有了整個計算機硬體系統完整資源的一部分罷了。

  而站在這個程序的角度來看,自己對資源的使用是通過那個監控程式來實作的,是以,該程序會認為自己是除了那個監控軟體之外的唯一的運作在這個硬體系統上的程序,他自己是唯一的占有了除了那個監控程式消耗的CPU和記憶體資源之外所有的硬體系統資源的程式。他無法了解還有其他程序存在這一事實。每個程式都是這樣在工作的。這是因為監控程式為每個程序虛拟出一個絕對私有的美好家園。

  kernel到底負責做什麼呢?現在我們可以做出這樣的總結了:

    第一、驅動底層硬體使得硬體可以被輕松通路;

    第二、将底層硬體資源抽象成簡單易用的資源,以友善程式調用;

    第三、管理各程序的運作,把有限的資源合理配置設定給程序并予以監控,讓其彼此之間相安無事。

什麼才是完整的作業系統?

  我們通常所說一個完整的作業系統由核心(Kernel)和各種應用程式(Applications)組成。核心運作在硬體系統之上,屏蔽了底層硬體複雜邏輯和醜陋接口,将其虛拟化為更加加單易用的接口,以友善程式調用,是以這些抽象出來的接口,我們稱之為"系統調用(System Call)"。是以程式員在開發應用程式的時候就必須要清楚的知道一個作業系統核心中包含了哪些調用接口,當編寫代碼的過程中需要用到那個系統調用的時候,直接在程式中調用即可。但是核心中的系統調用數量足有數百個,對于程式員來講,想完全了解所有的接口的功能以及調用方式也是異常辛苦的事情。于是,就有一些人将那些經常被調用的接口再次進行了封裝,我們将這些被封裝起來的接口稱之為"庫(Libraries)",而庫是更加接近程式的最終形态的一種接口。這樣一來,程式員在開發程式的時候,既可以選擇基于系統調用來編寫程式,也可以選擇基于庫調用來進行程式編寫程式,于這樣就為程式員們創造了更加自由,更加便利的開發環境。而現在在Linux開發領域,庫成為了一種标準接口,因為基于庫的程式開發速度更快,效率更高。這些庫也稱為API(Application Program Interface)。

  如果從程式員的開發視角來看,有一個程式員所開發的成員使用了Linux的API,那麼這個程式在Windows裡面是否可以運作呢?如果想要将一個在Linux開發的程式在Windows裡面運作起來,或者反之在Windows下開發的程式在Linux裡面運作起來,就需要将這些不同作業系統的API統一起來,也就是說在作業系統中提供可以互相相容的庫調用。網際網路中定義了一個規範,叫POSIX(Portable Operating System,可移植作業系統)。任何一個遵守POSIX規範的API而編寫的程式代碼,可以在不同的作業系統上通用。

  如果站在一個程式的運作視角來看,或者站在一個應用者的視角來講,庫是二進制檔案,核心是二進制檔案,程式是二進制檔案,他們都是可以運作的,但是庫一般是不能直接運作的,而是在被某個其他的二進制程式調用的時候才會運作。也就意味着,一個程式是否能夠運作,要看該程式所依賴調用的二進制庫二者是否相容,這樣一來,就又有了另外一個接口,即ABI(Applications Binary Interface),這個接口是應用者運作程式時面對的接口。

  程式設計接口相容并不意味着二進制接口相容,任何一個應用程式隻有轉碼成為二進制格式以後才可以使用的。這需要一個編譯器編譯。如果我們将程式在Windows上編譯,編譯器将轉碼為适用于Windows所支援的ABI的運作格式,是以放到Linux裡面是運作不了的;同理,在Linux可以編譯,而編譯成二進制以後,隻能相容Linux的ABI接口,而無法放到Windows裡面運作了。是以,在程式員接口上能相容,在運作接口上未必能相容,而且一般情況下也不可能相容的。

  這些就是作業系統的組成結構。

  接下來聊一下作業系統的功能,通常情況下,作業系統都會具備以下基本功能:

    1.驅動程式

    2.程序管理

    3.安全管理

    4.網絡功能

    5.記憶體管理

    6.檔案系統

  這麼多的功能沒有一個是幫使用者完成具體的任務的,是以,為了讓使用者能夠使用作業系統來實作其所需的功能,作業系統隻有核心是不夠的,在作業系統之上還應該有具體的應用程式,需要哪種功能就應該提供哪種功能的應用程式即可。在諸多的應用程式中,有一種特殊的應用程式——通路界面程式(也稱為通路接口程式)。

  通路界面程式大緻可以分為兩大類,即:

    GUI:Graphic User Interface,即圖形使用者界面

    CLI:Command Line Interface,即CLI

  就像我們常用的Windows,裝完之後有一個桌面,這個桌面就是Windows為使用者提供的GUI。在這個桌面上我們可以用滑鼠實作點選操作。亦或者像現在用的手機,操作接口就是觸摸屏,我們也可以認為這是一種GUI,這種GUI可以通過手指的觸摸、點選、劃動的方式實作操作。在觸摸屏出現之前,我們對計算機的操作往往隻有鍵盤和滑鼠。而如果不是GUI,滑鼠變得無用了,隻要有鍵盤就可以了。那麼是GUI的操作效率高還是CLI的操作效率高呢?我想凡是使用過CLI的人都應該清楚的知道一點:CLI效率要高得多。其實作在就連微軟公司也将GUI從Windows系統中剝離出來了,從2008開始,Windows也提供了一款CLI,那就是PowerShell了。為什麼有些人認為CLI操作比較慢呢?其主要原因就在于通常有這樣想法的人是沒有使用過CLI或者畏懼使用檔案界面,覺得CLI的操作太難,又是指令又是參數的,相反GUI的話,隻需要滑鼠點選即可完成大部分的操作。但事實是:在CLI下面一個指令即可完成的操作,在GUI下可能需要數次點選加各種目錄的切換才能完成,是以說,GUI比較容易上手,但是操作效率其實很低。要學會使用GUI,很短的時間就可以,三五分鐘;如果想深入使用,三五天就可以了。而CLI的入門曲線比較陡峭,對CLI來講,恐怕僅僅是學會使用,沒有三五十天恐怕是很困難的。但一旦入門,你就會發現,基于CLI的操作是相當的簡單,比那些把複雜邏輯隐藏在GUI背後的視窗系統要容易的多。使用起來幾乎是透明的,任何一個環節出現問題,都可以随時查找問題并能夠及時糾正這些問題。從這個角度來說,Linux是比Windows更簡單更易用的作業系統。如果說難度的話,Linux隻是入門比較難而已。

  不管是哪種類型的通路界面都是一種應用程式,包括GUI。對Linux而言,桌面僅僅是一款應用程式而已。沒有這個應用程式Linux依然可以運作的很好,有了這個應用程式反而可能運作的不好了,這個GUI使得Linux背負了一個重重的枷鎖,系統的資源不得不被GUI無情的占用,而且由于GUI程式存在不穩定性,使得GUI随時可能崩潰。

  通路界面反正就是一種應用程式,沒有什麼其他特殊的地方,是以對于Linux而言,可用的選擇就有很多。

    GUI:

    GNOME:使用C語言研發的,開發環境叫gtk。GNU

    KDE:使用C++語言研發的,開發環境叫qt

    XFCE:嵌入式環境中的輕量級圖形界面

    CLI:

    bash zsh csh sh tcsh ksh 

    此外,接口還包括telnet、ssh、共享桌面等各種類型的遠端連接配接通路界面

  那麼對于操作系來說,這些通路界面是否是必須的呢?如果對于Windows來講, 可以說這是必須的,但是對于Linux來講的話,倒也未必。我們在作業系統核心之上安裝這樣的操作界面程式,主要的目的是為了讓使用者可以友善的去使用存放于磁盤上的各類其他應用程式,如:遊戲,播放器等。那麼問題就來了,是不是其他的應用程式必須要通過這種方式才能啟動呢?

  答案顯然是否定的,在任何一款作業系統中,啟動應用程式的方式通常由兩種,即:手動啟動和自動運作。

繼續閱讀