MiniGUI Lite 版本的新改进
簡介:?MiniGUI從0.98開始推出Lite版本。Lite版本是MiniGUI邁向嵌入式應用重要的一步。在Lite版本中,我們使用了自己設計的引擎,拋棄了pthread庫,從而使得MiniGUI能夠輕裝上陣,更穩定,更高效率,也更符合嵌入式系統應用。本文介紹了MiniGUILite版本的基于UnixIPC實現的多進程機制。并詳細介紹了一些實現細節。
?
1 引言:為什么要開發Lite版本
現在,大多數UNIX系統采用X 窗口系統作為圖形用戶界面,MS Windows 則采用 Microsoft公司自己設計的GUI系統。這兩種GUI系統也代表著目前通用GUI系統的兩種實現。比如,著名的自由軟件MicroWindows就同時實現了類似于MS Windows的MicroWindows API 和類似于X Window的NanoX API。
MiniGUI 原來就采用了類似于MS Windows的體系結構,并且建立了基于線程的消息傳遞和窗口管理機制。然而,它是基于POSIX 線程的,這種實現提供最大程度上的數據共享,但也同時造成MiniGUI體系結構上的脆弱。如果某個線程因為非法的數據訪問而終止運行,則整個系統都將受到影響。
另一種方法是采用UNIX進程間通信機制建立窗口系統,即類似 X Window 的客戶/服務器體系。但是這種體系結構也有它的先天不足,主要是通常的 IPC 機制無法提供高效的數據復制,大量的 CPU 資源用于各進程之間復制數據。在 PDA 等設備中,這種 CPU 資源的浪費將最終導致系統性能的降低以及設備耗電量的增加。
為了解決以上各種問題,同時也為了讓 MiniGUI更加適合于嵌入式系統,我們開發了MiniGUI Lite 版本。
2 Lite版本簡介
在MiniGUI Lite 版本中,我們可以同時運行多個 MiniGUI 應用程序。首先我們啟動一個服務器程序 mginit,然后我們可以從中啟動其他做為客戶運行的 MiniGUI 應用程序。如果因為某種原因客戶終止,服務器可以繼續運行。mginit程序建立了一個虛擬控制臺窗口。我們可以從這個虛擬控制臺的命令行啟動其他的程序,甚至可以通過 gdb 調試這些程序。 這大大方便了MiniGUI應用程序的調試。
MiniGUI-Lite 區別于 MiniGUI 原有版本的最大不同在于我們可以在 MiniGUI-Lite 程序中創建多個窗口,但不能啟動新的線程建立窗口。除此之外,其他幾乎所有的 API 都和 MiniGUI 原有版本是兼容的。因此,從 MiniGUI 原有版本向 MiniGUI-Lite 版本的移植是非常簡單的。象mglite-exec 包中的程序,其中所有的程序均來自 miniguiexec 包,而每個源文件的改動不超過 5 行。
3 Lite版本的設計
設計之初,我們確定MiniGUI Lite 版本的開發目的:
顯然,要滿足這三個設計目的,如果采用傳統的 C/S 結構對現有 MiniGUI 進行改造,應該不難實現。但傳統 C/S 結構的缺陷卻無法避免。經過對 PDA 等嵌入式系統的分析,我們發現,某些 PDA 產品具有運行多個任務的能力,但同一時刻在屏幕上進行繪制的程序,一般不會超過兩個。因此,只要確保將這兩個進程的繪制相互隔離,就不需要采用復雜的 C/S 結構處理多個進程窗口之間的互相剪切。在這種產品中,如果采用基于傳統 C/S 結構的多窗口系統,實際是一種浪費。
因此,我們對 MiniGUI-Lite 版本進行了如下簡化設計:
4 Lite版本的一些實現細節
4.1 系統初始化
應用程序的入口點為main()函數,而MiniGUI應用程序的入口點為MiniGUIMain,在這兩個入口點之間,是MiniGUI的初始化部分和結束部分。如圖 1所示。
圖 1 MiniGUI應用程序流程
在系統初始化時,MiniGUI區分兩種情況:服務器(Server)和客戶(Client)。針對這兩種不同的情況,隨后的各項操作均有不同的處理,這主要依據全局變量mgServer。由于僅僅根據名稱判斷是否為服務器,所以服務器的名字只能是"mginit"。 InitGUI()是對MiniGUI進行初始化的函數,它主要負責:
流程如圖 2(為突出重點,我們忽略了一些細節):
圖 2 InitGUI流程
4.2 共享資源初始化
共享資源是客戶服務器模型中的重要元素,它由服務器負責創建和釋放,而提供所有客戶程序共享的數據資源。它的初始化過程由圖 3所示的調用流完成。
圖 3 InitGUI調用流
如果是服務器,則初始化此結構,src/kernel/sharedres.c/LoadSharedResource()負責完成這一任務,它的執行流如圖 4所示:
圖 4 LoadSharedResource 流程
對于客戶,則只需要與此結構進行連接即可,它在src/kernel/sharedres.c/AttachSharedResource()實現,參見圖 5:
圖 5 AttachSharedResource 流程
4.3 服務器客戶通信連接初始化
在客戶服務器模型的討論中,我們還將詳細的討論服務器客戶的通信機制,這里只給出初始化的調用關系。見圖 6。
圖 6 通信連接的初始化
ServerStartUp實現流程如圖 7所示:
圖 7 ServerStartUp 流程
ClientStartUp()實現如圖 8所示:
圖 8 ClientStartUp流程
4.4 多進程模型
Lite版本是支持客戶服務器(C/S)方式的多進程系統,在運行過程中有且僅有一個服務器程序在運行,它的全局變量mgServer被設為TRUE,其余的MiniGUI應用程序為客戶,mgServer變量被設為FALSE。各個應用程序分別運行于各自不同的進程空間,如圖 9所示:
圖 9 多進程模型
目前的程序結構使每個加載的進程擁有一個自已的桌面模型及其消息隊列,進程間的通信依靠以下所提到的進程通信模型來完成。
4.5 進程通信模型
這里我們所指的進程通信包括通過共享內存實現的數據交換和通過套接字實現的客戶服務器通信模型。先看在MiniGUI中使用Socket的通信模型結構,如圖 10:
圖 10 基于Socket 的通信模型
下面再看看MiniGUI進程間的資源共享問題。見圖 11。
圖 11 內存共享通信模型
如上圖所示,服務器負責裝入共享資源,其中包括系統圖標、位圖、字體等,客戶則通過AttachSharedResource()獲取指向共享資源的指針,初始化一塊共享內存及與使用已有共享內存的方法在前面的描述中已提到,在此不再贅述。
4.6 各進程之間的同步
這里所指的進程同步主要是指各進程繪制的同步,顯然,同時不可能有兩個進程向屏幕繪制。傳統的GUI實現大多是只有一個進程負責繪制,而在我們Lite版本中,各進程負責自己的繪制。同時,我們的Lite 版本還支持虛屏切換,當我們切換出去的時候,誰也不能夠向屏幕繪制。
Lite 版本利用Unix 信號解決了繪制同步問題。系統定義了兩個信號:SIG_SETSCR 和 SIG_DNTDRAW,它們其實是重定義了的信號SIGUNUSED和 SIGSTKFLT。每個進程都定義了兩個變量dont_draw和cant_draw。
服務器利用SIG_SETSCR和SIG_DNTDRAW來控制各客戶程序誰有權對屏幕繪制,而不是自己全權代理。這也使得進程間通信量大大減少:當服務器希望一個客戶程序不要向屏幕繪制時,就向它發送SIG_DNTDRAW信號,當讓其繪制時,則發送SIG_SETSCR。從而實現了各進程間的屏幕繪制同步。
當一個客戶收到SIG_DNTDRAW時,將自己的變量dont_daw設置為ture,收到SIG_SETSCR時,則將dont_draw變量設置為false。另一個變量cant_draw則是給客戶自己用的,比如,做剪切時,當它的剪切域為空集時,又比如,當進行虛屏切換時,當前的進程將自己的cant_draw變量設置為true。
另外,如果一個客戶正在繪圖,我們只有等它畫完后才能讓其他進程得到這一權利。我們不需要知道誰在繪圖,但我們要等到這一過程結束。Lite版本利用信號量機制解決了這一問題。在共享內存里保存著一個變量shmid,各進程利用它來實現各自的鎖機制。這種機制有點類似于文件鎖,不過要快許多。
從而,利用信號量機制,Lite版本實現了多進程的繪制同步。服務器利用信號控制各客戶,而各客戶也充分合作。相關代碼都在MiniGUI的系統庫里實現。保證了系統的穩定運行。
5 總結語
MiniGUI Lite版本試圖在傳統的基于線程的單體結構和C/S結構之間尋求一種效率和穩定性的折中,以便更加適合運行在PDA等小型嵌入式系統中。如今,MiniGUI Lite版本已經穩定地運行在一些PDA系統上,事實證明這種嘗試是成功的。
參考資料
- MiniGUI 資源
- MiniGUI 主頁
總結
以上是生活随笔為你收集整理的MiniGUI Lite 版本的新改进的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 股票常用名词解释与技术指标公式
- 下一篇: C4D 入门笔记(二)