有那么一类应用程序,是能够为各种用户(包括本地用户和远程用户)所用的,拥有用户授权级进行管理的能力,并且不论用户是否物理的与正在运行该应用程序的计算机相连都能正常执行,这就是所谓的服务了。

(一)服务的基础知识

Question 1. 什么是服务?它的特征是什么?

 
 在NT/2000中,服务是一类受到操作系统优待的程序。一个服务首先是一个Win32可执行程序,如果要写一个功能完备且强大的服务,需要熟悉动态连
接库(Dlls)、结构异常处理、内存映射文件、虚拟内存、设备I/O、线程及其同步、Unicode以及其他的由WinAPI函数提供的应用接口。当然
本文讨论的只是建立一个可以安装、运行、启动、停止的没有任何其他功能的服务,所以无需上述知识仍可以继续看下去,我会在过程中将理解本文所需要的知识逐
一讲解。

  第二要知道的是一个服务决不需要用户界面。大多数的服务将运行在那些被锁在某些黑暗的,冬暖夏凉的小屋子里的强大的服务器上
面,即使有用户界面一般也没有人可以看到。如果服务提供任何用户界面如消息框,那么用户错过这些消息的可能性就极高了,所以服务程序通常以控制台程序的形
式被编写,进入点函数是main()而不是WinMain()。

  也许有人有疑问:没有用户界面的话,要怎样设置、管理一个服务?怎样
开始、停止它?服务如何发出警告或错误信息、如何报告关于它的执行情况的统计数据?这些问题的答案就是服务能够被远程管理,Windows
NT/2000提供了大量的管理工具,这些工具允许通过网络上的其它计算机对某台机器上面的服务进行管理。比如Windows
2000里面的“控制台”程序(mmc.exe),用它添加“管理单元”就可以管理本机或其他机器上的服务。

Question 2. 服务的安全性…

 
 想要写一个服务,就必须熟悉Win
NT/2000的安全机制,在上述操作系统之中,所有安全都是基于用户的。换句话说――进程、线程、文件、注册表键、信号、事件等等等等都属于一个用户。
当一个进程被产生的时候,它都是执行在一个用户的上下文(context),这个用户帐号可能在本机,也可能在网络中的其他机器上,或者是在一个特殊的账
号:System Account――即系统帐号的上下文

  如果一个进程正在一个用户帐号下执行,那么这个进程就同时拥有这个用户所能
拥有的一切访问权限,不论是在本机还是网络。系统帐号则是一个特殊的账号,它用来标识系统本身,而且运行在这个帐号下的任何进程都拥有系统上的所有访问权
限,但是系统帐号不能在域上使用,无法访问网络资源…

  服务也是Win32可执行程序,它也需要执行在一个context,通常服务都是在系统账号下运行,但是也可以根据情况选择让它运行在一个用户账号下,也就会因此获得相应的访问资源的权限。

Question 3. 服务的三个组成部分

 
 一个服务由三部分组成,第一部分是Service Control Manager(SCM)。每个Windows
NT/2000系统都有一个SCM,SCM存在于Service.exe中,在Windows启动的时候会自动运行,伴随着操作系统的启动和关闭而产生和
终止。这个进程以系统特权运行,并且提供一个统一的、安全的手段去控制服务。它其实是一个RPC
Server,因此我们可以远程安装和管理服务,不过这不在本文讨论的范围之内。SCM包含一个储存着已安装的服务和驱动程序的信息的数据库,通过SCM
可以统一的、安全的管理这些信息,因此一个服务程序的安装过程就是将自身的信息写入这个数据库。

  第二部分就是服务本身。一个服务拥有能从SCM收到信号和命令所必需的的特殊代码,并且能够在处理后将它的状态回传给SCM。

 
 第三部分也就是最后一部分,是一个Service Control
Dispatcher(SCP)。它是一个拥有用户界面,允许用户开始、停止、暂停、继续,并且控制一个或多个安装在计算机上服务的Win32应用程序。
SCP的作用是与SCM通讯,Windows 2000管理工具中的“服务”就是一个典型的SCP。

  在这三个组成部分中,用户最可能去写服务本身,同时也可能不得不写一个与其伴随的客户端程序作为一个SCP去和SCM通讯,本文只讨论去设计和实现一个服务,关于如何去实现一个SCP则在以后的其它文章中介绍。

