計算機是怎么跑起來的?


01

在學習工作中,經常會遇到些讓我腦子短路無法回血的問題?

  • 你去評估下這項目需要幾台機器能維持穩定性,CPU要幾核,內存要多大?
  • X模塊偶發出現內存飆升的情況,你追查下原因順便想想如何優化?

瞬間,鴉雀無聲甚至氣氛一度及其尷尬。作為一個CURD男孩,寫代碼就是一把梭復制粘貼,那能管那么寬?仔細一想,我也是學過計算機組成原理、操作系統原理的男孩,豈能說慫就慫?

這時,馮·諾依曼、寄存器、內存、二進制、補碼這些詞忽隱忽現的飄過,就像一堆雜亂無章的思緒擠地鐵一樣擠入我的腦海。然而,我發現這跟上面的問題並沒有絲毫聯系,放佛我有一把方天畫戟卻切不動一盤菜的感覺,並沒有什么用。

我相信,大多數同學在熟練編寫業務代碼后,會在出現一些復雜問題后被委以重任,這就非常考驗大家的基本功了。

於是,我趁疫情在家時間充裕,花了一些時間閱讀書籍和思考,嘗試再去總結下計算機的基礎知識。

02

首先,我先從計算機的三大原則開始說起。

1. 是什么?計算機是執行輸入、運算、輸出的機器

計算機通路.png

計算機本質上就是一台機器,機器的工作模式:接收指令(輸入)、理解指令(運算)、做出動作(輸出)。工作模式很簡單,關鍵是計算機如何理解指令的呢?

舉個例子:在一個陽光明媚的早上,你對你對象說:不去上班行不行?你對象嬌滴滴的回答:不去上班你養我啊?

針對這橋段,你仔細想想你對象腦子里是怎么流轉的?

  • 輸入:聲音(漢語)
  • 理解:
    • 接收聲信號
    • 分析聲信號是鳥語、英語、日語還是漢語?
    • 從腦庫存(內存)中抽取積累的信息(學習所得),自我翻譯理解
  • 輸出:表情(嬌滴滴) + 聲音(漢語)

其實,計算機也有三大基礎元件。

  • CPU(處理器):負責解釋、執行程序。
  • 內存:負責存儲程序和數據。
  • I/O(Input/Output):負責將計算機和外部設備(周邊設備)連接在一起。

簡單說,I/O就相當於五官跟大自然連接的器官,內存就相當於你的腦庫存(腦知識庫),CPU就相當於你的腦神經中樞。

2. 怎么交流?計算機只能理解數字

不同人種,不同的生物,有不同的語言。機器也不例外,它也有獨特的語言,你只有跟它說數字才能理解。

你可能質疑道:放屁,我明明在我的瀏覽器用搜索引擎搜索關鍵字「靚仔」,它給我輸出「博主照片」,它明明可理解中文。

其實,這功勞就要歸功於程序,程序充當了中間翻譯官。比如,我們人類本身是無法識別語言的,有些人上知天文下知地理,而有些人卻只會牛逼和卧槽。這一切,取決於我們的腦庫存的知識,這些知識會把外界的信息進行翻譯讓大腦能夠理解。

於是,計算機中的內存是程序的載體,計算機只能理解數字,那么程序就必須被翻譯成數字才能在計算機中運行。 程序要想運行起來,它將經歷:程序 -> 編譯(翻譯)-> 機器語言。

這時候,你可能會想:程序到底是什么東西,能解釋清楚嗎?

3. 程序是什么?指令和數據的集合

程序就像是我們腦庫存中的知識庫一樣,數據相當於人的記憶,指令相當於人的邏輯。

舉個例子:

例子1: 1 + 1 = 2
1是數據,+運算是指令

例子2:
int i = 1; // 數據
int j = 0; // 數據

// 指令:順序、條件、循環
if (i > 0) {
    j = i + i;
} else {
    j = i - i;
}

03

通過敘述,大概解釋清楚了計算機的硬核元件是CPU、內存、I/O,程序的硬核內容是數據、指令,程序存儲在內存中供CPU讀取執行運算。

