本章知識點主要來自朱有鵬老師視頻課,部分自己添加總結
什么是內存?(硬件和邏輯兩個角度)
從硬件角度:內存實際上是電腦的一個配件(一般叫內存條)。根據不同的硬件實現原理還可以把內存分成SRAM和DRAM(DRAM又有好多代,譬如最早的SDRAM,后來的DDR1、DDR2·····、LPDDR)
從邏輯角度:內存是這樣一種東西,它可以隨機訪問(隨機訪問的意思是只要給一個地址,就可以訪問這個內存地址)、並且可以讀寫(邏輯上當然也可以限制其為只讀或者只寫);內存在編程中天然是用來存放變量的(就是因為有了內存,所以C語言才能定義變量,C語言中的一個變量實際就對應內存中的一個單元)。
計算機程序運行的目的是什么?
計算機為什么需要編程?編程已經編了很多年,已經寫了很多程序,為什么還需要另外寫程序?計算機有這個新的程序到底為了什么?
程序的目的是為了去運行,程序運行是為了得到一定的結果。
計算機就是用來計算的,所有的計算機程序其實都是在做計算。計算就是在計算數據。
所以計算機程序中很重要的部分就是數據。
計算機程序 = 代碼 + 數據 計算機程序運行完得到一個結果,就是說代碼 + 數據 (經過運行后) = 結果
從宏觀上來理解,代碼就是動作,就是加工數據的動作;數據就是數字,就是被代碼所加工的東西。
那么可以得出結論:程序運行的目的不外乎2個:結果、過程
用函數來類比:
int add(int a, int b) { return a + b; } // 這個函數的執行就是為了得到結果 void add(int a, int b) { int c; c = a + b; printf("c = %d.\n", c); } // 這個函數的執行重在過程(重在過程中的printf),返回值不需要 int add(int a, int b) { int c; c = a + b; printf("c = %d.\n", c); return c; } // 這個函數又重結果又重過程 |
計算機程序運行過程
計算機程序的運行過程,其實就是程序中很多個函數相繼運行的過程。程序是由很多個函數組成的,程序的本質就是函數,函數的本質是加工數據的動作。
什么是代碼?:函數
什么是數據?:全局變量、局部變量
總結:為什么需要內存呢?
內存是用來存儲可變數據的,數據在程序中表現為全局變量、局部變量等(在gcc中,其實常量也是存儲在內存中的,對於大部分單片機中,常量是存儲在flash中的,也就是在代碼段),對我們寫程序來說非常重要,對程序運行更是本質相關。
所以內存對程序來說幾乎是本質需求。越簡單的程序需要越少的內存,而越龐大越復雜的程序需要更多的內存。內存管理是我們寫程序時很重要的話題。我們以前學過的了解過的很多編程的關鍵其實都是為了內存,譬如說數據結構(數據結構是研究數據如何組織的,數據是放在內存中的)和算法(算法是為了用更優秀更有效的方法來加工數據,既然跟數據有關就離不開內存)。
深入思考:如何管理內存(無OS時,有OS時)
對於計算機來說,內存容量越大則性能越大,所以大家都希望自己的電腦內存更大。我們寫程序時如何管理內存就成了很大的問題。如果管理不善,可能會造成程序運行消耗過多的內存,這樣遲早內存都被你這個程序吃光了,當沒有內存可用時程序就會崩潰。所以內存對程序來說是一種資源,所以管理內存對程序來說是一個重要技術和話題。
先從操作系統角度講:
操作系統掌握所有的硬件內存,因為內存很大,所以操作系統把內存分成1個1個的頁面(其實就是一塊,一般是4KB),然后以頁面為單位來管理。頁面內用更細小的方式來以字節為單位管理。操作系統內存管理的原理非常麻煩、非常復雜、非常不人性化。那么對我們這些使用操作系統的人來說,其實不需要了解這些細節。操作系統給我們提供了內存管理的一些接口,我們只需要用API即可管理內存。
譬如在C語言中使用 malloc free 這些接口來管理內存。
當沒有操作系統時:
在沒有操作系統(其實就是裸機程序)中,程序需要直接操作內存,編程者需要自己計算內存的使用和安排。如果編程者不小心把內存用錯了,錯誤結果需要自己承擔。
再從語言角度來講:
不同的語言提供了不同的操作內存的接口。
- 譬如匯編:根本沒有任何內存管理,內存管理全靠程序員自己,匯編中操作內存時直接使用內存地址(譬如0xd0020010),非常麻煩;
- 譬如C語言:C語言中編譯器幫我們管理直接內存地址,我們都是通過編譯器提供的變量名等來訪問內存的,操作系統下如果需要大塊內存,可以通過API(malloc free)來訪問系統內存。裸機程序中需要大塊的內存需要自己來定義數組等來解決。
- 譬如C++語言:C++語言對內存的使用進一步封裝。我們可以用new來創建對象(其實就是為對象分配內存),然后使用完了用delete來刪除對象(其實就是釋放內存)。所以C++語言對內存的管理比C要高級一些,容易一些。但是C++中內存的管理還是靠程序員自己來做。如果程序員new了一個對象,但是用完了忘記delete就會造成這個對象占用的內存不能釋放,這就是內存泄漏。
- Java/C#等語言:這些語言不直接操作內存,而是通過虛擬機來操作內存。這樣虛擬機作為我們程序員的代理,來幫我們處理內存的釋放工作。如果我的程序申請了內存,使用完成后忘記釋放,則虛擬機會幫我釋放掉這些內存。聽起來似乎C# java等語言比C/C++有優勢,但是其實他這個虛擬機回收內存是需要付出一定代價的,所以說語言沒有好壞,只有適應不適應。當我們程序對性能非常在乎的時候(譬如操作系統內核)就會用C/C++語言;當我們對開發程序的速度非常在乎的時候,就會用Java/C#等語言。