探秘 Windows 7 系統(tǒng)中的 POSIX 子系統(tǒng)

2010/6/26 20:39:09    編輯:SnakeWind     字體:【

Win7之家afsion.com.cn):探秘 Windows 7 系統(tǒng)中的 POSIX 子系統(tǒng)

《Windows Internals 5e》第二章開頭提到了1989年Windows NT最初設(shè)計時的設(shè)計要求,其中倒數(shù)第二條是:

Meet government requirements for POSIX 1003.1 compliance。

Windows NT一直提供了POSIX子系統(tǒng),但是在最近的若干版本中,一直沒有默認安裝上。

要在Windows 7中安裝,第一步是在“打開或關(guān)閉系統(tǒng)功能”中選中“基于UNIX的應(yīng)用程序子系統(tǒng)”一項,如圖所示:

稍等過后,我們就可以使用基于Windows NT的POSIX子系統(tǒng)的POSIX應(yīng)用程序了。...好拗口,不過咱還是得稍微提醒一下,就算使用POSIX的庫,但是如果不是使用基于Windows的編譯器,還是沒法運行的。從這個角度說,POSIX子系統(tǒng)也就是方便了UNIX應(yīng)用程序到Windows的移植罷了。順便提一下,Windows的POSIX子系統(tǒng)是基于POSIX.1(IEEE.Std 1003.1-1990;ISO/IEC 9945-1:1990)的.我們不妨稍微看看POSIX子系統(tǒng)給我們帶來的新組件:

其中,%SystemRoot%/System32/psxss.exe是POSIX子系統(tǒng)的環(huán)境子系統(tǒng)進程的映像,其地位就像csrss.exe之于Windows子系統(tǒng)一樣。psxss.exe將會在系統(tǒng)首次運行POSIX應(yīng)用程序的時候啟動,其生命周期一直截止到系統(tǒng)關(guān)閉為止。psxdll.dll就是POSIX庫文件,對POSIX庫的調(diào)用最終都將落到它的手中。...不過它的主要任務(wù)其實是將POSIX系統(tǒng)調(diào)用轉(zhuǎn)換為Windows系統(tǒng)調(diào)用,再調(diào)用Windows子系統(tǒng)的相關(guān)功能來完成任務(wù)。畢竟是Windows的地盤,有道是強龍難壓地頭蛇,更何況這地頭蛇的能耐還不輸強龍呢。再看那個%SystemRoot%/posix.exe,它將會成為POSIX子系統(tǒng)的會話管理進程,只要有任何POSIX應(yīng)用程序運行,它就會存在;而如果所有POSIX進程都已經(jīng)終結(jié),這個進程也會被殺死。

但是現(xiàn)在我們還是不能自行編寫POSIX應(yīng)用程序,也不能像在Unix中一樣使用C Shell和Unix Perl,這些都是需要額外下載的。微軟提供了Utilities and SDK for Subsystem for UNIX-based Applications,其中包含了一系列源于SVR-5和BSD的實用程序和命令,開發(fā)所需的頭文件和庫,以及一套Unix Perl(呃...ActivePerl的Windows版本和Linux版的Perl咱也有...咱都快變成Perl收藏家了...),還有Visual Studio調(diào)試插件(windows 7的版本是for Visual Studio 2003/2005/2008的,不支持2010;Vista的版本不支持2008)。

