关于windows service 的一些基础知识

Service 程序是在后台悄悄运行的。我们通过将自己的程序登记为服务,可以使自己的程序不出现在任务管理器中,并且随系统启动而最先运行,随系统关闭而最后停止。 服务控制管理器是一个RPC 服务器,它显露了一组应用编程接口,程序员可以方便的编写程序来配置服务和控制远程服务器中服务程序。

创建一个windows service 的流程基本如下:

  1. 写一个service 程序, 在这里需要注意的是,service 程序和普通的程序是有区别的。 windows service 程序是由windows service manager 管理的(config, create, delete, start, stop, etc…),一个service程序需要能接受并处里来自service manager 的这些请求,才能被service manager启动。

    service manager 启动服务程序后,等待service程序 主线程调用系统函数StartServiceCtrlDispatcher。该函数的主要用于建立 service主线程 和 service manager 的链接。只有建立连接,service才能接收来自service manager 的各种请求,也就是才能被service manager启动。如果service程序未调用StartServiceCtrlDispatcher(),则会显示“服务没有及时响应启动或控制请求。”错误。

    一个SERVICE_WIN32_OWN_PROCESS 类型的服务应该立即调用 StartServiceCtrlDispatcher 函数,可以在服务启动后让服务入口点函数完成初始化工作,但不要超过30秒。否则必须建立另外的线程完成这些共同的初始化工作,从而保证服务程序主函数能及时地调用 StartServiceCtrlDispatcher 函数。

  2. 使用sc create 创建service
    值得注意的是, sc create 只是在windows 注册表 和 service 数据库中 创建了service,并没有做其他的工作。

  3. 使用sc start 或者 net start 开启service。
    如果将service配置为自动启动或为了启动从属服务, windows 在启动过程中,会在启动时自动调用StartService()来开启这个service。

  4. 使用sc failure 配置程序crash 后,重启动作:

$ sc failure msftpsvc reset= 30 actions=restart/5000
# reset 多久没有失败后,失败计算器清0
#actions=restart/5000,程序crash 5s后, 重启service 

下面介绍下service 的启动流程

  1. 某些进程必须调用StartService()来告知service manager应该启动该服务。这可能是Windows本身(如果将服务配置为自动启动或为了启动从属服务),或者可能是服务管理工具,net start命令或应用程序。
    无论哪个进程调用StartService都可以为service设置参数。这些参数最终将传递给ServiceMain()。注意:这些参数永远不会传递给main()。ServiceMain在main 里。
    如果是Windows调用StartService,则不传递任何参数。
  2. 运行服务创建命令,该命令是在创建服务时设置的。这是CreateService()调用的lpBinaryPathName参数,如果您正在使用binpath命令,则也称为sc create。
    如果命令包含命令行参数,则以常规方式将其传递给main()。注意:这些参数永远不会传递给ServiceMain()
  3. 主线程必须调用StartServiceCtrlDispatcher()来运行service控制调度程序,该调度程序提供与service manager进程之间的连接。如果应用程序未调用StartServiceCtrlDispatcher(),则会显示“服务没有及时响应启动或控制请求。”错误。
    service 可以通过调用StartService()设置的参数来调用ServiceMain()。
    ServiceMain()或由它启动的线程然后进行实际工作,包括根据需要向service manager通知服务状态。
    您会注意到有两组不同的参数:

由StartService()设置的参数,这些参数传递给ServiceMain()。
由CreateService()或ChangeServiceConfig()设置的参数,这些参数传递给main()。

这些服务于不同的目的。如果在安装服务时需要配置某些内容,则可以使用main()的参数。如果在启动服务时需要配置某些内容,则可以使用ServiceMain()的参数。或者当然可以两者都做;只是不要让他们感到困惑!

通常,ServiceMain()参数仅由旨在与常规应用程序协同工作并由该应用程序启动的服务使用。

请注意,由于至少两个原因,main()无法通过调用StartService()来更改传递给ServiceMain()的参数:首先,为时已晚,因为已经处理了启动请求,因此已经设置了参数;其次,在服务初始化期间,service manager 数据库被锁定,因此尝试调用StartService()将导致死锁。

(如果Windows提供了某种方式来配置默认参数或覆盖指定的参数,那将是很好的选择。但是,在这种情况下,确实没有任何理由不使用全局变量:应用程序的命令行对于应用程序而言是固有的全局变量因此使用全局变量在哲学上是合理的。)

Nitpickers的一角:实际上,当将服务配置为自动启动或必须启动服务依赖项时,Windows可能不会从字面上调用StartService。 service manager 更有可能调用等效的内部函数。但是结果是一样的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值