宕機與記憶體的關係

  從電腦出現至今就一直被宕機伴隨著,幾乎沒有誰的電腦從不遭遇宕機。在使用過程中,偶爾一次宕機應該算是正常現象,如果經常宕機,電腦就存在一定的問題了。那麼,電腦為什麼會宕機呢?有哪些因素會造成電腦宕機呢?要搞清楚這些問題,首先要弄清楚,到底什麼是宕機?為什麼會發生宕機?

  造成宕機的原因是多種多樣的,有軟體問題,有硬體問題,不過,宕機的本質都是一樣的。

  早在N年前,我主持某大學計算機專業本科生畢業答辯的時候,就向某學生提出過這樣兩個問題:

  1.電腦宕機的時候,CPU在幹什麼***或者說,CPU處於什麼狀態?***”

  2.在計算機中,無論指令程式碼還是資料程式碼,都是用二進位制來表示的,請問,CPU是如何判定某二進位制程式碼是指令程式碼還是資料程式碼?

  其實,上面兩個問題的實質是一樣的,主要涉及到CPU是如何取得指令和如何執行指令的,把這兩個問題搞清楚了,宕機的問題也就容易理解了。

  首先來看看,馮.諾依曼結構的電腦是如何取得指令、又是如何執行指令的:

  馮.諾依曼***1903~1957***,匈牙利裔數學家,1945年戈德斯坦、勃克斯等人,聯名發表了一篇長達101頁紙的報告,即計算機史上著名的“101頁報告”,提出了現代計算機結構的理論模型--儲存程式計算機模型***Stored Program Computer***,這就是今天計算機最基本的原理模型。

  這種結構型別計算機工作的時候,首先必須把完成工作步驟和相關的資料用二進位制程式碼表示出來***編寫程式***,然後再把它們儲存在計算機的記憶體中,CPU依次從記憶體中讀相關的指令程式碼和資料進行運算,直到完成整個運算過程並輸出結果。

  要完成這樣的運算過程,人們在設計運算器***CPU***的時候,首先就要考慮的是,在一段記憶體中,CPU怎樣區分指令程式碼和資料程式碼。熟悉計算機的人都清楚,指令用來確定“做什麼”和“怎樣做”,資料是“做”的時候需要原始數。

  比如:要計算機做1 2=?中,“ ”表示要做什麼和怎樣做,1和2則是做的時候需要的原始數。現在假設某CPU中,“ ”用二進位制“00000001”來表示,“1、2”分別用“00000001、00000010”來表示。那麼,這段程式存入記憶體中就是這樣的:

  

  

   前面的XXXX1 XXXX2 XXXX3表示記憶體的地址

  從上面可以看出,“ ”指令和被加數是完全相同的,當然,這是我故意這樣假設的,但是,在實際情況中,這種情況是大量存在的。在正常情況下,CPU只能把XXXX1記憶體中的00000001作為指令,XXXX2記憶體中的00000001作為被加數才能得到正確的結果。那麼CPU如何才能做到不把第二個00000001也當成“ ”呢?

  1.人們把記憶體的某個地址規定為起始地址***又稱為復位地址***,也就是說,當計算機開機或者被強行復位***也就是機箱上那個重啟動按鈕按下的的時候***,CPU立即跳轉到這個地址中,並且把它裡面的程式碼作為指令來執行,同時根據這個指令的長度和格式判斷下一條指令在什麼地方。

  對於X86系列CPU***也就是現在人們常用的什麼奔XX、賽XX系列***,它的復位地址是FFFF0,如果表示成邏輯地址則是:

  用DEBUG執行一條指令***這是一條無條件跳轉指令***:jmp

  2.給各種指令規定了相應的長度和格式。比如:某數 某數這條指令就規定:這條指令的長度是3個位元組,其中第一個位元組表示“ ”,後面兩個位元組表示被加數和加數。於是,當CPU到達這個指令後,就自動把第一個程式碼作為指令,後面兩個程式碼作為資料,依次類推,第4個程式碼就必然是指令.....

  現在假設,CPU在執行指令的時候因某種原因,誤把本來是資料的程式碼當成了指令,結果除了是計算結果出錯外宕機也就是必然的了。

  還是以前面那個加法程式為例:當CPU把第三個程式碼***也就是00000010***當成了指令,而恰好這個程式碼是一跳轉指令,CPU的執行結果將是:XXXX3--跳轉--執行--跳轉--執行........進入周而復始的亂條,不過注意,雖然是在亂跳,CPU卻始終是在不停的正常地執行指令,所謂的“亂”是對使用者而言,對CPU來說卻是正常的。

  還有一種情況就是,如果恰好跳轉到了

  有朋友可能會問,記憶體中怎麼可能有如此多的跳轉指令呢?是怎麼形成的呢?

  計算機中的最小儲存單位是位元組***8個二進位制位***,指令功能、長度和格式也是在一個位元組中規定的。因此,平均來說,每256個程式碼中就有可能出現一條跳轉指令***8位二進位制數最多表示256***。

  還有一種情況:現在計算機的記憶體已經達到數G的儲存容量,絕大多數都不可能用到這個極限,也就是說,有相當長一段區域是空白,即使記憶體只有數百M的計算機中也不可能把記憶體用完,同樣存在相當數量的空白區域。特別需要注意的是,空白區域不等於裡面就沒有程式碼。因為,在數字邏輯電路中,不可能存在“沒有”這種情況,即使是表示沒有***叫做“空”--NULL***也是要用一個程式碼來表示的***NULL用00000000***來表示,所以,空白區域內的程式碼是“11111111”或者乾脆就是一些隨機程式碼。X86系列的CPU“11111111”是一條單位元組的指令nop--空操作指令,當CPU跳轉到這些空白區域時,雖然不會發生再次跳轉的現象,CPU也會逐條執行這些程式碼,執行到最後一個記憶體後,CPU將會回到記憶體的0號起始地方然後又從頭開始執行程式。

  有朋友問了,如果硬碟出錯會不會宕機呢?這個問題要這樣看。CPU從硬碟中調入資料的時候會對硬碟資料做比較嚴格的校驗***一般是CRC--迴圈冗餘校驗***,如果校驗成功,則不會宕機,如果校驗失敗,CPU會給予使用者提示“校驗失敗或者檔案損壞”--當然也不會宕機;只有在硬碟上的檔案已經損壞,硬碟把資料傳給CPU的時候“自己沒有發現”造成的資料混亂。所以,硬碟資料損壞後,只能造成資料丟失,無法執行程式,也可能無法啟動計算機。不過,有一種情況例外,那就是硬碟上的某區域做成的虛擬記憶體,如果這個區域損壞是有可能宕機。

  記憶體的啟動監測問題,計算機在開機的時候會對記憶體進行檢測,這種檢測的方法不外乎有如下一些:

  1.最簡單的檢測方法:把記憶體從頭到尾讀一遍,能夠讀出資料便認為記憶體正確。

  2.稍微複雜一些的檢測方法:把記憶體從頭到尾讀、寫一遍,能夠讀寫資料便認為記憶體正確。

  3.再複雜一些的檢測方法:把記憶體從頭到尾讀、寫數遍能夠讀寫資料便認為記憶體正確。

  4.簡單的校驗檢測方法:把記憶體從頭到尾讀、寫數遍,讀出的資料和寫入的資料進行比較,能夠讀寫、並且讀的資料和寫的資料相同,則認為記憶體正確

  5.比較複雜的校驗檢測方法:對記憶體讀寫的資料同時進行奇偶校驗和CRC校驗,這種方法多用於高檔伺服器,同時,能夠做奇偶校驗的記憶體***ECC記憶體***價格比普通記憶體貴10倍以上***不知道為什麼***。