如何将用户态24小时倒计时线程迁移至内核态后台运行?
将用户态24小时倒计时迁移至内核空间的实现方案
原始用户态代码
用户提供的用户态倒计时实现代码如下:
const int SECONDS_IN_24_HOURS = 24 * 60 * 60; DWORD WINAPI TimerThreadFunction(LPVOID lpParam) { for (int i = 0; i < SECONDS_IN_24_HOURS; ++i) { double currentTime = MyTimer(); std::cout << "Thread " << GetCurrentThreadId() << " countdown at: " << i + 1 << " seconds, Current time: " << currentTime << " seconds\n"; std::this_thread::sleep_for(std::chrono::seconds(1)); } std::cout << "---------------- 24 hours have passed! ----------------\n"; return 0; } int main() { HANDLE hThread; DWORD dwThreadId; // Create a thread to run the timer function hThread = CreateThread( NULL, // default security attributes 0, // default stack size TimerThreadFunction, // thread function NULL, // parameter to thread function 0, // default creation flags &dwThreadId // returns the thread identifier ); if (hThread == NULL) { return 1; } std::cout << "Thread created successfully with ID: " << dwThreadId << std::endl; SetThreadAffinityMask(hThread, 1 << 0); WaitForSingleObject(hThread, INFINITE); CloseHandle(hThread); return 0; }
内核态实现思路与代码
内核空间无法直接使用用户态API(如CreateThread、std::cout),必须替换为内核专属机制,以下是两种可行实现方案:
方案1:系统线程+逐秒休眠(与用户态逻辑对齐)
通过创建内核系统线程,配合KeDelayExecutionThread实现逐秒倒计时,适合需要实时输出进度的场景:
#include <ntddk.h> #define SECONDS_IN_24_HOURS (24 * 60 * 60) // 内核系统线程函数 VOID TimerSystemThread(PVOID Context) { UNREFERENCED_PARAMETER(Context); HANDLE threadHandle = NULL; NTSTATUS status = PsGetCurrentThread(&threadHandle); // 设置线程亲和性到CPU 0 KAFFINITY affinityMask = 1 << 0; status = KeSetSystemThreadAffinityEx(threadHandle, affinityMask); if (!NT_SUCCESS(status)) { DbgPrint("Failed to set thread affinity: 0x%X\n", status); } // 24小时倒计时循环 for (ULONG i = 0; i < SECONDS_IN_24_HOURS; ++i) { // 获取当前系统时间(转换为秒) LARGE_INTEGER currentTime; KeQuerySystemTime(¤tTime); double seconds = (double)currentTime.QuadPart / 10000000.0; // 输出到调试器 DbgPrint("Kernel Thread %lu countdown at: %lu seconds, Current time: %.2f seconds\n", PsGetCurrentThreadId(), i + 1, seconds); // 休眠1秒(负数值表示相对时间,1秒=10^7个100纳秒单位) LARGE_INTEGER delay; delay.QuadPart = -10000000LL; KeDelayExecutionThread(KernelMode, FALSE, &delay); } DbgPrint("---------------- 24 hours have passed! ----------------\n"); // 终止内核线程 PsTerminateSystemThread(STATUS_SUCCESS); } // 驱动入口函数 NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) { UNREFERENCED_PARAMETER(RegistryPath); HANDLE threadHandle = NULL; NTSTATUS status; // 创建系统线程 status = PsCreateSystemThread( &threadHandle, THREAD_ALL_ACCESS, NULL, NULL, NULL, TimerSystemThread, NULL ); if (!NT_SUCCESS(status)) { DbgPrint("Failed to create system thread: 0x%X\n", status); return status; } DbgPrint("Kernel thread created successfully with ID: %lu\n", PsGetCurrentThreadId()); // 关闭线程句柄(内核线程会独立运行) ZwClose(threadHandle); // 设置驱动卸载回调 DriverObject->DriverUnload = [](PDRIVER_OBJECT DriverObject) { UNREFERENCED_PARAMETER(DriverObject); DbgPrint("Timer driver unloaded\n"); }; return STATUS_SUCCESS; }
方案2:KTIMER+DPC(高效长定时)
如果不需要逐秒输出进度,使用内核定时器KTIMER结合延迟过程调用DPC更节省系统资源,无需持续占用线程:
#include <ntddk.h> #define SECONDS_IN_24_HOURS (24 * 60 * 60) KTIMER g_countdownTimer; KDPC g_countdownDpc; // DPC回调函数:定时结束时执行 VOID CountdownDpcRoutine(PKDPC Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2) { UNREFERENCED_PARAMETER(Dpc); UNREFERENCED_PARAMETER(DeferredContext); UNREFERENCED_PARAMETER(SystemArgument1); UNREFERENCED_PARAMETER(SystemArgument2); DbgPrint("---------------- 24 hours have passed! ----------------\n"); } // 驱动入口函数 NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) { UNREFERENCED_PARAMETER(RegistryPath); // 初始化定时器和DPC KeInitializeTimer(&g_countdownTimer); KeInitializeDpc(&g_countdownDpc, CountdownDpcRoutine, NULL); // 设置24小时后触发定时器 LARGE_INTEGER delay; delay.QuadPart = -SECONDS_IN_24_HOURS * 10000000LL; // 负数值表示相对时间 KeSetTimerEx(&g_countdownTimer, delay, 0, &g_countdownDpc); DbgPrint("24-hour countdown timer started\n"); // 设置驱动卸载回调 DriverObject->DriverUnload = [](PDRIVER_OBJECT DriverObject) { UNREFERENCED_PARAMETER(DriverObject); // 取消定时器 KeCancelTimer(&g_countdownTimer); DbgPrint("Timer driver unloaded\n"); }; return STATUS_SUCCESS; }
关键注意事项
- 内核驱动需使用Windows Driver Kit(WDK)编译,测试环境需开启测试签名模式
- 内核中无控制台输出,
DbgPrint的内容需通过WinDbg等调试工具查看 - 内核线程禁止调用用户态C++标准库,必须使用内核原生API
- 驱动卸载时需清理定时器或线程资源,避免内存泄漏或系统不稳定
内容的提问来源于stack exchange,提问作者eden sson
相关产品推荐
相关产品推荐

