資源描述:
《第5章進程間通信》由會員上傳分享,免費在線閱讀,更多相關內容在教育資源-天天文庫。
1、第5章進程間通信為了實現(xiàn)特殊的目的,系統(tǒng)編程時往往使用多個進程,這些進程往往會使用動態(tài)鏈接庫為紐帶,實現(xiàn)進程間的數(shù)據(jù)通信。進程間的數(shù)據(jù)通信方法有很多,如果只是一個簡單的通知事件,可以采用Win32提供的系統(tǒng)對象比如信號燈、互斥、關鍵臨界區(qū)、事件等。如果需要大量的數(shù)據(jù)通信,而又不在乎速度和性能,適時性要求不高可以采用文件、注冊表和WindowsNT提供的事件日志等。對于適時性要求較高的場合,可以采用創(chuàng)建內存共享文件、創(chuàng)建管道、郵槽,通過窗口消息來實現(xiàn)消息共享。對于遠程的應用程序,還可以通過socket和有關網(wǎng)絡協(xié)議實現(xiàn)通信。前面已經(jīng)提
2、到了多種方法,比如內存共享文件、動態(tài)鏈接庫的共享節(jié)等,這里主要介紹系統(tǒng)內核對象的應用以及其他幾種進程間通信的方法。5.1只啟動一份程序實例只保留一份應用程序實例的目的是顯而易見的,它主要是防止在多個實例加載的系統(tǒng)中造成資源浪費,同時也可以避免多個實例存取同一系統(tǒng)對象造成的各種沖突。為了只允許運行程序的一個實例,往往需要在程序運行時,對系統(tǒng)進行檢查,發(fā)現(xiàn)已經(jīng)有一個實例存在就立即退出。由于每一個進程啟動時都會有一個進程標識,有時會創(chuàng)建自己的主窗口,在注冊表或者系統(tǒng)文件中寫入一些標記信息,有時也會創(chuàng)建一些系統(tǒng)對象,這些信息都可以作為查找前
3、面一個實例存在的標志。前面介紹進程枚舉時提到了通過進程枚舉得到各個進程標識,進而得到進程名稱的實現(xiàn)。實際上這個過程本身就可以作為查找應用程序實例的一種方法。一般地,用戶會盡可能地避免修改可執(zhí)行文件的名稱,而進程文件名稱重名的幾率雖然存在,但是非常小,通過進程名稱查找仍然是非常有效的。當然了這種方法極其繁瑣,一方面它要處理WindowsNT4和Windows9x之間的差異;另一方面,進程的枚舉也不是一件輕松的任務。所以這種方法的應用不是很多。通過窗口查找應該是一個簡單易行的辦法,因為大部分基于GUI實現(xiàn)的應用程序都會創(chuàng)建自己的窗口,這
4、些窗口類名和窗口標題完全相同的幾率很低,使用這種方法應該是簡單有效的。Windows提供的FindWindow和FindWindowEx兩個函數(shù)可以根據(jù)窗口類名和窗口標題來查找是否存在一個指定特征的窗口,以此來作為進程是否存在的標志。比如InternnetExplorer程序和Shell進程都有其獨特的特征。利用這些特征來判斷進程實例的存在是非常有效的,而且這種方法不需要創(chuàng)建任何系統(tǒng)內核對象。但是這種方法有一個很大的局限性,就是如果一個程序運行時沒有窗口消息循環(huán),這種方法就會失效。使用內核對象來識別程序實例是最精確的,相當于DNA鑒
5、定,下面是一段采用互斥內核對象實現(xiàn)的,同樣用戶還可以使用事件、原子等對象。例5-1通過互斥對象實現(xiàn)惟一實例進程。HANDLECreateOneAppMutex(LPCTSTRlpName){HANDLEhMutex;//CreatemutexhMutex=CreateMutex(NULL,TRUE,lpName);switch(GetLastError()){caseERROR_SUCCESS:break;//互斥對象創(chuàng)建成功,沒有實例運行CaseERROR_ALREADY_EXISTS:hMutex=NULL;break;//互斥
6、對象已經(jīng)存在,程序的一個實例正在運行default:break;}//由于某個原因可能無法創(chuàng)建實例returnhMutex;}這種方法實現(xiàn)的原理是基于所有系統(tǒng)內核對象不允許兩個重名的對象共存。它實現(xiàn)的原理是,每個進程啟動時首先根據(jù)系統(tǒng)的對象(事件、互斥、原子)檢查該名稱標識的對象是否存在。如果不存在,就創(chuàng)建該對象;否則直接退出。在程序退出時,系統(tǒng)會釋放該系統(tǒng)對象。顯然這種方法的準確性是無庸置疑的,但是使用這種方法有一定的風險,因為系統(tǒng)的對象的創(chuàng)建和釋放是通過兩個步驟實現(xiàn)的。如果在進程運行期間,系統(tǒng)異常退出,那么系統(tǒng)內核對象回收就無法
7、實現(xiàn)。這樣已經(jīng)創(chuàng)建的對象將一致保持到系統(tǒng)注銷或者重新啟動時為止,除非用戶采用其他方法關閉該內核對象。否則,可以設想進程本來已經(jīng)異常終止,但是它申請創(chuàng)建的內核對象卻沒有釋放,檢查時這個對象仍然存在,這樣很有可能進程將無法創(chuàng)建一個惟一的實例。5.2使用共享內存實現(xiàn)進程間通信盡管進程間通信的方法有多種,但是對于單機而言,最底層共享的機制是內存共享文件。上面提到的多種方法都是基于內存共享文件實現(xiàn)的。使用內存共享文件可以提高共享的性能,降低系統(tǒng)開銷。使用內存共享文件實現(xiàn)進程共享是基于同一文件映射對象的視圖來實現(xiàn)的,各個進程會共享同一物理存儲器
8、的同一個頁面,任何一個進程對該共享文件對象的修改都會同時影響其他進程對該對象的映射,它們會立即看到修改進程對共享內存對象的變更。使用內存共享文件實現(xiàn)共享數(shù)據(jù),一般都會創(chuàng)建一個名稱字符串標識的共享內存對象。創(chuàng)建的方法是調用CreateF