現(xiàn)在在開始菜單中應(yīng)該已經(jīng)有Subsystem for UNIX-based Application子菜單了。展開它看看,一共有兩個菜單項:Download Untilities for Subsystem for UNIX-based Applications和What’s new in Subsystem for UNIX-based Applications兩項。Download Untilities for Subsystem for UNIX-based Applications就是指向Utilities and SDK for Subsystem for UNIX-based Applications下載頁的鏈接——不過是Windows Server 2008和Windows Vista的版本-_-|||請使用What’s new in Subsystem for UNIX-based Applications首頁上提供的鏈接(最終會指向http://www.microsoft.com/downloads/details.aspx?FamilyID=dc03485b-629b-49a6-b5ef-18617d1a9804&displaylang=en)下載基于Windows 7和Windows Server 2008 R2的版本——不只是版本更新,體積也變得小多了,由450M左右下降到了250M左右(說起來Windows SDK的體積也由Windows Vista的1.5G下降到了700M左右了,挺厲害的啊...)

現(xiàn)在開始菜單中應(yīng)該已經(jīng)有了更多選項了:

嗯,除了超鏈接和幫助之外就全是我們剛剛裝上的那些工具中的Shell那部分了。微軟為POSIX子系統(tǒng)提供了數(shù)百款來源于UNIX的工具可以使用,而這些工具都是基于Windows POSIX子系統(tǒng)直接使用GNU原生的代碼編譯的?梢哉f這幾百個工具也是Windows POSIX子系統(tǒng)對于POSIX.1提供的良好支持的明證...只是,那個版本實在是太舊了...上一個圖對比一下微軟為POSIX子系統(tǒng)提供的vim工具和opensolaris 2009.06當中提供的vim工具:

由圖可見,微軟提供的還是14年以前的版本呢。雖然不是不能理解,不過微軟對這個POSIX子系統(tǒng)還真是不上心啊...

注意,啟動Shell(我用的是C Shell)之后的當前目錄好像是當前用戶的目錄...確實是UNIX的風格的說...可以輸入cd /跳轉(zhuǎn)到根目錄下。輸入ls -l看看~哈哈,充滿UNIX風格的目錄列表呈現(xiàn)在面前。不過,這些目錄都是原原本本的Windows目錄,而根目錄其實就是你在安裝Untility and SDK for SUA時選擇的目錄。正因如此,你會發(fā)現(xiàn)所有目錄的owner竟然都是Windows的用戶組:

如果要通過POSIX子系統(tǒng)造訪Windows的文件系統(tǒng),請先進入/dev/fs下。該目錄下面的虛擬目錄,就是你的Windows磁盤驅(qū)動器的映射。提醒一下,UNIX是區(qū)分大小寫的哦。

微軟為POSIX子系統(tǒng)提供了兩套GCC,分別是3.3和4.2.0...呃,后者還是GCC第一個支持OpenMP的版本。我們不妨試著編譯UNIX-Only的程序看看。話說我對UNIX編程實在不太擅長,因此就寫一個簡單的fork好了。

Test1.c
  1. #include <unistd.h>
  2. #include <stdio.h>
  3. int main(int argc,char **argv){
  4. if(fork())
  5. printf("This is parent process.\n");
  6. else
  7.         printf("This is child process.\n");
  8.  
  9. return 0;
  10. }

然后輸入如圖的命令,別忘了修改成自己的路徑,然后就可以執(zhí)行看看了。寫代碼當然可以使用vi了,不過我用的是UltraEdit。別忘了保存的時候?qū)⒕幋a選成ASCII,把換行符選成UNIX樣式咯。

OK,這樣就運行出來了。話說,gcc的反應(yīng)好象比在OpenSolaris里面慢一點啊。就這么抵觸微軟嗎?

不過這里編譯出來的應(yīng)用程序,自然是沒法在UNIX操作系統(tǒng)下運行的。相反,只要給它加上個exe后綴,就可以像平常運行Windows應(yīng)用程序一樣通過POSIX子系統(tǒng)運行它。作為本文的結(jié)束,我們來做一個小小的實驗:

首先,稍微修改一下剛剛的代碼:

隱藏行號 復制代碼 ? Test1.c
  1. #include <unistd.h>
  2.  #include <stdio.h>
  3.   
  4. int main(int argc,char **argv){
  5. if(fork()){
  6. printf("This is parent process.\n");
  7. for(;;);
  8. }
  9. else{
  10. printf("This is chile process.\n");
  11. for(;;);
  12. }
  13.  
  14. return 0;
  15. }
  16.  

使用GCC編譯這段代碼并將編譯所得的程序修改為exe后綴,隨后關(guān)閉所有的POSIX進程。找一個好用一點的進程監(jiān)視軟件(推薦Sysinternals的Process Explorer),看看現(xiàn)在的進程狀況。大致應(yīng)該如下所示:

需要注意的是posix.exe進程已經(jīng)不存在了;叵肭拔乃,posix.exe是POSIX的會話進程,沒有posix.exe也就間接說明了沒有POSIX應(yīng)用程序正在運行。

現(xiàn)在我們啟動剛才編譯的程序,現(xiàn)在Process Explorer的界面應(yīng)該如下所示:

嗯嗯,我們的程序和它fork出的子進程正在高高興興地運行著,因為我們在程序中添加了死循環(huán)所以進程不會立刻退出,而是像沒有出口的自旋鎖一樣饕餮著CPU資源...嗯,這些都不重要,重要的是posix.exe的重回人間——在上面的截圖中就是那個pid為5556的進程,F(xiàn)在,只要我們在運行著test1.exe的Shell中按下Ctrl+C,test1.exe父子就和posix.exe先生一起去進程天國報到了^^

(順便插一句題外話,.Net Framework 4的TPL中好像有提供SpinLock結(jié)構(gòu)支持自旋鎖的功能,雖然使用自旋鎖的花銷會比較小,但是請謹慎使用這個結(jié)構(gòu),尤其是不要用于可能發(fā)生長時間鎖定的操作——否則會發(fā)生什么,請參見上圖驟然上漲的CPU使用率曲線...畢竟自旋鎖就是通過循環(huán)實現(xiàn)的,不同于互斥鎖,自旋鎖會一直處于忙等的狀態(tài),直到時間片結(jié)束,然后是下一個時間片...下下個時間片...)