最近正好在思考系統(tǒng)API設(shè)計中考量的一些問題,
【某網(wǎng)友討論到】
: 那地址是不是同一個地址呢。我現(xiàn)在的理解是這樣的,假設(shè)有巨大的真實內(nèi)存。windows首先將高2G的內(nèi)存自己占了,用作各種內(nèi)核對象。這2G內(nèi)存共享給每個進程,但進程不能直接訪問,只能通過windows給定的函數(shù)訪問。
: 然后每個進程都給他2G內(nèi)存,進程如果創(chuàng)建自己的對象就放到自己那2G內(nèi)存里面,如果要建立內(nèi)核對象就放到共享的那高2G里面去。
: 所以不同進程如果可以訪問高2G內(nèi)存的話,任何進程訪問到同一個高地址實際上都是訪問到同一個對象。但如果訪問低2G地址的話,不同進程是對應不同的對象的。
在不同的進程中,詢問同一個內(nèi)核對象的實際地址(無論是線性地址還是物理地址),是無意義的:
首先,內(nèi)核對象只能由在內(nèi)核態(tài)下的例程才能直接訪問,在我們?nèi)粘5拇a中,所調(diào)用的Windows API,比如CreateFile, (注意調(diào)用剛開始時是處于用戶態(tài)下的),一般都會在ntdll.dll中找到對應的內(nèi)核函數(shù)或例程,接著系統(tǒng)切換到內(nèi)核態(tài),開始調(diào)用實際對應的內(nèi)核函數(shù)(KiCreateFile),這個時候才會去訪問內(nèi)核對象的實際地址,然后建立一個該內(nèi)核對象對應當前進程的Handle,并把它返回給caller,同時切換回用戶態(tài);因此,對于用戶態(tài)程序來說,只要且只能知道該內(nèi)核對象在當前進程中的對應的Handle就可以對其進行操作了;
其次,這樣的設(shè)計是出于對OS核心數(shù)據(jù)結(jié)構(gòu)(當然包括我們正在討論的內(nèi)核對象)的保護;如果用戶態(tài)程序可以輕易的獲取內(nèi)核數(shù)據(jù)結(jié)構(gòu)的實際地址,那么對于整個OS的安全和穩(wěn)定顯然構(gòu)成很大的問題;一個用戶態(tài)的誤操作可以輕易的引起整個OS的崩潰,而有了這一層的保護,崩潰的只是當前進程而不是整個系統(tǒng);
接著上面這點,也可以看出,內(nèi)核對象的如此設(shè)計達到了接納OS本身的平滑演進的目的。從Windows 3.0到95/98,從NT到Win2k/XP,再到眼下的Vista/Win7,Windows操作系統(tǒng)本身發(fā)生了巨大的變化和進步,采納了無數(shù)的新技術(shù)新方法,但是它基本的系統(tǒng)應用編程接口,也就是我們所熟知的windows API,卻并沒有發(fā)生太大的改變,很多Win 3.0 這個16位OS時代的程序代碼只要當初設(shè)計規(guī)范編碼規(guī)范,稍許修改就可以在最新版的OS上運行如飛;是什么做到了這些?也就是所謂的極為重要的向后兼容性,我個人認為,把操作系統(tǒng)的重要/主要功能抽象成內(nèi)核對象,并通過一套極為solid的API暴露出來,達成了這個目標。
這是一種更高層次上的面向?qū)ο螅褜崿F(xiàn)的細節(jié),把系統(tǒng)的復雜,簡單而優(yōu)雅的封裝了起來。你只要調(diào)用CreateFile去建個文件或管道或郵槽,不用擔心當前OS是Windows 3.0還是Win7,獲得的Handle,你也不用去關(guān)心它以及它所指向的內(nèi)核對象是Windows 3.0的實現(xiàn)還是Win7的實現(xiàn)。
Windows上所有的精彩幾乎都是基于這套通過內(nèi)核對象概念抽象并暴露的API基礎(chǔ)之上,COM/OLE,這個二十年前震撼性的ABI和IPC范疇的技術(shù)規(guī)范,其中很多的設(shè)計思路也是植根于內(nèi)核對象的設(shè)計理念,如COM對象的引用計數(shù)和內(nèi)核對象引用計數(shù),IUnknown和Windows Handle(前者是指向某個二進制兼容的組件對象,后者引用或間接指向某個內(nèi)核對象,都是對于某個復雜概念的一致性抽象表述),等等;
十年前的.net,本來是作為COM的升級版本推出,把COM/OLE的實現(xiàn)復雜性封裝在了虛擬機平臺CLR里面,而從這個虛擬機的開源實現(xiàn)SSCLI,我們可以看到大量的COM機制在.net的具體實現(xiàn)里面起了舉足輕重的作用。在這些VM中大量symbol有著COR的前綴或者后綴,COR指代什么?Common Object Runtime, 原來CLR/SSCLI的設(shè)計思路也是把OS通過虛擬機VM的形式,并通過common object向應用程序暴露功能。
小結(jié)一下,
OS內(nèi)核對象API,三十年前系統(tǒng)級別的對象抽象;
COM/OLE,二十年前二進制組件級別的對象抽象;
.net/CLR, 十年前虛擬機平臺級別的對象抽象;
寫到這里倒是引起了我其他的一些思考,軟件工業(yè)界一直以來對面向?qū)ο驩O是熱火朝天,特別是語言層面,從C++/Java/C#到Python/JScript,不一而足;
但是我們有沒有從根本性的設(shè)計理念上對面向?qū)ο螅旒{雅言了呢?
如果現(xiàn)在設(shè)計Windows這套API的任務放在大家面前,會采用內(nèi)核對象/Handle方案還是直接指向OS內(nèi)部數(shù)據(jù)結(jié)構(gòu)的方式來暴露功能?
從三十年前的這套API的設(shè)計中,我們真的可以學到很多。