那么,我們用Java、C還是Php寫程序,到底在寫什么?

本質上,寫程序就是在輸入初始值(申請內存),執行運算(順序、條件、循環),輸出預期值(寫入內存)。

流程圖.jpg

但是,我們知道內存是連續的,順序執行是順理成章的被計算機理解,條件/循環執行呢?於是,就出現跳轉指令,用於跳轉到指定的程序塊。
內存跳轉圖.jpg

基於內存約束,數據也就是連續存儲在內存中。但是,人類對世界的需求是千奇百怪的,更不是純線性結構的。同時,我們又無法去改變內存的結構。

於是,出現了很多的數據結構。

  • 線性:鏈表、堆、棧
  • 樹狀:二叉樹
  • 圖狀:鄰接矩陣、鄰接表、逆鄰接表、十字鏈表

那么,這些數據結構有什么用?本質上來說,是為了適應各種運算方式從而找到最優解也就是算法,我認為「數據結構」是為「算法」服務的,這樣才能更好的運轉。

簡單說,程序就是「數據 + 指令」線性存儲在內存中供CPU調遣,CPU運算就是在執行順序、條件、循環的運算邏輯。為了滿足現實世界的訴求,人類為了更好讓機器服務,於是研究出了各種各樣的運算法則(算法),算法需要特殊的存儲結構(數據結構),這樣在現實世界與機器就友好相處了。

04

我們常聽資深程序員說:不要去爭執學什么語言了,學透一門語言,學習其他語言是很容易的?

通過上面分析,你仔細想想學習編程語言的過程?

  • 第一課:數據類型(int、long、char、指針、bool)
  • 第二課:運算符(+-*/)、控制流程(順序、條件、循環)
  • 第三課:數組、結構體、類
  • 第四課:集合
  • 第五課:文件、網絡(I/O)
  • 第六課:並發編程(CPU)
  • 第七課:內存管理(內存)

其實,學習一門編程語言的邏輯是非常簡單的,你想你按這個邏輯去學習一門新編程語言也可以輕松上手,主要關注不同語言的差異。

  1. 學習程序基礎結構「數據 + 指令」。於是,先學習數據類型,運算方式、控制流程、數組、結構體、類。
  2. 為了簡化我們的使用成本,於是必然會有很多可復用的集合「數據結構 + 算法」,list、map、set一定會與你相遇,只不過是穿什么大褲衩罷了。
  3. 網絡編程、文件處理,就是計算機跟外界接觸的器官,輸入/輸出罷了。
  4. CPU是執行運算的大腦,為了更好的榨干CPU,那就必然會並發編程,至於怎么並就取決於計算機有幾核。
  5. 內存管理就像倉庫管理,你要有進有出。那么,內存你申請了不釋放,必然會出現飆升直到倉庫飽滿掛掉。不同的是,內存管理是一項基本工作也是很復雜的事情,不同語言可能會推出自動回收內存的機制,也有像C++這種需手動回收的機制。

這樣,我們理清楚了計算機硬件跟我們寫的程序在宏觀上的一個關系。於是,我們回到最初的問題。

問題1: 你去評估下這項目需要幾台機器能維持穩定性,CPU要幾核,內存要多大?

根據監控峰值QPS,根據不同QPS狀況統計CPU和內存的占用情況,根據實際情況給個折中值就好。

問題2: X模塊偶發出現內存飆升的情況,你追查下原因順便想想如何優化?

這就是個內存管理問題,主要去review內存申請和銷毀的程序邏輯,重點看是否有申請不釋放的邏輯,輔之以工具,那就有解決辦法了。

總而言之,有時候並不是碰到的問題的有多難,而是如何去思考定位關鍵問題,輔之以工具,不斷實驗和調試,最終從根本上解決問題。而不是,胡子眉毛一把抓,或怒氣沖冠大喊尼瑪狗逼,或驚慌失措叨叨涼了涼了。相信自己,腦子在思考,我們就能贏。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM