服务启动过程

来源:互联网 发布:淘宝网首页唯品会 编辑:程序博客网 时间:2024/05/19 00:39

我的理解:服务启动过程可以通过几个有阶段性的函数来进行了解。

一  StartServiceCtrlDispatcher函数

当SCM启动一个服务进程时,该进程立即调用StartServiceCtrlDispatcher函数。该函数接收一个入口点列表,每个入口点列表对应于该进程中的一个服务。每个入口点是由它所对应的服务的名称来标识的。例如下面的代码:

 SERVICE_TABLE_ENTRY DispatchTable[] =
    {
        { SVCNAME, (LPSERVICE_MAIN_FUNCTION) SvcMain },
        { NULL, NULL }
    };
   StartServiceCtrlDispatcher( DispatchTable );

SERVICE_TABLE_ENTRY的定义如下:

typedef struct _SERVICE_TABLE_ENTRY {
  LPTSTR lpServiceName;//服务的名称
  LPSERVICE_MAIN_FUNCTION lpServiceProc;//该服务对应的服务入口点
} SERVICE_TABLE_ENTRY,  *LPSERVICE_TABLE_ENTRY;

DispatchTable即是这里所说的入口点列表。现在我还不知道当有两个或者两个以上的服务时,StartServiceCtrlDispatcher函数是如何确定本次该执行哪个服务的。应该是通过服务的名字,只是我没有看到有传一个服务名字给StartServiceCtrlDispatcher函数。如果您知道,恳请指点一下,非常感谢。

 

StartServiceCtrlDispatcher创建了一个命名管道来跟SCM进行通信,在建立了该通信管道以后,它进入一个循环,等待SCM通过该管道发送过来的命令。每次SCM启动一个属于该进程的服务时,它发送一个“服务启动”命令。StartServiceCtrlDispatcher一直在等待来自SCM的命令,只有当该进程的所有服务都停止时它才会将控制返回至该进程的main函数,以便服务进程在退出以前做一些资源清理工作。

 

二 ServiceMain函数

 

ServiceMain函数就是上面提到的服务入口点,即SERVICE_TABLE_ENTRY结构体中第二成员所保存的对象。上面提到的“StartServiceCtrlDispatcher函数接收一个入口点列表”,这个入口点列表中每一个表项都保存有一个ServiceMain函数对应的指针(这样说应该不准确,反正类似于回调函数),调用该地址即调用ServiceMain函数。这样ServiceMain函数就被调用了。

 

ServiceMain函数的第一个动作时调用RegisterServiceCtrlHandler函数。此函数接收一个指向服务控制处理器函数的指针(MSDN中这样描述此指针指向的函数:

An application-defined callback function used with the RegisterServiceCtrlHandler function. A service program can use it as the control handler function of a particular service.)

这个服务控制处理器函数原型如下:

VOID WINAPI Handler(
  [in]                 DWORD fdwControl
);

一个服务实现Handler函数以便处理各种来自SCM的命令。RegisterServiceCtrlHandler函数并不与SCM通信,但它为StartServiceCtrlDispatcher函数将此函数存储在本地进程内存中。服务入口点继续初始化该服务,包括分配内存、创建通信端点,以及从注册表中读入私有配置数据。大多数服务都遵从一个惯例:将服务的参数保存在其服务注册表键下的名为Parameters的子键下面。在入口点初始化该服务的过程中,它可能会利用SetServiceStatus函数来定期地给SCM发送状态消息,以便告诉SCM该服务的启动过程正在如何进行。当入口点完成了初始化以后,服务线程通常进入一个循环,等待来自客户应用的请求。例如,Web服务器会初始化一个TCP监听套接字,等待进来的HTTP连接请求。

 


 

 

 

 

 

 

 

原创粉丝点击