假如我是一條內(nèi)存
我從無(wú)邊無(wú)盡的黑暗中慢慢醒來(lái),迷迷糊糊,茫然四顧。
耳邊傳來(lái)了風(fēng)扇賣(mài)力干活的嗡嗡聲,估計(jì)就是他把我吵醒的。 這時(shí)候 CPU阿甘 現(xiàn)身了:“兄弟,快醒醒,開(kāi)機(jī)了,要干活了,我要把程序和數(shù)據(jù)從硬盤(pán)讀取到你這里來(lái)了!”
“放到我這里干嘛?”
“唉,一斷電,你什么都忘了,不把程序讀入內(nèi)存,我怎么執(zhí)行啊?”
奧,對(duì)了,我是內(nèi)存啊,阿甘是我的好朋友,雖然說(shuō)程序都在硬盤(pán)上存著,但是阿甘被設(shè)計(jì)成只能運(yùn)行我內(nèi)存中的程序,所以程序必須要裝載進(jìn)來(lái)。
在這個(gè)系統(tǒng)里,阿甘最快,我第二, 硬盤(pán)則慢如蝸牛,他整天叫囂著說(shuō)要提高訪問(wèn)速度,到時(shí)候可以把我徹底替換掉, 但是這么多年過(guò)去了,還是沒(méi)有什么進(jìn)展。
不知道等了多長(zhǎng)時(shí)間,阿甘終于把一個(gè)叫做Linux的操作系統(tǒng)給裝載到我這里來(lái)了,阿甘說(shuō)從此以后它就是這里的老大。
可是我卻感覺(jué)不到老大的存在,我只知道我那一個(gè)個(gè)電容所代表的0和1 ,由于這些電容不能持久地保持電荷,我得定期地去刷新,如果不及時(shí)刷新,那些0和1的數(shù)據(jù)就會(huì)丟失,這將是極為嚴(yán)重的事故,主人就會(huì)把我從主板上拔掉,用另外一個(gè)家伙來(lái)替換我,決不允許這樣的事情發(fā)生!
次序問(wèn)題
但是程序員們卻不管什么電容,什么刷新,在他們的眼里,我就是一個(gè)個(gè)的空格子,每個(gè)格子對(duì)應(yīng)一個(gè)地址,就像門(mén)牌號(hào)一樣。
我最小的一個(gè)格子就是一個(gè)bit ,只能存儲(chǔ)0和1,這實(shí)在是太小了, 人們把8個(gè)bit 稱為一個(gè)字節(jié)(Byte), 就可以表達(dá)2的8次方種可能,從00000000 到 11111111, 如果是無(wú)符號(hào)數(shù)的話,就是0~255。
很明顯,Byte還是太小,人們又把更多的字節(jié)(比如4個(gè))組織起來(lái),叫做一個(gè)Word(字) 。
字節(jié)數(shù)目一多,就出現(xiàn)了很有意思的問(wèn)題,比如說(shuō)有個(gè)整數(shù),十六進(jìn)制的值是0x1234567, 一共是四個(gè)字節(jié),那該以什么次序存儲(chǔ)他們呢?
一種辦法是這樣:
還有一種方法是這樣:
可笑的是人類(lèi)為這兩種方式爭(zhēng)執(zhí)不休,有人堅(jiān)決支持大端法,有人則捍衛(wèi)第二種(即小端法),還有些和稀泥的家伙,大端小端都支持,就看你怎么選擇和配置了。
我問(wèn)CPU阿甘:“如果兩個(gè)機(jī)器的字節(jié)次序不同,他們兩個(gè)通信的時(shí)候,豈不天下大亂?”
阿甘嘆息一聲:“唉,他們?cè)谥贫═CP/IP的時(shí)候,確定了統(tǒng)一的網(wǎng)絡(luò)次序,使用大端法來(lái)傳輸數(shù)據(jù)。操作系統(tǒng)老大會(huì)提供特定的函數(shù)來(lái)實(shí)現(xiàn)網(wǎng)絡(luò)和主機(jī)之間字節(jié)次序的轉(zhuǎn)換,比如 htonl 函數(shù),就可以把32位整數(shù)由主機(jī)字節(jié)次序轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)次序, ntohl則恰恰相反。 ”
編譯器
剛才說(shuō)到,內(nèi)存中每個(gè)字節(jié)都有一個(gè)對(duì)應(yīng)的地址,只要能記住這個(gè)地址就可以把這個(gè)字節(jié)的值給取走,或者寫(xiě)入一個(gè)值。
比如說(shuō),剛才CPU阿甘執(zhí)行了一些列的指令, 它把地址0x100處的值取出來(lái),和 0x104處的值相加,放到0x110處, 然后再和0x108處的值相乘,結(jié)果放到0x10C處。
這一系列操作搞得我眼花繚亂,我對(duì)CPU阿甘說(shuō):“這程序員真是很厲害,居然能夠記住這么多地址!”
阿甘說(shuō):“怎么可能? 他們笨得很,根本記不住,全靠了編譯器的幫忙。”
“編譯器? ”
“是啊,編譯器允許程序員用變量的方式來(lái)表達(dá)程序,它可以把這些變量轉(zhuǎn)換成地址。沒(méi)有編譯器,程序員將會(huì)像熊貓一樣少。”
- total = base + bonus
- tax = total * rate
原來(lái)如此,我這里看到的都是二進(jìn)制的值,沒(méi)想到程序員都給他們起了一個(gè)名字。
信息 = 位 + 上下文
有一次, 阿甘問(wèn)我地址0x300的值是多少,我看了一眼,告訴他說(shuō)是一個(gè)32位整數(shù)1735159650。
阿甘大驚失色:“兄弟,你睡了一覺(jué)什么忘了嗎, 你不能擅自去解釋你內(nèi)存數(shù)據(jù)的類(lèi)型啊!”
“為什么? 這就是個(gè)整數(shù)嘛!”
“你這里的值實(shí)際上是0x 676C 6F62,他有可能是32位整數(shù)1735159650,也有可能是浮點(diǎn)數(shù) 1.116533*10^24,還有可能是機(jī)器指令呢!!記住!解釋權(quán)不在你,而在人家應(yīng)用程序那里,你就管好你電容里的'二進(jìn)制'就行!”
我覺(jué)得很羞愧,這么重要的準(zhǔn)則都給忘記了!
信息=位+上下文, 我這里只負(fù)責(zé)一串串的二進(jìn)制位,至于這些位的信息是什么,得加上下文才能理解了。
指針
過(guò)了一會(huì)兒,阿甘問(wèn)我0x108處存了什么內(nèi)容, 這一次我不再“解釋”了,我告訴他是0x100。
奇怪的是他接下來(lái)又問(wèn)我0x100處的值是什么, 我告訴他說(shuō)是0x12C, 他這才滿意地離開(kāi)。
我拉著他問(wèn)道:“你這次怎么了,這么麻煩?還得讀兩次才行?”
他說(shuō):“沒(méi)辦法,程序員用指針了!”
- int i = 300;
- int *p = &i
- total = *p + 200;
“看到?jīng)]有,這個(gè)變量p就表示指針。”
我嚇了一跳:“難道我的格子里保存的不僅僅是值,而是地址?”
“是啊,這就再次證明,你不要胡亂解釋你保存的值。 我告訴你,有時(shí)候還會(huì)出現(xiàn)二級(jí)指針呢。”
- int i = 300;
- int *p = &i ;
- int **pp = &p;
這真是顛覆了我的認(rèn)知,我還是刷新我的電容去吧!
不過(guò),在億萬(wàn)次的讀寫(xiě)操作中,我通過(guò)這些指針的關(guān)系,也發(fā)現(xiàn)了一些獨(dú)特的模式,比如說(shuō)我發(fā)現(xiàn)這樣的東西很常見(jiàn):
我問(wèn)阿甘:“這是在干嘛? ”
“這就是程序員實(shí)現(xiàn)的鏈表啊。”
“ 那這個(gè)東西呢?”
阿甘說(shuō):“這不就是一顆二叉樹(shù)嘛! 程序員管這些東西叫做數(shù)據(jù)結(jié)構(gòu)。”
我原來(lái)以為,我就是一個(gè)大數(shù)組而已,沒(méi)想到通過(guò)指針,可以表達(dá)各種各樣的復(fù)雜的數(shù)據(jù)結(jié)構(gòu)的,只要你能沿著指針來(lái)回跳轉(zhuǎn)就行。
但是我心里隱隱覺(jué)得不妥,這指針實(shí)在是太強(qiáng)大了,程序員可以把它指向任何地方,我知道有些地方是操作系統(tǒng)老大的獨(dú)有區(qū)域,是嚴(yán)禁外界進(jìn)入的,萬(wàn)一指針指到這里會(huì)發(fā)生什么事?
阿甘說(shuō):“這不用你操心,如果有個(gè)程序通過(guò)指針想訪問(wèn)它根本沒(méi)有權(quán)限的區(qū)域,老大就會(huì)引發(fā)一個(gè)segment fault,把這個(gè)程序殺死!”
“殺死以后呢?”
“那個(gè)程序的內(nèi)存空間就會(huì)被釋放, 與此同時(shí)老大會(huì)生成一個(gè)叫做core dump的文件,讓程序員們?nèi)シ治觥?唉,今天你真是煩人,問(wèn)了這么多問(wèn)題。 不說(shuō)了,主人要關(guān)機(jī)了,明天再見(jiàn)!”
風(fēng)扇停轉(zhuǎn),電流消失,整個(gè)世界安靜了。
第二天
我從無(wú)邊無(wú)盡的黑暗中慢慢醒來(lái),迷迷糊糊,茫然四顧。
耳邊傳來(lái)了風(fēng)扇賣(mài)力干活的嗡嗡聲,估計(jì)就是他把我吵醒的。 這時(shí)候CPU阿甘現(xiàn)身了:“兄弟,快醒醒,開(kāi)機(jī)了,要干活了,我要把程序和數(shù)據(jù)從硬盤(pán)讀取到你這里來(lái)了!”
.....
【本文為51CTO專(zhuān)欄作者“劉欣”的原創(chuàng)稿件,轉(zhuǎn)載請(qǐng)通過(guò)作者微信公眾號(hào)coderising獲取授權(quán)】