http://c.biancheng.net/cpp/html/2871.html
2015
首先我們需要知道的是,當(dāng)我們?cè)谑褂脴?biāo)準(zhǔn)庫(kù)的函數(shù)去讀寫(xiě)文件時(shí),我們所操作的地址并不是這些文件的物理地址(也就是實(shí)際上在硬盤(pán)上的地址),而是操作系統(tǒng)給進(jìn)程分配的
虛擬內(nèi)存地址。
為什么會(huì)這樣呢?
首先,這是操作系統(tǒng)為了防止硬件被某些惡意的程序?yàn)E用。其次實(shí)際上外存設(shè)備的種類(lèi)十分的復(fù)雜繁多,虛擬內(nèi)存空間也是在為應(yīng)用程序提供簡(jiǎn)單統(tǒng)一可操作的空間。
我們的用戶(hù)界面實(shí)際上只是任務(wù)管理器中可以看到的一個(gè)名為 explorer.exe 的進(jìn)程,內(nèi)核才是操作系統(tǒng)的核心。系統(tǒng)上的其他部分都必須依靠?jī)?nèi)核才能提供服務(wù)。對(duì)于提供保護(hù)機(jī)制的現(xiàn)代系統(tǒng)來(lái)說(shuō),內(nèi)核獨(dú)立于普通的應(yīng)用程序,它一般處于系統(tǒng)態(tài),擁有受保護(hù)的內(nèi)存空間和訪(fǎng)問(wèn)硬件設(shè)備的所有權(quán)限。這種系統(tǒng)態(tài)和被保護(hù)起來(lái)的內(nèi)存空間,統(tǒng)稱(chēng)為
內(nèi)核空間。
相應(yīng)的,我們?cè)谑褂脴?biāo)準(zhǔn)庫(kù)的函數(shù)去讀寫(xiě)文件時(shí),實(shí)際上是通過(guò)標(biāo)準(zhǔn)庫(kù)去調(diào)用內(nèi)核的方法獲取到一個(gè)文件的映射內(nèi)存,然后再通過(guò)這個(gè)映射的虛擬內(nèi)存去操作硬件上的文件。
windows操作系統(tǒng)中的每個(gè)進(jìn)程都有分配 4GB 大小的虛擬進(jìn)程地址空間。32位操作系統(tǒng)將 4GB 的物理內(nèi)存空間劃分為兩個(gè)部分,進(jìn)程使用 2G ,一般是被稱(chēng)作用戶(hù)空間,內(nèi)核使用 2G ,稱(chēng)為內(nèi)核空間。一個(gè)進(jìn)程在被創(chuàng)建的時(shí)候如果內(nèi)存不夠的話(huà),自然就是靠虛擬內(nèi)存了,其空間跨度包括三個(gè)部分:處理器部分(CPU)<-- 主存儲(chǔ)器部分(內(nèi)存)<-- I/O設(shè)備(如硬盤(pán))
如果你的內(nèi)存只有 2GB 的話(huà),那么對(duì)于一個(gè)進(jìn)程而言,它的 4GB 虛擬內(nèi)存空間多是在IO設(shè)備中虛擬的。
好了,話(huà)題繞回來(lái)。如果你能理解上述的保護(hù)機(jī)制,那么你也大概理解了內(nèi)核在操作系統(tǒng)中是怎么樣一個(gè)角色,那么我們接下來(lái)開(kāi)始談?wù)劸浔?br>
句柄是 windows 編程的一個(gè)基礎(chǔ)概念。如果你有接觸過(guò)進(jìn)程ID的話(huà),這個(gè)概念上有相近的地方,譬如進(jìn)程ID就是系統(tǒng)中每一個(gè)進(jìn)程的唯一標(biāo)識(shí)。
而句柄的話(huà)則比進(jìn)程ID更細(xì)致一些,它是運(yùn)行在系統(tǒng)中的程序中的不同對(duì)象或者同類(lèi)對(duì)象中的不同的實(shí)例。諸如,一個(gè)窗口,按鈕,圖標(biāo),滾動(dòng)條,輸出設(shè)備,控件或者文件等。
一個(gè)進(jìn)程可以創(chuàng)建多個(gè)窗口,而每一個(gè)在 Windows 系統(tǒng)下被創(chuàng)建的窗口都有它的句柄(上一節(jié)說(shuō)過(guò)的HWND類(lèi)型,窗口的句柄)。當(dāng)然不止是窗口,一個(gè)窗口中可能有著更多的實(shí)例,或者叫做控件會(huì)比較好理解,比如一個(gè)QQ的登錄窗口有一個(gè)HWND(Handle of window),在這個(gè)窗口中有可以輸入QQ賬號(hào)和密碼的文本框,這些具體的控件也都有著它對(duì)應(yīng)的句柄。OK,介紹到這里,相信大家已經(jīng)有了一定的概念了。
那么需要注意的是當(dāng)一個(gè)進(jìn)程被初始化時(shí),系統(tǒng)就會(huì)為它分配一個(gè)句柄表。大家可以結(jié)合上面說(shuō)的例子理解一下句柄表這個(gè)概念。這個(gè)句柄表只用于內(nèi)核對(duì)象。作為一個(gè)稱(chēng)職的 Windows 程序員,必須懂得這些基本信息。
為什么要使用windows API來(lái)編程
要在windows 上做開(kāi)發(fā)的話(huà),調(diào)用系統(tǒng)的API實(shí)際上才是速度最快的辦法。我們?cè)贑的基礎(chǔ)中有學(xué)過(guò)文件操作,還有一些簡(jiǎn)單的內(nèi)存操作??墒侨绻憧戳松厦娴膬?nèi)核介紹之后,應(yīng)該會(huì)知道實(shí)際上操作系統(tǒng)是會(huì)提防著每個(gè)進(jìn)程,作為一個(gè)程序是無(wú)法直接訪(fǎng)問(wèn)到內(nèi)存和硬件的。
也就是說(shuō),如果我要進(jìn)行文件操作或者內(nèi)存操作的話(huà),最后都是要通過(guò)內(nèi)核來(lái)提供相應(yīng)的功能來(lái)實(shí)現(xiàn)的。這也意味著,同樣的讀寫(xiě)文件的程序,如果一個(gè)是標(biāo)準(zhǔn)庫(kù)的函數(shù)寫(xiě)的,一個(gè)是用系統(tǒng)API寫(xiě)的,那么系統(tǒng)API寫(xiě)的程序絕對(duì)要比用標(biāo)準(zhǔn)庫(kù)的快。
原因很簡(jiǎn)單,因?yàn)闃?biāo)準(zhǔn)庫(kù)要訪(fǎng)問(wèn)硬件(文件)最后還是要低聲下氣的去找內(nèi)核,不然的話(huà)就沒(méi)辦法訪(fǎng)問(wèn)到。于是很簡(jiǎn)單的能看出來(lái)兩者的優(yōu)劣,一個(gè)是繞著彎子去調(diào)用內(nèi)核的API訪(fǎng)問(wèn),一個(gè)是直接調(diào)用內(nèi)核的API去訪(fǎng)問(wèn),自然是后者的速度和效率更高。
事實(shí)上,我們所熟悉的
malloc() 內(nèi)存分配函數(shù),到了 windows 系統(tǒng)上最后還是要調(diào)用 windows API 中的 HeapAlloc() 函數(shù)。人總是追求速度和效率的,所以這也是為什么我們?cè)?windows 上開(kāi)發(fā)需要學(xué)習(xí)使用 windows API 的原因。