C++在内核实现线程《C++多线程编程实战》

整个内核就是一个进程. 内核有一个线程表,跟踪该系统中所有的线程.
回收用户级线程: 如果线程管理开销非常小,没必要这样做

要求必须安装WinDDK,驱动程序开发工具包
本示例有2个项目

windows桌面应用程序项目一: KernelThread

  • ThreadApp.h
#include <windows.h>
#include <tchar.h>

#define DRIVER_NAME TEXT( "TestDriver.sys" )
#define DRIVER_SERVICE_NAME TEXT(" TestDriver ")
#define Message(n) MessageBox(0, TEXT(n), \
TEXT("Test Driver Info"), 0)

BOOL StartDriver(LPTSTR szCurrentDriver);
BOOL StopDriver(void);

  • ThreadApp.cpp
#include "ThreadApp.h"

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	LPSTR szCommandLine, int iCmdShow)
{
	StartDriver(DRIVER_NAME);
	ShellAbout(0, DRIVER_SERVICE_NAME, TEXT(""), NULL);
	StopDriver();
	return 0;
}

BOOL StartDriver(LPTSTR szCurrentDriver)
{
	HANDLE hFile = 0;
	DWORD dwReturn = 0;
	SC_HANDLE hSCManager = { 0 };
	SC_HANDLE hService = { 0 };
	SERVICE_STATUS ServiceStatus = { 0 };
	TCHAR szDriverPath[MAX_PATH] = { 0 };
	GetSystemDirectory(szDriverPath, MAX_PATH);
	TCHAR szDriver[MAX_PATH + 1];
#ifdef _UNICODE
	wsprintf(szDriver, L"\\drivers\\%ws", DRIVER_NAME);
#else
	sprintf(szDriver, "\\drivers\\%s", DRIVER_NAME);
#endif
	_tcscat_s(szDriver, (_tcslen(szDriver) + 1) * sizeof(TCHAR),
		szDriver);
	BOOL bSuccess = CopyFile(szCurrentDriver, szDriverPath, FALSE);
	if (FALSE == bSuccess)
	{
		Message("copy driver failed");
		return bSuccess;
	}
	hSCManager = OpenSCManager(NULL, NULL,
		SC_MANAGER_CREATE_SERVICE);
	if (0 == hSCManager)
	{
		Message("open sc manager failed!");
		return FALSE;
	}
	hService = CreateService(hSCManager, DRIVER_SERVICE_NAME,
		DRIVER_SERVICE_NAME, SERVICE_START | DELETE | SERVICE_STOP,
		SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_IGNORE,
		szDriverPath, NULL, NULL, NULL, NULL, NULL);
	if (0 == hService)
	{
		hService = OpenService(hSCManager, DRIVER_SERVICE_NAME,
			SERVICE_START | DELETE | SERVICE_STOP);
		Message("create service failed!");

		Message("open service failed!");
		return FALSE;
	}
	BOOL startSuccess = StartService(hService, 0, NULL);
	if (FALSE == startSuccess)
	{
		Message("start service failed!");
		return startSuccess;
	}
	CloseHandle(hFile);
	return TRUE;
}

BOOL StopDriver(void)
{
	SC_HANDLE hSCManager = { 0 };
	SC_HANDLE hService = { 0 };
	SERVICE_STATUS ServiceStatus = { 0 };
	TCHAR szDriverPath[MAX_PATH] = { 0 };
	GetSystemDirectory(szDriverPath, MAX_PATH);
	TCHAR szDriver[MAX_PATH + 1];
#ifdef _UNICODE
	wsprintf(szDriver, L"\\DRIVERS\\%WS", DRIVER_NAME);
#else
	sprintf(szDriver, "\\drivers\\%s", DRIVER_NAME);
#endif
	_tcscat_s(szDriver, (_tcslen(szDriver) + 1) * sizeof(TCHAR),
		szDriver);
	hSCManager = OpenSCManager(NULL, NULL,
		SC_MANAGER_CREATE_SERVICE);
	if (0 == hSCManager)
	{
		return FALSE;
	}
	hService = OpenService(hSCManager, DRIVER_SERVICE_NAME,
		SERVICE_START | DELETE | SERVICE_STOP);
	if (hService)
	{
		ControlService(hService, SERVICE_CONTROL_STOP,
			&ServiceStatus);
		DeleteService(hService);
		CloseServiceHandle(hService);
		BOOL ifSuccess = DeleteFile(szDriverPath);
		return TRUE;
	}
	return FALSE;
}

控制台项目2: DriverApp

  • DriverApp.h
//每个驱动程序都必须在此头文件中
#include "ntddk.h"

//声明2个主例程
DRIVER_INITIALIZE DriverEntry; //驱动程序入口点
DRIVER_UNLOAD OnUnload; //驱动程序卸载

  • DriverApp.cpp
#include "DriverApp.h"

VOID ThreadStart(PVOID lpStartContext)
{
	PKEVENT pEvent = (PKEVENT)lpStartContext;
	DbgPrint("Hello! I am kernel thread. My ID is %u. Regards..",
		(ULONG)PsGetCurrentThreadId());
	KeSetEvent(pEvent, 0, 0);
	PsTerminateSystemThread(STATUS_SUCCESS);
}

NTSTATUS DriverEntry(PDRIVER_OBJECT theDriverObject, PUNICODE_STRING theRegistryPath)
{
	//确保执行第一天命令之前已经声明了所有变量
	HANDLE hThread = NULL;
	NTSTATUS ntStatus = 0;
	OBJECT_ATTRIBUTES ThreadAttributes;
	KEVENT kEvent = { 0 };
	PETHREAD pThread = 0;
	
	theDriverObject->DriverUnload = OnUnload; //设置卸载例程
	DbgPrint("Entering KERNEL mode..");

	//初始化对象,在创建内核线程之前
	InitializeObjectAttributes(&ThreadAttributes, NULL, OBJ_KERNEL_HANDLE,
		NULL, NULL);

	//内核开发必须消息谨慎,哪怕一丁点的错误都会导致**蓝屏死机**或机器崩溃,所以使用__try - __except块
	__try
	{
		KeInitializeEvent(&kEvent, SynchronizationEvent, 0);
		ntStatus = PsCreateSystemThread(&hThread, GENERIC_ALL, &ThreadAttributes,
			NULL, NULL, (PKSTART_ROUTINE)&ThreadStart, &kEvent);
		if (NT_SUCCESS(ntStatus))
		{
			//与用户空间创建句柄不同.需要在返回时初始化一个触发事件
			//此例程无法使用PsCreateSystemThread返回的句柄
			KeWaitForSingleObject(&kEvent, Executive, KernelMode, FALSE, NULL); 
			
			ZwClose(hThread); //关闭内核句柄和防止内存泄漏
		}
		else
		{
			DbgPrint("Could not create system thread!");
		}
	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{
		DbgPrint("Error while creating system thread!");
	}
	return STATUS_SUCCESS;
}

VOID OnUnload(PDRIVER_OBJECT DriverObject)
{
	DbgPrint("Leaving KERNEL mode..");
}
  • 最后要实现PKSTART_ROUTINE或线程的开始地址,线程的指令从这里开始执行.例如
VOID (__stdcall* KSTART_ROUTINE)(PVOID StartCOntext);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值