读懂源码系列-FileZilla Server 设计原则分析-入口分析(2)
来源:互联网 发布:我友网络 编辑:程序博客网 时间:2024/06/15 21:00
1.预备知识
FileZilla Server ftp 服务器是作为 Windows 服务运行的。我们来看下安装好的服务,通过 Win + R,输入 services.msc 找到 FileZilla Server FTP server:
可以看到名为 FileZilla Server 的服务,指向了新编译生成的 *\Debug\FileZilla Server.exe 可执行文件。如果点击启动,那么 FTP 服务器就会正式运行。
Windows 操作系统不但提供了 services.msc 服务管理界面,而且还提供了 sc.exe 命令行工具,使得我们可以安装、删除、启动、停止和配置服务。
此外,还有如下 API 接口,可以完成上述功能:
OpenSCManager
CreateService
DeleteService
OpenService
StartService
ControlService
2.入口分析
FileZilla Server 项目源码,把 Windows 服务管理功能和 FTP 服务器本身功能结合在一起了。
首先,找到包含 WinMain 函数的文件 Service.cpp。入口函数可以分为两个部分:
1.根据命令行选项,完成自身的安装、删除、启动、停止和配置服务;
2.作为服务程序入口 等待 StartServiceCtrlDispatcher 函数返回;
注意 StartServiceCtrlDispatcher 这个函数,使得当前调用进程与服务控制管理器(SCM)进程 services.exe 建立连接,并使调用进程的主线程成为服务控制派遣线程,服务控制派遣线程之后将处理 SCM 发送的服务控制请求,直到所有服务都停止,派遣线程才返回。
接下来看以下代码段:
const SERVICE_TABLE_ENTRY servicetable[] ={{ServiceName,(LPSERVICE_MAIN_FUNCTION)ServiceMain},{NULL,NULL}};BOOL success;success = StartServiceCtrlDispatcher(servicetable);
SERVICE_TABLE_ENTRY 可以指定服务进程的服务名和服务入口,对于每一个服务入口,都会新建一个线程,用于执行服务入口。本服务只有一个入口,就是 ServiceMain。因此,主线程调用 StartServiceCtrlDispatcher 函数后,服务进程有两个线程:
1.主线程,进入 StartServiceCtrlDispatcher ,并且在之后处理 SCM 的控制命令;
2.新建服务线程,执行 ServiceMain;
根据以上分析,执行流程就进入了 ServiceMain 函数:
1.注册 SCM 控制命令处理函数 ServiceCtrlHandler ,这个函数由主线程执行,可以处理服务停止等 SCM命令;
void ServiceCtrlHandler(DWORD nControlCode){BOOL success;switch (nControlCode) {case SERVICE_CONTROL_SHUTDOWN:case SERVICE_CONTROL_STOP:nServiceCurrentStatus = SERVICE_STOP_PENDING;success = UpdateServiceStatus(SERVICE_STOP_PENDING, NO_ERROR, 0, 1, 3000);KillService();return;case 128:SendReloadConfig();break;default:break;}UpdateServiceStatus(nServiceCurrentStatus, NO_ERROR, 0, 0, 0);}2.新建线程 ServiceExecutionThread ,作为 FTP 服务器的主线程;
DWORD ServiceExecutionThread(LPDWORD param){// initialize Winsock libraryBOOL res = TRUE;WSADATA wsaData;WORD wVersionRequested = MAKEWORD(2, 2);int nResult = WSAStartup(wVersionRequested, &wsaData);if (nResult != 0)res = FALSE;else if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {WSACleanup();res = FALSE;}if (!res){SetEvent(killServiceEvent);UpdateServiceStatus(SERVICE_STOPPED, NO_ERROR, 0, 0, 0);return 0;}CServer *pServer = new CServer;VERIFY(pServer->Create());if (!nServiceRunning)PostQuitMessage(0);MSG msg;while (GetMessage(&msg, 0, 0, 0)) {TranslateMessage(&msg);DispatchMessage(&msg);}delete pServer;WSACleanup();SetEvent(killServiceEvent);return 0;}可以看到, FTP 主线程,是一个 Windows 消息循环。这个也是我们接下来主要分析的部分。
3.等待服务结束事件
3.结构总结
我们通过忽略所有细节,分析出了 FTP 服务器的整体结构。结构如下:
从外围代码来看,服务程序有3个线程:
1.主线程,直到服务处于停止状态,才从 StartServiceCtrlDispatcher 函数返回,并负责执行 SCM 发送的命令;
2.服务入口线程,执行 ServiceMain函数。函数体里边会等待一个事件,以及等待 FTP 主线执行完毕,才会返回;
3.FTP 主线程,初始化服务器,并进入Windows 消息循环。消息循环结束后,线程结束。
所以,我们对 FTP 服务器的分析,将集中于 FTP主线程部分。
阅读全文
0 0
- 读懂源码系列-FileZilla Server 设计原则分析-入口分析(2)
- 读懂源码系列-FileZilla Server 设计原则分析-编译篇(1)
- 读懂源码系列-FileZilla Server 设计原则分析-socket 事件响应流程(3)
- 读懂源码系列-FileZilla Server 设计原则分析-socket 事件处理流程(4)
- FileZilla Server源码分析(1)
- FileZilla Server源码分析--大漠落日5节
- thinkphp源码分析(1)--- 入口文件
- openstack4j 源码分析(一) 入口
- [FileZilla Client 源码分析二]CCommandQueue类
- ThinkPHP3.1.3源码分析(一) 入口文件分析
- jQuery Sizzle 入口 [ 源码分析 ]
- [java][junit4][源码分析]JUnitCore-入口分析
- Yii设计分析-入口程序
- gallery3d的源码分析——入口2
- Poseidon(MyBatis)源码分析(2-框架初始化入口)
- 第二人生源码分析(3)程序入口点
- Flume 1.7 源码分析(三)程序入口
- FileZilla客户端实现分析
- 深入Kotlin
- 特征经验分享以及管理文件,远程运行的小技巧
- 玩转Python爬虫与信息获取(1)
- WebUploader 设置单个图片上传
- Unity中 www 与Resources 使用区别
- 读懂源码系列-FileZilla Server 设计原则分析-入口分析(2)
- xposed hook 方法 含有自定义类和自定义类数组
- EM(期望最大)算法详解(上)
- php 发送与接收流文件
- 洛谷 P3708 koishi的数学题
- my sql部分重要语句示例
- 大学生该怎么活,才有意义。
- Linux系统安装之前
- 二维数组动态改变下拉菜单内容