Question 4. 怎样开始设计服务

  还记得前面我提到服务程序的入口点函数一般都是main()吗?一个服务拥有很重要的三个函数,第一个就是入口点函数,其实用WinMain()作为入口点函数也不是不可以,虽然说服务不应该有用户界面,但是其实存在很少的几个例外,这就是下面图中的选项存在的原因。

  由于要和用户桌面进行信息交互,服务程序有时会以WinMain()作为入口点函数。

 
 入口函数负责初始化整个进程,由这个进程中的主线程来执行。这意味着它应用于这个可执行文件中的所有服务。要知道,一个可执行文件中能够包含多个服务以
使得执行更加有效。主进程通知SCM在可执行文件中含有几个服务,并且给出每一个服务的ServiceMain回调(Call
Back)函数的地址。一旦在可执行文件内的所有服务都已经停止运行,主线程就在进程终止前对整个进程进行清除。

  第二个很重要的函数就是ServiceMain,我看过一些例子程序里面对自己的服务的进入点函数都固定命名为ServiceMain,其实并没有规定过一定要那样命名,任何的函数只要符合下列的形式都可以作为服务的进入点函数。

VOID WINAPI ServiceMain(
  DWORD dwArgc, // 参数个数
  LPTSTR *lpszArgv // 参数串
);

 
 这个函数由操作系统调用,并执行能完成服务的代码。一个专用的线程执行每一个服务的ServiceMain函数,注意是服务而不是服务程序,这是因为每
个服务也都拥有与自己唯一对应的ServiceMain函数,关于这一点可以用“管理工具”里的“服务”去察看Win2000里面自带的服务,就会发现其
实很多服务都是由service.exe单独提供的。当主线程调用Win32函数StartServiceCtrlDispatcher的时候,SCM为
这个进程中的每一个服务产生一个线程。这些线程中的每一个都和它的相应的服务的ServiceMain函数一起执行,这就是服务总是多线程的原因――一个
仅有一个服务的可执行文件将有一个主线程,其它的线程执行服务本身。

  第三个也就是最后的一个重要函数是CtrlHandler,它必须拥有下面的原型:

VOID WINAPI CtrlHandler(
DWORD fdwControl //控制命令
)

 
 像ServiceMain一样,CtrlHandler也是一个回调函数,用户必须为它的服务程序中每一个服务写一个单独的CtrlHandler函
数,因此如果有一个程序含有两个服务,那么它至少要拥有5个不同的函数:作为入口点的main()或WinMain(),用于第一个服务的
ServiceMain函数和CtrlHandler函数,以及用于第二个服务的ServiceMain函数和CtrlHandler函数。

 
 SCM调用一个服务的CtrlHandler函数去改变这个服务的状态。例如,当某个管理员用管理工具里的“服务”尝试停止你的服务的时候,你的服务的
CtrlHandler函数将收到一个SERVICE_CONTROL_STOP通知。CtrlHandler函数负责执行停止服务所需的一切代码。由于
是进程的主线程执行所有的CtrlHandler函数,因而必须尽量优化你的CtrlHandler函数的代码,使它运行起来足够快,以便相同进程中的其
它服务的CtrlHandler函数能在适当的时间内收到属于它们的通知。而且基于上述原因,你的CtrlHandler函数必须要能够将想要传达的状态
送到服务线程,这个传递过程没有固定的方法,完全取决于你的服务的用途。

本文测试环境为Win2000 Server + SP2
Athlon XP 1700 + 256MB DDR
全部资料参考自MSDN OCT 2001

