专用服务器启动链(srcds)
专用服务器复用客户端的引擎与 AppSystem 机制,但入口、模块表、帧驱动方式不同:它没有窗口消息泵驱动的 MainLoop,而是由 dedicated.dll 主动循环调用引擎的 RunFrame。
相关页面:客户端启动链 · 接口工厂与 AppSystem · 主循环与 Tick
相关源码文件#
dedicated_main/main.cpp:srcds.exe入口dedicated/sys_windows.cpp、dedicated/sys_linux.cpp:平台DedicatedMain与模块表dedicated/sys_ded.cpp:通用main、CDedicatedAppSystemGroup、服务器循环dedicated/sys_common.cpp、dedicated/sys_subproc.cpp:RunServer导出与 Linux 多进程engine/sys_dll2.cpp:CDedicatedServerAPI
1. 时序#
2. 入口与模块表#
srcds.exe的 Windows 入口加载bin\dedicated并调用DedicatedMain;POSIX 版先dlopentier0、vstdlib 再加载 dedicated:dedicated_main/main.cpp:73-113、dedicated_main/main.cpp:121-162。- Windows 的
DedicatedMain建立命令行并在 SE translator 保护下调用通用main:dedicated/sys_windows.cpp:372-400。 - 通用
main构造CDedicatedAppSystemGroup并由CDedicatedSteamApplication运行:dedicated/sys_ded.cpp:599、dedicated/sys_ded.cpp:650-652。后者与客户端版本的区别是文件系统直接用静态链接的FileSystemFactory(dedicated 内联了文件系统代码):dedicated/sys_ded.cpp:551-582。 CDedicatedAppSystemGroup::Create先把 dedicated 自身的导出接口加入组,再调用平台LoadModules:dedicated/sys_ded.cpp:317-331。Windows 模块表包含 engine、soundemittersystem、inputsystem、materialsystem、studiorender、vphysics、datacache、vgui2、vscript,并强制shaderapiempty.dll:dedicated/sys_windows.cpp:264-294;Linux 版同理:dedicated/sys_linux.cpp:270-292。
没有图形输出并不意味着不需要渲染相关模块:材质系统、studiorender、datacache 仍然被加载,以支持模型与碰撞数据(推断,依据是模块表本身)。
3. PreInit 与 Main#
PreInit 设置 Steam 环境、挂载内容、调用 NET_Init、按 -game 载入 gameinfo 搜索路径,并决定使用 VGUI 界面还是文本控制台(Linux 只有文本控制台):dedicated/sys_ded.cpp:333-392。
Main 启动控制台或 VGUI;Windows -steam 文本模式下还会读取 gameinfo 的 SteamAppId 挂载依赖;最后把 -game、-defaultgamedir、父组等信息打包成 ModInfo_t 调用 engine->ModInit:dedicated/sys_ded.cpp:394-453。
观察:
main在运行应用前注册了一个 gameinfo 目录建议函数,它固定返回"left4dead":dedicated/sys_ded.cpp:584-588、dedicated/sys_ded.cpp:649。这是从其它产品遗留的代码,但在正常启动中不会生效:LocateGameInfoFile只有在命令行既没有-vproject也没有-game、且不是 Steam 文件系统(m_bNoGameInfo为假)时才会询问该建议函数,public/filesystem_init.cpp:481-484、public/filesystem_init.cpp:1063-1127;专用服务器把m_bNoGameInfo设为IsSteam():dedicated/sys_ded.cpp:346-348。即使走到这一步,找不到left4dead/gameinfo.txt也只会继续回退到VPROJECT环境变量和当前目录自动探测:public/filesystem_init.cpp:1129-1150。所以带-game csgo启动时它没有影响。
4. 引擎侧:CDedicatedServerAPI#
- 引擎通过
EXPOSE_SINGLE_INTERFACE( CDedicatedServerAPI, IDedicatedServerAPI, VENGINE_HLDS_API_VERSION )暴露专用服务器接口:engine/sys_dll2.cpp:2558。 ModInit标记专用服务器、配置 breakpad、挂载兼容 VPK 与白名单跟踪、初始化材质系统 mod 状态,然后创建CModAppSystemGroup( true, … )并Run():engine/sys_dll2.cpp:2751-2863。CModAppSystemGroup::Create在纯服务器模式下加载matchmaking_ds,跳过 client.dll:engine/sys_dll2.cpp:2190-2193、engine/sys_dll2.cpp:2240-2259。Main的纯服务器分支:eng->Load(true, …)后把帧循环交给dedicated->RunServer(),返回后SV_ShutdownGameDLL:engine/sys_dll2.cpp:2372-2397。
5. 服务器循环#
CDedicatedExports::RunServer:Linux 上支持-fork N创建 N 个子进程实例,否则直接调用::RunServer;Windows 先把命令行中的##替换为实例号:dedicated/sys_common.cpp:144-207、dedicated/sys_subproc.cpp:750-761。RunServer先连跑两帧让引擎加载资源,然后循环RunServerIteration:dedicated/sys_ded.cpp:230-277。- 每次迭代:Windows 处理消息、VGUI 或每 5 帧处理一次控制台输入,然后
engine->RunFrame():dedicated/sys_ded.cpp:156-223。 CDedicatedServerAPI::RunFrame只在未退出时调用eng->Frame():engine/sys_dll2.cpp:2885-2896。
6. 专用服务器特有的帧行为#
| 行为 | 说明 | 证据 |
|---|---|---|
| 帧率锁到 tick | FilterTime 在专用服务器(非基准模式)上把最小帧时间设为 host_nexttick,未到下一个 tick 就睡眠 | engine/sys_engine.cpp:264-271、engine/sys_engine.cpp:477-499 |
| 时钟倒退保护 | dt < 0 时直接按下一个 tick 计算 | engine/sys_engine.cpp:443-451 |
| 看门狗 | State_Run 前后开启/关闭 watchdog(首帧放宽到 30 秒) | engine/host_state.cpp:603-613 |
| 休眠 | 无人时进入休眠,SV_Think 只等待网络消息而不调用 server.dll 的帧 | engine/sv_main.cpp:3331-3348 |
| 创意工坊地图 | 下载挂起完成后切换到多人换图状态 | engine/host_state.cpp:615-620 |
约束与边界#
dedicated组要求的vphysics、IVP/Havana 物理库、gcsdk、server_valve、steamdatagramlib等工程文件在仓库中缺失(见 构建与物理组织),因此这条启动链在本仓库内无法闭环构建(推断)。- 本页只核对了 Windows 与 Linux 的模块表;OSX 的专用服务器路径未分析。