服務程式入門

來源:互聯網
上載者:User

 系統服務體系架構
CE的系統服務是一個DLL,這個DLL的構建幾乎與流裝置驅動一模一樣
與流裝置驅動一樣,Windows CE系統服務提供同樣的10個入點口,從xxx_Init到 xxx_PowerDown
系統服務有三個前置詞字元

系統服務IOCTL命令
IOCTL_SERVICE_START
IOCTL_SERVICE_STOP
IOCTL_SERVICE_REFRESH
IOCTL_SERVICE_INSTALL
IOCTL_SERVICE_STATUS
IOCTL_SERVICE_SUPPORTED_OPTIONS

系統服務的應用控制
ActivateService
RegisterService
GetServiceHandle
ServiceIoControl
DeregisterService

服務管理員是由進程Service.exe來實現的,其工作機制與功能與裝置管理員Device.exe非常相似。

Device.exe負責載入所有的驅動程式,Service.exe負責載入所有的服務。

在Windows CE中,實現一個服務程式與實現流式介面驅動程式非常相似,所有有服務程式均以動態連結程式庫提供,並匯出其中的相關介面函數。
與流式介面驅動程式類似,服務程式有也一個3字元的Prefix和一個Index,這些資訊也在註冊表中被設定。

Windows CE的服務有兩種啟動方式
通過註冊表中設定相應的登錄機碼,系統啟動時,讓Service.exe自動載入服務。
應用程式使用函數載入服務

當Windows CE啟動時,Service.exe搜尋系統註冊表中的HKEY_LOCAL_MACHINE\Service
然後枚舉Service下的所有子鍵,並依次載入所有的服務。

應用程式通過服務的API函數動態載入服務程式。Windows CE提供ActivateService()函數來實現服務的動態載入。

一般情況下,Service.exe進程負責載入所有的服務。
在一些特殊情況下,可能需要將一個服務由Service.exe進程單獨載入,從而實現與其他服務的隔離。
如果服務在Service.exe進程中單獨載入,這個服務稱為獨立服務。

要把某一個服務配置成獨立服務,只需配置註冊表鍵HKEY_LOCAL_MACHINE\Service\服務\ 下的Context項。
如果Context項設為2,則表明該服務為獨立服務。

在Windows CE下,許多服務程式都是作為網路服務伺服器存在的。這些服務都會偵聽某個網路連接埠,當有客戶串連這些連接埠時,服務程式會給客戶提供相應的服務。
這樣的服務,Windows CE稱之為超級服務。 

參看 裝置驅動
—————————
Windows CE嵌入式開發入門-基於Xscale架構
9.1.8 服務與裝置的比較

討論有關Windows Mobile服務模組、服務模組和普通驅動程式的區別以及如何註冊、啟用/控制/停止一個服務。

Services.exe是一個和Device.exe有同等地位的進程,它的用途是為了彌補Device.exe的不穩定。如果一個裝置驅動由於某種原因處於異常狀態或者不受裝置管理員控制時,若讓其繼續存留在裝置管理員中,則會影響其他正常啟動並執行驅動程式,甚至使系統崩潰,而使用服務這種機制能儘可能地避免這種情況發生,當系統中有類似服務作業失敗的訊號產生時,系統不會因此而受到影響。和驅動程式一樣,服務也提供了能控制其自身運行狀態的函數介面集,如啟動服務、暫停服務、其他I/O控制。

在Windows Mobile. NET中操作服務和操作裝置驅動的方式十分類似。如果一個裝置驅動實際上並不需要和硬體發生互動,也不需要處理序間通訊的時候,就應當將其實現為一個服務,以提高系統安全性。服務出錯,不會引起系統的嚴重錯誤。

Services.exe同樣可以被配置用來在特定的串連上等待資訊。Socket連接埠接收到資料包時,Services.exe就會將資料分發到相應的服務中去。
有一點需要注意的是,Services.exe只是防止驅動程式因為服務失敗而崩潰,但並不保證它不會引起其他服務的錯誤,因此服務應當認真調試。
在%WINCEROOT%\Public\Servers\Sdk\Samples\Telnetd目錄下,Windows CE.NET提供了一個範例程式,裡麵包含了如何啟動、載入和卸載一個服務,同時還包含了如何進行流介面服務的實現方式。
1.如何啟用並且控制一個服務
所謂啟用服務就是將服務載入到Service.exe的進程空間裡來。可以使用以下方法來載入服務並且在載入後進行控制。

*使用註冊表中built-in鍵的功能,在系統啟動時,通過註冊表自舉將服務載入;
*使用ActivateService函數,通過程式來載入服務;
*可以使用CreateFile函數來開啟一個服務;
*可以使用I/O control、ReadFile、WriteFile、SetFilePointer等函數來操作一個服務;
*還可以使用GetServiceHandle來獲得服務的控制代碼。

當用程式來載入一個服務時,代碼載入的格式為:
ActivateService(L”TELNETD”, 0);

和裝置管理員能控制一個正在啟動並執行裝置驅動一樣,Service.exe也能通過多種途徑來控制一個正在啟動並執行服務。
以下是實現控制服務的具體步驟。
(1)使用CreateFile函數,在參數中設定適當的首碼和索引值。這些值應當在註冊服務的時候被寫入註冊表;
(2)向服務發送I/O控制字。利用DeviceIoControl函數,裝置管理員重新導向到該服務的XXX_IOControl入口。下面的程式碼片段顯示了如何擷取一個服務的狀態:
HANDLE hService = CreateFile(L”TEL0:”,0,0,NULL,OPEN_EXISTING,0,NULL);
if(hService != INVALID_HANDLE_VALUE) {
DWORD dwState;
DeviceIoControl(hService, IOCTL_SERVICE_STATUS, NULL, 0,
&dwState, sizeof(DWORD), NULL, NULL);
CloseHandle(hService);
};

(3)如果服務還支援流式介面的話,那麼可以通過額外的操作來控制一個服務。如ReadFile、WriteFile、SetFilePointer函數。

還可以使用GetServiceHandle 函數來控制一個服務的狀態。需要注意的是,在調用流式介面之前,必須擷取服務的有效控制代碼,否則這些操作不會成功。可以通過GetServiceHandle函數擷取服務的有效控制代碼。

下面是使用GetServiceHandle的一個例子:
HANDLE hService = GetServiceHandle(“TEL0:”, NULL, NULL);
if(hService != INVALID_HANDLE_VALUE) {
DWORD dwState;
ServiceIoControl(hService, IOCTL_SERVICE_STATUS, NULL, 0,
&dwState, sizeof(DWORD), NULL, NULL);
}

2.Windows CE服務的目的
*作為裝置管理員的補充
*處理不需要直接和系統有互動的請求
* 增強驅動的可靠性,降低系統崩潰的可能
* 提供超級服務

Services.exe是作為對Device.exe模組的補充,著重加強了其載入系統服務的可靠性。它將那些和系統核心互動不是很多或者不用直接和核心互動的請求與系統服務分割開來獨立處理,這樣就降低了核心的處理負擔。

當有一個服務發生故障時,及時地將這個服務和系統服務分割開來是保障系統安全啟動並執行重要手段之一。這個特性使得Windows CE中的驅動程式在系統服務發生故障的時候,仍然有較高的安全運行能力,降低系統崩潰風險。例如,很多嵌入式裝置在運行之後可能無人監管,因此系統安全性要求比較高,不能象案頭Windows系統那樣經常因為裝置驅動的錯誤而崩潰。

所謂的超級服務是指一個所有連接埠都允許被Services.exe監控的標準服務,即一個服務能監視所有其他的服務。使用超級服務有一個好處就是,即便許多的服務在使用,只要它們是被超級服務監視的,那麼這些服務的處理線程都只由超級服務的處理線程承擔,即所有服務最終只有一個處理線程。如果不使用超級服務,那麼每個服務都要建立一個接受線程。

Services.exe模組是通過註冊表載入的。代碼如下所示:
[HKEY_LOCAL_MACHINE\init]
“Launch60″=”services.exe”
“Depend60″=hex:14,00

3.服務與裝置的區別
* Device.exe載入驅動用來管理裝置
* Sevice.exe載入驅動用來管理軟體服務
* Services.exe象Device.exe一樣可以載入多個服務
* 如果要同時使用Device.exe和Services.exe, Windows CE中32個進程槽就要被佔用兩個

Services.exe和Device.exe模組被設計用來互相補充。Device.exe即裝置管理員用來載入驅動程式,以此來管理外圍裝置,Services.exe將載入那些不和裝置打交道的服務。
Services.exe可以管理多個服務,正如裝置管理員可以管理多個裝置驅動那樣。 Services.exe負責將和系統無關的服務的處理從裝置管理員中分割出來。當然,裝置管理員可以在Services.exe沒有被載入的環境下運行,這樣可以節省一個進程槽。但是,不載入Service.exe的後果就是驅動程式啟動並執行安全性下降。

4.如何註冊一個服務
* 使用RegisterService函數註冊
* RegisterService函數功能和RegisterDevice函數功能類似,後者目前逐漸被ActivateDeviceEx所替代。

