首頁 > 軟體

Linux學習:計算機和作業系統的基礎知識

2020-06-16 17:30:13

  在正式開始學習 Linux 作業系統之前,有必要先回顧/學習一下計算機和作業系統的基本知識,為我們在後續的學習中鋪路搭橋,在了解計算機一些基礎原理的條件下再去進行學習,理解應該會更透徹一些。我會從一個程式的簡單構成開始,逐步介紹我對計算機工作原理的一些理解,希望能夠給大家做一個參考。由於中間涉及的知識很多,有些內容我沒有進行深究,存在許多漏洞,因此僅供參考。

  1.程式的構成

  程式是由什麼構成的?簡單說來,這裡有一個公式:程式 = 資料 + 指令。這是程式設計師再熟悉不過的了,資料自不用多說,指令就是告訴程式,怎樣操作目標資料,這個“操作”不僅僅是在資料之間進行簡單的運算,而是包含了操作這些資料的一系列行為的集合,比如做兩個數位的加法運算,除了本身的加法這一指令之外,我們還需告訴CPU從哪裡讀取目標資料,以及完成加法操作後將資料放到何處等。

  計算機的底層是二進位制資料,因此不管是指令還是資料,最終都會以二進位制的形式儲存。對於CPU,怎麼區分我們傳入的二進位制程式碼是資料還是指令呢?這就需要不同的線路將資料和指令進行分離。

  • 控制(指令)匯流排:用來向CPU傳輸指令
  • 資料匯流排:用來向CPU傳輸資料

  2.CPU的簡單理解

  一個CPU的核心部件包括三個:運算器,控制器和暫存器。

  運算器是執行運算操作的地方,它會接收資料的輸入,在內部計算完成之後將資料輸出。

  光有運算器還是不夠的,由於我們的指令和資料都是儲存在記憶體中,運算器需要知道在記憶體的哪個地方讀取資料,哪個地方讀取指令,以及在計算完成之後將資料放到哪裡等。這些資訊就是由控制器提供的。

  暫存器是做什麼的?暫存器也叫暫存器,顧名思義,就是暫時儲存資料的地方。暫存器位於CPU的內部,用以儲存等待處理或者處理過的資料。為什麼需要暫存器?比如我們做一個四則運算,每次運算之後的結果應該儲存在哪裡?記憶體嗎?如果將每步運算結果儲存在記憶體中,無疑是加大了CPU的開銷,因為要在每步計算完成之後將其放入記憶體中,然後再讀取出來,再輸入到運算器進行計算……這很麻煩,開銷很大,並且浪費了CPU寶貴的效能。暫存器的作用就是將資料暫時存放在CPU的內部,那麼CPU在存取這些資料的時候,效率將會得到極大的提高(就近原則)。

  3.中斷機制(Interrupt)

  計算機有很多I/O裝置,比如鍵盤,滑鼠,,光碟機,磁碟,硬碟等。如果我們敲擊了鍵盤,CPU怎麼知道我們操作的是鍵盤而不是滑鼠或者光碟機呢?我們可以將敲擊鍵盤這個行為當做一個事件,這個事件是偶發的,CPU如果想偵測到這個事件,有兩個方式可以選擇:

  • 輪詢機制(Poll):CPU比較勤快,每隔一段時間就去看看,有沒有發生這個事件,如果發生了,就執行某個操作,如果沒有發生時間,則不做任何處理。
  • 中斷機制(Interrupt):CPU比較懶,並不想總是去檢視這些事件有沒有發生,而是找另一個人幫忙看著,如果發生了事件,就通知CPU,CPU再去做相應處理。

  和CPU一樣,我們都非常勤(lan)快(duo),喜歡輕鬆又有保障的活。對於輪詢機制,有一個問題:事件是有隨機性的,有可能CPU輪詢了一天,使用者並沒有做出任何操作,那不是虧大發了嗎。所以我們肯定會選擇中斷機制啦,事實上CPU採用的也正是中斷機制。

  4.中斷控制器

  上面說了CPU的中斷機制。那麼問題來了,CPU又怎麼知道是滑鼠還是鍵盤上產生了事件?

  這時候中斷控制器就登場了。中斷控制器和CPU的針腳相連,如果把中斷控制器比做蜘蛛,它將通過周圍遍布的蛛網和計算機上的I/O裝置連線,如果某個I/O裝置上產生了一個事件,就會發生電信號的變化,這個變化通過蛛網傳給中斷控制器,控制器也就知道是哪一個裝置發生了響應,進而將訊息傳遞給CPU。

  5.南橋和北橋

  對於計算機中的資料處理,有高速低速之分,或者高頻和低頻之分。南橋和北橋就是分別用來傳輸這兩種型別的資料,北橋在物理上距離CPU較進,用來處理高速高頻的資料。大多數的I/O裝置都在南橋上,這些裝置經過南橋匯總後,通過線路連線傳到北橋,再由北橋傳給CPU。

   舉例:一個網頁同時給一百萬個使用者存取,網頁檔案存放在伺服器的硬碟中,伺服器的每次響應都需要從硬碟中讀取這個網頁,由於硬碟連線在南橋,讀取速度和頻率較慢,這會產生嚴重的伺服器延遲(比如一個硬碟最高一次只能進行10萬次的資料輸出,那麼剩下的九十萬使用者就得等著),這是非常搞糟的體驗。因此,現在的伺服器很多都採用了固態硬碟,並將硬碟直接連線在北橋上,以獲取更高的讀取效能。

  6.主頻和快取

   主頻可以理解為CPU的計算能力,主頻越大,CPU在單位時間的計算能力越強。CPU的頻率可以達到1GHZ,而記憶體的讀取速度遠遠低於CPU的頻率。給予木桶原理,即使CPU的速度再高,記憶體的讀取效率跟不上,計算機的整體效能也難以提高。為此我們可以造更快的記憶體,但是這種方式造價極高。於是出現了快取技術,快取技術是在速度和造價之間的擇中原則。

  速度越快的部件,造價越高。因此最快的核心部分,我們只要一小塊,然後在其外圍放效能稍低(相對於核心)造價也稍低的裝置,這就是快取。CPU有一級快取,二級快取...快取在CPU和記憶體之間起到了承上啟下的作用。

  快取的工作,需要遵循程式的區域性性原理,程式的區域性性原理分為時間區域性性和空間區域性性。

  • 時間區域性性:剛剛存取的資料可能還會被存取,那麼將該資料需要被快取。
  • 空間區域性性:如果存取一個資料,那麼離這個資料非常近的資料,也應該存取的比較快。因此在存取一個資料的時候,把其周圍的資料也一併載入進來,這樣就提高了其周圍資料的存取速度。

  程式的區域性性原理,不僅應用在CPU的工作上,也用在碼農的編碼過程中,運用時間區域性性和空間區域性性,可以顯著提高程式的執行效率。

  舉例:

  • Javascript中存取內層變數比存取全域性變數快得多,因此我們在編碼的過程中盡量少的依賴全域性變數,可以提高執行的效率。(克制使用全域性變數的好處不僅這一處,這裡簡單的舉例說明)。
  • for迴圈中快取變數,運算元據庫的時候快取欄位等。

  7.機器碼,組合,高階語言

  我們知道所有程式必須要編譯機器碼(二進位制)才能被計算機識別和執行,我們也知道組合是對機器碼的抽象,讓我們不用直面枯燥難懂的機器碼,而使用易於人類的語言進行程式設計。組合語言也叫作微碼,是CPU廠商為我們暴露出來,通過微碼我們可以進行針對CPU的程式設計。需要注意的是,不同的CPU架構不同,對於同一操作,其暴露出的微碼也不盡相同。因此針對不同的CPU,我們需要分別對他們進行程式設計。儘管有些許蛋疼,但總比使用機器碼程式設計好太多了。

  高階語言是對組合語言更高的抽象,結合一些額外的機制,來彌合CPU之間的不同。然後暴露出公共的API程式設計師呼叫,儘管對於這份API,其在不同的平台下可能會進行不同的實現,但是對於程式設計師,我們只需呼叫這個API,就可以實現平台的相容,而我們自己再也不用考慮硬體的差異性了。

  8.CPU的架構

  下面是一些常見的架構: 

  • ARM:手持硬體裝置(安卓,IOS)
  • x86:32位元平台
  • x64:64位元,來自AMD
  • 安騰:來自惠普,Intel收購
  • Alpha:惠普
  • UltraSparc:SUN公司
  • Power:IBM
  • M68000:摩托羅拉(M68K)
  • PowerPC :IBM

  9.CPU怎麼執行一個程式

  單核的CPU,在某個時刻只能進行一次運算,為什麼我們的程式看上去是並行執行呢?

  這裡需要引入切割機制,切割機制可以分為CPU切割和記憶體切割。

  CPU切割:把CPU按照時間片(Slice)切割。比如一個Slice是5ms,那麼每個程式只能執行5ms,下一個5ms就該換一個程式執行了(當然也可能仍然執行這個程式,具體取決於CPU的分配機制)。同時,CPU還應該有一個機制來記錄程式的執行狀態,以便程式在下一次執行的時候可以從先前的狀態繼續執行。

  記憶體切割:引入分段機制,想象兩個程式同時執行,而且都從記憶體的某一個編號開始佔用(比如0x00000),那麼後面的程式就會破壞掉前面程式的資料。現在引入了記憶體分段的機制,將記憶體分為一塊塊的區域,這些區域內部都從0x00000開始,那麼程式就不會相互干擾了。

  10.作業系統

  上例中,怎麼保證每個程式在每個時間片中程式都是嚴格執行呢?如果程式賴著不走怎麼辦?

  這就需要引入作業系統了,作業系統就是用來對程式進行排程,以及協調其他程式進行工作,是位於硬體和應用軟體之間的中間層。有了作業系統,任何程式都不能直接和硬體打交道,而是要經過作業系統這一中間層進行處理。

  同一份程式,在不同的作業系統執行的效果不同的解釋:程式要執行某一個功能,將請求交給作業系統,作業系統通過呼叫相關的庫來執行,不同的作業系統實現實現某種庫的方式可能不一樣,那麼程式的效果也就不一樣了。

  11.Shell

  以Windows為例,為什麼雙擊桌面上的圖示就可以執行相應的程式,或則在命令列中輸入calc就可以開啟計算器呢?

  上面的兩種操作:雙擊圖示和在命令列輸入命令迴車,本質上都是指令。我們的指令需要作業系統傳到核心(kernel)中,然後實現程式的執行。接收指令的這個東東,就是人機互動介面(Shell)。Shell包括兩種:

  • GUI圖形Shell
  • CLI命令列Shell

  不管是GUI還是CLI,目的都是向核心傳送指令,實現某項操作,對於核心來說,通過什麼方式傳送指令並不重要。

  作業系統核心的功能包括: 

  • 進程管理(協調)
  • 記憶體管理
  • 檔案系統
  • 網路功能
  • 硬體驅動
  • 安全機制等

  12.Linux發行版

  終於講到Linux了,照例在此之前應該講講Linux的起源,Unix,Bell實驗室,Apple和Windows等等,但是歷史性的東西並不是這篇博文的重點,這裡就暫且跳過。

  Linux是作業系統,也就是軟體,軟體要想執行,就需要編譯成相應的二進位制程式碼才能執行。

  上面我們也談到過,不同的CPU架構,完成某項操作的實現方式可能不同,因此在編譯作業系統的時候不應該出現交叉編譯的情況(比如在AMD上編譯在Intel上執行)。

  也就是說,想要在某個平台上使用作業系統,需要針對這個平台進行編譯。這無疑增加了學習和使用的難度,作為初學者而言,這是噩夢。於是出現了一些組織,他們來對Linux的原始碼和外圍的一些軟體進行編譯整合,然後發行出來,這就是Linux的發行版。這樣的公司或組織有RedHat,Debian等

  13.軟體包管理器

  早期的軟體都是隨著核心一起打包發布的,這樣有個明顯的缺點:不利於軟體的管理,如軟體的安裝,解除安裝等。於是出現了軟體包管理器,用來方便軟體的管理,安裝,解除安裝等。比較著名的有dpt(debian),rpm(redhat)等。

  14.Linux的基本原則

  • 組裝:組合功能目的單一的小程式,完成複雜的任務
  • 一切皆檔案
  • 儘量避免捕獲使用者介面(互動),比如輸入ls,馬上列出目錄下的檔案,不需要其他操作。
  • 組態檔儲存為純文字格式——一個簡單的文字編輯器就可以完成所有的功能。

  15.命令的構成

  基本格式為:命令 = 命題主體 + 選項 + 引數。

  命令執行:輸入命令後,由shell將指令傳送給kernel,kernel即對該指令進行判斷,決定是否執行。

  命令可以跟上選項,用來修正命令的執行方式。格式為:

  • 短選項:-單一字元,如 -a,-l,-h
  • 長選項:--單詞,如 --help

  短選項多個選項可以組合:-a -h 可以組合成 -ah。長選項通常不能組合。

  命令的引數:命令的表示命令的作用物件。如:ls -ah /etc 為列出 /etc 目錄下的檔案,如果不加引數,預設為當前目錄。

  16.一些瑣碎知識

  Linux(我這裡使用的是RedHat)下一般有6個終端可以使用,可以按鍵盤組合鍵 ctrl + alt + f1~f6切換。

  $ startx & -> 啟用圖形介面。

  Linux圖形介面的型別:Gnome(C),KDE(C++),XFace(輕量級圖形介面)。

  Linux命令列介面型別:bash csh zsh ksh....

  任何跟shell相關的啟動的程式,只要shell關了,這個程式也就關了(這不廢話嗎)。

  su:切換使用者(switch user 縮寫)。

  su root [-l] :半切換,完全切換。

  passwd:修改密碼,連輸兩次即可。

  對於root,可以隨便修改,對於普通使用者,需要滿足密碼複雜性規則。

   17.總結

  這篇文章主要介紹了CPU和作業系統的簡單工作原理,涉及到的概念有:運算器,控制器,暫存器,匯流排,南北橋,作業系統,shell等。算是對基礎知識的一些總結,由於沒有深刻學習,文章中有很多漏洞,更有許多模糊的知識沒有加以說明。文章組織不夠嚴謹,只是單純的將知識點分條羅列,邏輯性有待加強。

  就以這篇文章開始,一步步開啟Linux的大門吧。

本文永久更新連結地址http://www.linuxidc.com/Linux/2016-10/136083.htm


IT145.com E-mail:sddin#qq.com