Windows NT服务--独立的观点
在windows中,服务是一种特殊的进程,可以说它和用户无关,它的作用不是完成用户任务,而是进行一些管理类的操作或者通用的服务类操作,实际上windows服务就是一个可执行文件,但是远远不只是这些。 Windows NT的服务架构非常复杂,是整个系统架构中独立的一块。windows服务执行的往往都是一些无须用户介入的任务,也就是说它执行的任务不是具体的,而是具有支撑性质的,比较底层的,比如网络登录,文件驱动,设备驱动,ftp等等,其他的进程往往就和登录用户密切相关了,毕竟计算机就是让用户使用的,而其上执行的任务也就是用户要求的,因此用户是windows进程一个很重要的属性,同时也是操作系统本身一个很重要的性质,可以实现安全管理等相关操作。 windows服务主要由三部分组成,一是服务本身;二是服务控制管理器(SCM);三是服务控制程序(SCP)。SCM是个管理中心,管理着所有的线上服务,所谓线上服务就是已经安装的服务,SCP和SCM交互来管理服务本身,注意服务本身并不需要直接和SCM交互,这样就可以让写一个服务变得更加容易,人们可以像写普通的应用程序一样来完成一个服务的编程,唯一需要附加的就是和SCP接口就可以了,这样看来虽然windows服务的架构非常复杂,但是三者之间的耦合度却很低,足见设计的精妙。SCM维护着一个数据库,该数据库储存着已安装的服务和驱动程序的信息,SCM管理着它们,SCM根据这些信息控制服务的关闭和启动等行为,服务可以从SCM接收命令然后采取一定的动作,注意它是通过SCP来接收命令的,服务本身就是一个一直运行的应用程序,SCP作为一个 接口提供出来,用户可以通过它控制服务的行为,SCM同时也和SCP交互,在这繁复的数据流背后是成熟的RPC,windows中信号是不流行的,但是RPC却非常普遍,下面通过一个简单例子说明一下枝枝蔓蔓: #include "stdafx.h" #include.h> void Install(char * name); void Uninstall(char *name); char *a = "mee11"; BOOL Running = TRUE; SERVICE_STATUS_HANDLE hServiceStatus; SERVICE_STATUS status; SC_HANDLE hSCM; int option(int argc, TCHAR* argv[]) { hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); if (argc <= 1) return 0; if (_wcsicmp(argv[1], _T("-i")) == 0) { Install(a); ::CloseServiceHandle(hSCM); return 1; } if (_wcsicmp(argv[1], _T("-u")) == 0) { Uninstall(a); return 1; } return 0; } void Install(char *name ) //安装服务,实际上就是将该新服务的信息写入SCM管理的数据库中 { if (!hSCM) return 0; char szFilePath[260]; ::GetModuleFileNameA(NULL, szFilePath, sizeof(szFilePath)); SC_HANDLE hService = ::CreateServiceA(hSCM,(LPCSTR)name,(LPCSTR)name,SERVICE_ALL_ACCESS,SERVICE_WIN32_OWN_PROCESS,SERVICE_DEMAND_START,SERVICE_ERROR_NORMAL,szFilePath,NULL,NULL,NULL,NULL,NULL); if (!hService) { ::CloseServiceHandle(hSCM); return ; } char szKey[256]; HKEY hKey = NULL; strcpy(szKey, "SYSTEM//CurrentControlSet//Services//EventLog//Application//"); strcat(szKey, name); if (::RegCreateKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey) != ERROR_SUCCESS) { ::CloseServiceHandle(hService); ::CloseServiceHandle(hSCM); return; } ::RegSetValueEx(hKey,_T("EventMessageFile"),0,REG_EXPAND_SZ, (CONST BYTE*)szFilePath,strlen(szFilePath) + 1); DWORD dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE; ::RegSetValueEx(hKey,_T("TypesSupported"),0,REG_DWORD,(CONST BYTE*)&dwData,sizeof(DWORD));::RegCloseKey(hKey); ::CloseServiceHandle(hService); } void Uninstall(char *name) { SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); if (!hSCM) return ; SC_HANDLE hService = ::OpenServiceA(hSCM,name,DELETE); if (hService) { if (::DeleteService(hService)) ::CloseServiceHandle(hService); } ::CloseServiceHandle(hSCM); } static void WINAPI Handler(DWORD dwOpcode) { //注意是在这个Handler回调中处理的SCM发来的命令,这里要做的就是设置控制变量,间接改变服务的运行行为。 switch (dwOpcode) { case SERVICE_CONTROL_STOP: status.dwCurrentState = SERVICE_STOP_PENDING; ::SetServiceStatus(hServiceStatus, &status); Running = FALSE; break; default: break; } ::SetServiceStatus(hServiceStatus, &status); } static void WINAPI ServiceMaina(DWORD dwArgc, LPTSTR* lpszArgv) { hServiceStatus = RegisterServiceCtrlHandlerA(a,Handler); ::SetServiceStatus(hServiceStatus, &status); status.dwCurrentState = SERVICE_RUNNING; ::SetServiceStatus(hServiceStatus, &status); while (Running) { //做具体的服务吧,就像这是一个普通的应用程序一样 } status.dwCurrentState = SERVICE_STOP_PENDING; ::SetServiceStatus(hServiceStatus, &status);//最后告诉SCM,这个服务停止了。 } void StartService() { SERVICE_TABLE_ENTRY st[] = { {(LPWSTR)a, ServiceMain},{NULL, NULL}}; status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; status.dwCurrentState = SERVICE_STOPPED; status.dwControlsAccepted = SERVICE_ACCEPT_STOP; status.dwWin32ExitCode = 0; status.dwServiceSpecificExitCode = 0; status.dwCheckPoint = 0; status.dwWaitHint = 0; ::StartServiceCtrlDispatcher(st);//分派器开始,服务即将开始运行 } int _tmain(int argc, _TCHAR* argv[]) { if(!option(argc, argv)) { StartService(); } return 0; } 看到在RegisterServiceCtrlHandlerA中注册的Handler了吧,Handler就相当于一个控制器,这个Handler就是负责接收和处理命令的,它和主服务在不同的线程当中,主服务也就是上面例子中的while循环线程可以旁若无人的做任何事情,控制变量是全局的,可以在别的线程被改变,这个变量控制着服务的关闭行为,一切就是这么简单。关于服务的调试,可以用远程调试的办法进行。 windows专门为服务这个东西设计了如此复杂的机制,看得出服务的重要性,不过也不一定,windows本身就是微核结构而且内部大量使用了C/S架构,它为任何东西单独设计一个机制都不足为奇。它的API相当复杂,之所以这样就使因为windows是面向用户的,而用户是很难缠的,因此其api就提供了很多策略性的东西,当然也就相对复杂,windows服务仅仅是其中的一块而已,不过即使这样,windows的设计者还是做的很不错,程序员几乎不用费力就可以完成一个服务框架,当然如果深入一些,还有更加复杂的,不过那就涉及到一个新机制了,这就是svchost,很熟悉吧,不过不说了,我不喜欢讨论网上一搜一堆的东西,我比较喜欢思想性的东西,最起码还可能遭到一些反驳... 本文转自 dog250 51CTO博客,原文链接:http://blog.51cto.com/dog250/1273461