Services.exe 也可以通過編程來啟動。代碼如下所示:

HANDLE hService = RegisterService(“TEL”,0,”telnetd.dll”,0);

這行代碼啟動了telnet server的服務常式。如果telnet server當前正在TEL0裝置上運行,那麼這個函數將返回false。如果調用GetlastError函數,將得到ERROR_DEVICE_IN_USE的錯誤資訊。

RegisterService調用後,裝置管理員將調用服務的xxx_Init入口,在調用完xxx_Init介面後,服務處於什麼樣的狀態是依據服務各自不同dwContext設定而定的。在Services.h中,為這個參數預設定了以下值:
#define SERVICE_INIT_STARTED 0×00000000
#define SERVICE_INIT_STOPPED 0×00000001

如果dwContext參數中沒有設定SERVICE_INIT_STOPPED值,那麼服務在被註冊後將建立一個線程,並且啟動它作為服務的請求接收處理線程。
如果設定了SERVICE_INIT_STOPPED標誌,那麼代表本服務將接收超級服務的監督管理,自己將不擁有接收線程,而統一有超級服務進行處理。

下面是RegisterService函數的原型:

HANDLE RegisterService( LPCWSTR lpszType,
DWORD dwIndex,
LPCWSTR lpszLib,
DWORD dwInfo
);
參數解釋:
lpszType 指向一個字串,這個字串包含了服務的首碼名(由三個字母組成,和流驅動類似)
dwIndex 定義了0~9之間的服務的索引號。
lpszLib 指向一個字串,該字串包含了代表格服務的DLL檔案名稱。
dwInfo 這是代表在調用服務的xxx_Init 入口時,傳入的參數。

傳回值
如果傳回值是被註冊的服務的控制代碼,則代表操作成功。如果返回空值則代表操作失敗。

RegisterService可以將一個未載入的服務載入到系統中,同樣也可以為一個系統中已經存在的服務載入第2個執行個體。
RegisterService將先載入在參數lpszLib中定義的DLL連結庫,然後檢查該DLL連結庫是否匯出了xxx_Init、xxx_Deinit、xxx_IOControl介面。如果DLL連結庫名出錯,將導致系統尋找不到相應的檔案,那麼函數將返回ERROR_FILE_NOT_FOUND錯誤;如果DLL連結庫中匯出的介面集不正確的話,函數將返回ERROR_FILE_NOT_FOUND錯誤。
如果系統中已經有同類的服務在運行,即首碼名一致,那麼就需要用索引值來區分執行個體。如果索引值也衝突的話,函數將返回ERROR_DEVICE_IN_USE錯誤。
在成功載入DLL檔案後,Services.exe將調用xxx_Init入口,並且將dwInfo中的參數傳遞給它。如果init是成功的話,函數將xxx_Init的傳回值保留,這將是後面xxx_IOControl、xxx_Deinit入口調用時的重要參數。

5.如何停止一個正在啟動並執行服務
使用DeregisterService函數來停止並且卸載一個服務。DeregisterService將在系統中定位一個服務,並且將它標記為無效;然後DeregisterService將阻止任何企圖開啟該服務的函數。

下面的代碼是實現關閉一個服務的例子:
HANDLE hServide = GetServiceHandle(L”TEL0: “,NULL,NULL);
if(hSerice != NULL)
DeregisterService(hService);

DeregisterService 需要使用從RegisterService返回的服務控制代碼,而不是使用CreateFile 返回的控制代碼。因此應用程式無法通過檔案系統的流式API來擷取服務的控制代碼,只能使用GetServiceHandle。

6.服務中所使用的API

Services.exe實現了如下的介面。

* XXX_Close
服務實現這個介面,並且由Services.exe 調用。當應用程式調用CloseHandle或者CloseService來關閉一個服務時,Services.exe會將操作重新對應到本介面;
* XXX_Deinit
服務實現這個介面,並且由Services.exe 調用。當應用程式調用DeregisterService來取消註冊一個服務時,Services.exe會將操作重新對應到本介面;
* XXX_Init
初始化服務的介面;
* XXX_IOControl
向服務傳遞I/O控制字;
* XXX_Read
服務實現這個介面,並且由Services.exe調用。這個介面提供了類似讀檔案的功能,只能被流式的服務所實現;
* XXX_Seek
服務實現這個介面,並且由Services.exe調用。這個介面提供了類似檔案定位的功能,只能被流式的服務所實現。
* XXX_Write
服務實現這個介面,並且由Services.exe調用。這個介面提供了類似寫檔案的功能,只能被流式的服務所實現。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.