[转载]Windows服务编写原理及探讨(1)的更多相关文章

  1. [转载]Windows服务编写原理及探讨(4)

    (四)一些问题的讨论 前面几章的内容都是服务的一些通用的编写原理,但里面隐含着一些问题,编写简单的服务时看不出来,但遇到复杂的应用就会出现一些问题,所以本章就是用来分析.解决这些问题的,适用于高级应用 ...

  2. [转载]Windows服务编写原理及探讨(3)

    (三)对服务的深入讨论之下 现在我们还剩下一个函数可以在细节上讨论,那就是服务的CtrlHandler函数. 当调用RegisterServiceCtrlHandler函数时,SCM得到并保存这个回调 ...

  3. [转载]Windows服务编写原理及探讨(2)

    (二)对服务的深入讨论之上 上一章其实只是概括性的介绍,下面开始才是真正的细节所在.在进入点函数里面要完成ServiceMain的初始化,准确点说是初始化一个 SERVICE_TABLE_ENTRY结 ...

  4. C# windows 服务编写及安装

      最近项目中用到window服务程序,以前没接触过,比较陌生,花了两天的时间学习了下,写了个简单的服务,但在制作安装程序的时候,参照网上很多资料,却都制作不成功,可能是开发环境或项目配置的不同,这里 ...

  5. windows服务编写和“以管理员运行”程序的方法

    本文将首先解释如何 创建 一个定期查询可用物理内存并将结果写入某个文本文件的服务.然后指导你完成生成,安装和实现服务的整个过程. 第一步:主函数和全局定义 首先,包含所需的头文件.例子要调用 Win3 ...

  6. C#开发Windows服务 附简单实例实现禁止QQ运行

    本实例主要实现下面三个基本功能 1.C#开发windows服务 2.禁止QQ等程序运行 3.为windows服务创建自动安装程序 下面针对这三个基本功能进行实现 一.C#开发windows服务 Win ...

  7. C#曲线分析平台的制作(六,Sqldependency+Signalr+windows 服务)

    在经过五天的学习和资料收集后,终于初步实现了利用sqldependency进行数据库变化监控,signalr进行前后台交互,数据实时更新.下面将源代码贴出进行初步分析: 1.系统整体框架构成: 2.具 ...

  8. 玩转Windows服务系列——Debug、Release版本的注册和卸载,及其原理

    Windows服务Debug版本 注册 Services.exe -regserver 卸载 Services.exe -unregserver Windows服务Release版本 注册 Servi ...

  9. 玩转Windows服务系列——Debug、Release版本的注册和卸载,及其原理

    原文:玩转Windows服务系列——Debug.Release版本的注册和卸载,及其原理 Windows服务Debug版本 注册 Services.exe -regserver 卸载 Services ...

随机推荐

  1. 【bzoj5133】[CodePlus2017年12月]白金元首与独舞 并查集+矩阵树定理

    题目描述 给定一个 $n\times m$ 的方格图,每个格子有 ↑.↓.←.→,表示从该格子能够走到相邻的哪个格子.有一些格子是空着的,需要填上四者之一,需要满足:最终的方格图中,从任意一个位置出发 ...

  2. C++解析(11):对象的构造

    0.目录 1.对象的初始化 2.构造函数 3.无参构造函数与拷贝构造函数 4.小结 1.对象的初始化 对象中成员变量的初始值是多少? 下面的类定义中成员变量i和j的初始值是什么? 从程序设计的角度,对 ...

  3. [HDU5677]ztr loves substring

    ztr loves substring Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Othe ...

  4. 使用StoryBoard执行动画

    在WPF动画编程中,最常用的动画处理方式是DoubleAnimation动画,但是随着你的开发经验越来越多,你会发现,有时候使用这个动画类会很麻烦,因为这个动画是封闭动画,也就是说在动画的时间间隔内, ...

  5. Hbase(三) hbase协处理器与二级索引

    一.协处理器—Coprocessor 1. 起源Hbase 作为列族数据库最经常被人诟病的特性包括:无法轻易建立“二级索引”,难以执 行求和.计数.排序等操作.比如,在旧版本的(<0.92)Hb ...

  6. bzoj3007: 拯救小云公主(二分+并查集)

    挺水的题...好多题解说是对偶图,其实感觉不能算严格意义上的对偶图吧QAQ 先二分答案r,然后以boss为中心半径为r的圆不能走,求能否从左下走到右上. 不能从左下走到右上,说明这堆圆把图隔开了,于是 ...

  7. yd的拔钉子之路之 POI 2017

    写在前面的一些话 如果我NOIP没退役,这大概会写成一个系列吧,所以这算是系列的开始,要写一些奇怪的东西? 首先解释下什么叫“拔钉子”,其实就是在钉子上做题嘛......至于钉子具体是个什么东西就当面 ...

  8. HDU 4372 Count the Buildings——第一类斯特林数

    题目大意:n幢楼,从左边能看见f幢楼,右边能看见b幢楼 楼高是1~n的排列. 问楼的可能情况 把握看到楼的本质! 最高的一定能看见! 计数问题要向组合数学或者dp靠拢.但是这个题询问又很多,难以dp ...

  9. 《剑指offer》— JavaScript(14)链表中倒数第k个结点

    链表中倒数第k个结点 题目描述 输入一个链表,输出该链表中倒数第k个结点. 思路 两个指针,先让第一个指针和第二个指针都指向头结点,然后再让第一个指正走(k-1)步,到达第k个节点: 然后两个指针同时 ...

  10. 随机抽样一致性算法(RANSAC)转载

    这两天看<计算机视觉中的多视图几何>人都看蒙了,转载一些干货看看 转自王先荣 http://www.cnblogs.com/xrwang/archive/2011/03/09/ransac ...