Services
1 概述
1服務程序遵循Service Control Manager(SCM)的接口規則。 啟動方式由3種:1 系統啟動時自動啟動;2 通過服務控制面板;3 通過使用服務函數。2服務可以在沒有用戶登錄到系統的情況下運行。
2 驅動服務:驅動服務遵循設備驅動協議,它與服務程序類似,但是不與SCM交互。
3 The SCM processes service control notifications in a serial fashion
4 The default security descriptor allows the LocalSystem account, and members of the Administrators and Power Users groups to stop and start services.
2 服務在Win7中的新特性
1 可以注冊一個服務,在一個特定事件發生時啟動或者停止服務。
更新的函數
ChangeServiceConfig
|
Changes the configuration parameters of a service. This function supports managed service accounts and virtual accounts. For more information, see Service Accounts Step-by-Step Guide.
|
ChangeServiceConfig2
|
Changes the optional configuration parameters of a service. This function supports new configuration information levels for processor groups and service trigger events.
|
CreateService
|
Creates a service object and adds it to the specified service control manager database. This function supports managed service accounts and virtual accounts. For more information, see Service Accounts Step-by-Step Guide.
|
HandlerEx
|
An application-defined callback function used with the RegisterServiceCtrlHandlerEx function. This callback function supports new extended control codes for system time changes and service trigger events.
|
QueryServiceConfig2
|
Retrieves the optional configuration parameters of a service. This function supports new configuration information levels for processor groups and service trigger events.
|
SetServiceStatus
|
Updates the service control manager's status information for the calling service. This function supports new extended control codes for system time changes and service trigger events.
|
新的結構
Service Changes for Windows Vista
為了提高性能、可靠性、安全性、可管理性等,在Vista之后,服務提供了很多增強的特性。
Session 0 Isolation
服務總是運行在Session 0,在Vista之前,第一個用戶也是運行在Session0,在Vista之后,第一個用戶運行在Session1,第二個用戶運行在Session2, 等等,這樣用戶程序和服務就始終運行在不同的Session上。Session 0 不支持與用戶交互的進程。這就意味著Service不能向應用程序發送消息,應用程序也不能像Service發送消息。除此之外,Service還不能顯示GUI,如對話框,但是Service可以使用WTSSendMessage 函數在另一個Session中顯示對話框。
Delayed AutoStart 在系統啟動的一小段時間(shortly after)內啟動服務。
Failure Detection and Recovery:如果服務失敗,SCM可以執行失敗action,如重啟服務。
Preshutdown Notifications:是服務有足夠的時間來優雅的關閉。
Restricted Network Acess:
Running with Least Privilage:
關于服務
SCM維護者已安裝的服務和驅動服務的數據庫,并且提供了統一的安全的控制它們的方法。數據庫信息包括每個服務如何被啟動。
下面類型的程序使用SCM提供的函數:
服務程序(Service Program):一個為一個或者多個服務提供可執行代碼的程序。服務程序使用連接到SCM的函數以及發送狀態信息給SCM的函數。
服務配置程序(Service configuration program):一個查詢和修改服務數據庫的程序。服務配置程序使用打開數據庫的函數,在數據庫中安裝和刪除服務,對安裝的服務查詢和修改配置參數,安全參數。服務配置程序管理服務以及驅動服務。
服務控制程序(Service Control Program):一個啟動并控制服務以及驅動服務的程序。服務控制程序使用發送請求到SCM的函數。
Service Control Manager(服務控制管理器)
1 系統啟動時啟動;它是一個RPC (Remote procedure call) 服務器。所以服務配置和服務控制程序可以在遠程機器上管理服務。
提供接口功能:
管理安裝服務的數據庫;
啟動服務(系統啟動時,或者需要時)
枚舉安裝的服務
為運行的服務維護狀態信息
傳輸控制請求(control request)給正在運行的服務
鎖定和解鎖服務數據庫。
Database of installed service
在注冊表中維護著已安裝的服務列表。注冊表如下
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services.
這個鍵值為每一個安裝的服務包含一個子鍵,子鍵的名字就是服務名。
Database又叫作ServiceActive databse或者SCM database。你必須使用SCM提供的函數,而不能直接修改databse,即不能直接修改注冊表。
自動啟動服務
在系統啟動的時候,SCM將啟動所有自啟動的服務以及它們依賴的服務。
啟動順序:
1 按加載啟動組列表中的順序;這個信息保存在ServiceGroupOrder值中,
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control
2 GroupOrderList
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control
3 每個服務的依賴列表
當啟動完成后,系統執行啟動認證程序(boot verification program)根據BootVerificationProgram
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control.
默認情況下,這個值是沒有設置的。你可以提供程序來檢測系統,調用NotifyBootConfigStatus通知SCM,報告boot 狀態。
在成功重啟后,系統會將組冊表復制一份到下面目錄下last-known-good (LKG) configuration
HKEY_LOCAL_MACHINE\SYSTEM\ControlSetXXX\Services
按需啟動服務
當服務啟動之后,SCM執行下列步驟:
獲取存儲在數據庫中的帳戶信息
登錄到服務帳戶
加載用戶配置
在暫停狀態下創建服務
給進程分配一個Logon的token
允許進程執行
Service Record List
由于每個服務實體是從注冊表數據庫中讀取的,因此SCM為每個服務創建了一個Service Record,
一個Service Record包括:
服務名
啟動類型
服務狀態(SERVICE_STATUS結構)
指向依賴服務列表的指針
服務在安裝的時候用戶名和密碼是指定好的。SCM在注冊表中存放用戶名,在Local Security Authority(LSA)中存放密碼。
SCM保存兩份用戶密碼。一個當前密碼和一個備份密碼。在服務第一次安裝的時候使用當前密碼,備份密碼是未初始化的。當用當前密碼運行服務成功后,才會將當前密碼寫入到備份密碼。SCM在收到服務狀態通知后更新服務狀態。
驅動服務的狀態是通過查詢IO系統獲得的,而不是通過狀態通知,這點是與Service不同的。
SCM Handles
SCM支持句柄(Handle)來訪問下面的對象。
已安裝的服務的數據庫:用SCManager object來表示
服務:由一個安裝的服務代表服務對象。
數據庫鎖
Service Programs服務程序
Main函數:
調用StartServiceCtrlDispatcher函數連接到SCM并啟動control dispatcher線程。Control dispatcher線程循環loop,等待在dispatch table中指定的服務的請求。
例子:
void __cdecl _tmain(int argc, TCHAR *argv[])
{
// If command-line parameter is "install", install the service.
// Otherwise, the service is probably being started by the SCM.
if( lstrcmpi( argv[1], TEXT("install")) == 0 )
{
SvcInstall();
return;
}
// TO_DO: Add any additional services for the process to this table.
SERVICE_TABLE_ENTRY DispatchTable[] =
{
{ SVCNAME, (LPSERVICE_MAIN_FUNCTION) SvcMain },
{ NULL, NULL }
};
// This call returns when the service has stopped.
// The process should simply terminate when the call returns.
if (!StartServiceCtrlDispatcher( DispatchTable ))
{
SvcReportEvent(TEXT("StartServiceCtrlDispatcher"));
}
}
ServiceMain函數:
首先調用RegisterServiceCtrlHandler函數來注冊SvcCtrHandler函數作為服務的處理函數,然后開始初始化。
VOID WINAPI SvcMain( DWORD dwArgc, LPTSTR *lpszArgv )
{
// Register the handler function for the service
gSvcStatusHandle = RegisterServiceCtrlHandler(
SVCNAME,
SvcCtrlHandler);
if( !gSvcStatusHandle )
{
SvcReportEvent(TEXT("RegisterServiceCtrlHandler"));
return;
}
// These SERVICE_STATUS members remain as set here
gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
gSvcStatus.dwServiceSpecificExitCode = 0;
// Report initial status to the SCM
ReportSvcStatus( SERVICE_START_PENDING, NO_ERROR, 3000 );
// Perform service-specific initialization and work.
SvcInit( dwArgc, lpszArgv );
}
//
// Purpose:
// The service code
//
// Parameters:
// dwArgc - Number of arguments in the lpszArgv array
// lpszArgv - Array of strings. The first string is the name of
// the service and subsequent strings are passed by the process
// that called the StartService function to start the service.
//
// Return value:
// None
//
VOID SvcInit( DWORD dwArgc, LPTSTR *lpszArgv)
{
// TO_DO: Declare and set any required variables.
// Be sure to periodically call ReportSvcStatus() with
// SERVICE_START_PENDING. If initialization fails, call
// ReportSvcStatus with SERVICE_STOPPED.
// Create an event. The control handler function, SvcCtrlHandler,
// signals this event when it receives the stop control code.
ghSvcStopEvent = CreateEvent(
NULL, // default security attributes
TRUE, // manual reset event
FALSE, // not signaled
NULL); // no name
if ( ghSvcStopEvent == NULL)
{
ReportSvcStatus( SERVICE_STOPPED, NO_ERROR, 0 );
return;
}
// Report running status when initialization is complete.
ReportSvcStatus( SERVICE_RUNNING, NO_ERROR, 0 );
// TO_DO: Perform work until service stops.
while(1)
{
// Check whether to stop the service.
WaitForSingleObject(ghSvcStopEvent, INFINITE);
ReportSvcStatus( SERVICE_STOPPED, NO_ERROR, 0 );
return;
}
}
//
// Purpose:
// Sets the current service status and reports it to the SCM.
//
// Parameters:
// dwCurrentState - The current state (see SERVICE_STATUS)
// dwWin32ExitCode - The system error code
// dwWaitHint - Estimated time for pending operation,
// in milliseconds
//
// Return value:
// None
//
VOID ReportSvcStatus( DWORD dwCurrentState,
DWORD dwWin32ExitCode,
DWORD dwWaitHint)
{
static DWORD dwCheckPoint = 1;
// Fill in the SERVICE_STATUS structure.
gSvcStatus.dwCurrentState = dwCurrentState;
gSvcStatus.dwWin32ExitCode = dwWin32ExitCode;
gSvcStatus.dwWaitHint = dwWaitHint;
if (dwCurrentState == SERVICE_START_PENDING)
gSvcStatus.dwControlsAccepted = 0;
else gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
if ( (dwCurrentState == SERVICE_RUNNING) ||
(dwCurrentState == SERVICE_STOPPED) )
gSvcStatus.dwCheckPoint = 0;
else gSvcStatus.dwCheckPoint = dwCheckPoint++;
// Report the status of the service to the SCM.
SetServiceStatus( gSvcStatusHandle, &gSvcStatus );
}
Control Handler函數:
該函數是由dispatcher thread調用的,它處理在OpCode參數中傳進來的控制碼,然后調用ReportSvcStatus函數來更新服務狀態。當Handler收到控制碼時,只有當收到的控制碼引起服務狀態變化時才報告服務狀態。
VOID WINAPI SvcCtrlHandler( DWORD dwCtrl )
{
// Handle the requested control code.
switch(dwCtrl)
{
case SERVICE_CONTROL_STOP:
ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 0);
// Signal the service to stop.
SetEvent(ghSvcStopEvent);
ReportSvcStatus(gSvcStatus.dwCurrentState, NO_ERROR, 0);
return;
case SERVICE_CONTROL_INTERROGATE:
break;
default:
break;
}
}
Service Configuration Program Tasks服務配置程序的任務
安裝服務
刪除服務
改變服務配置
查詢服務配置
Service Control Program Tasks服務控制程序任務
啟動服務
停止服務
改變一個服務的DACL
Service Functions
The following functions are used or implemented by services.
The following functions are used by programs that control or configure services.
Service Structures
The following structures are used with services: