CD Code Digest Hub /CS:GO

专用服务器启动链(srcds)

10 分钟阅读 8 个章节 1 张图

专用服务器复用客户端的引擎与 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 版先 dlopen tier0、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. 专用服务器特有的帧行为#

行为说明证据
帧率锁到 tickFilterTime 在专用服务器(非基准模式)上把最小帧时间设为 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 的专用服务器路径未分析。