转载请注明来源:
enjoy5512的博客 : http://blog.csdn.net/enjoy5512
GitHub : https://github.com/whu-enjoy


.1. 使用系统线程

PsCreateSystemThread

NTSTATUS
PsCreateSystemThread(
_Out_PHANDLE ThreadHandle,
_In_ULONG DesiredAccess, //所需访问权限
_In_opt_POBJECT_ATTRIBUTES ObjectAttributes,
_In_opt_HANDLE ProcessHandle,
_Out_opt_PCLIENT_ID ClientId,
_In_PKSTART_ROUTINE StartRoutine,//线程中要执行的函数
_In_opt_PVOID StartContext//传递给上述要执行的函数的参数
); Parameters
ThreadHandle[out] 线程句柄[输出参数]
指向一个用于接收此句柄的变量。一旦此句柄 不再使用,驱动必须用ZwClose关闭此句柄。此句柄在WindowsVista 及以后版本的Windows系统中是内核句柄。在较早版本的Windows 里,此句柄不可以是内核句柄。 DesiredAccess[in]所需访问权限[输入参数]
指定ACCESS_MASK值用于指明对所创建线程的存取权限要求。 ObjectAttributes[in, optional]对象属性[输入参数,可选]
指向一个结构,它指定对象的属性。OBJ_PERMANENT,OBJ_EXCLUSIVE,和OBJ_OPENIF不是线程对象的有效属性。在Windows XP和更高版本的Windows,如果对方不在系统进程的上下文中运行,它必须为ObjectAttributes设置OBJ_KERNEL_HANDLE属性。对微软的Windows 2000和Windows 98/Me的驱动必须只在系统进程上下文中调用PsCreateSystemThread。对于WindowsVista 及其后版本的WindowsVista,此句柄将是一个内核句柄。 ProcessHandle[in, optional] 进程句柄[输入参数,可选]
指定“在其地址空间中运行线程的那个进程”的一个打开的句柄。调用者的线程必须对这个进程有process_create_thread访问权限。如果不提供此参数,则将在初始系统进程中创建线程。在为一个驱动程序创建的线程里,这个值应该是空的。可使用定义在ntddk.H中的NtCurrentProcess宏,来指定当前进程。 ClientId[out, optional]客户标识[输出参数,可选]
指向用于“接收新线程的客户端标识符”的结构。在为一个驱动程序创建的线程里,这个值应该是空的。 StartRoutine[in]开始例程[输入参数]
新创建的系统线程的入口点。这个参数是一个函数指针,指向能接收一个参数的ThreadStart例程,参数值是由调用者提供的startcontext参数。 StartContext[in, optional]开始语境[输入参数,可选]
当本函数(PsCreateSystemThread)开始执行时,提供一个单独的参数传递给所创建的线程。 返回值
PsCreateSystemThread如果成功创建线程则返回STATUS_SUCCESS.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

2. 线程中睡眠

NTSTATUS KeDelayExecutionThread(
_In_ KPROCESSOR_MODE WaitMode,
_In_ BOOLEAN Alertable,
_In_ PLARGE_INTEGER Interval
); Parameters WaitMode [in]
Specifies the processor mode in which the caller is waiting, which can be either KernelMode or UserMode. Lower-level drivers should specify KernelMode. Alertable [in]
Specifies TRUE if the wait is alertable. Lower-level drivers should specify FALSE. Interval [in]
Specifies the absolute or relative time, in units of 100 nanoseconds, for which the wait is to occur. A negative value indicates relative time. Absolute expiration times track any changes in system time; relative expiration times are not affected by system time changes. Return value
KeDelayExecutionThread returns one of the following values that describes how the delay was completed:
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
Return code Description
STATUS_SUCCESS The delay completed because the specified interval elapsed.
STATUS_ALERTED The delay completed because the thread was alerted.
STATUS_USER_APC A user-mode APC was delivered before the specified Interval expired.

Note that the NT_SUCCESS macro recognizes all of these status values as “success” values.


3. 使用同步事件

VOID
KeInitializeEvent(
IN PRKEVENT Event, // 这个参数是初始化事件对象的指针
IN EVENT_TYPE Type, // 这个参数是事件的类型。一类是“通知事件”对应参数为 NotificationEvent。另一类是“同步事件”,对应参数 SynchronizationEvent
IN BOOLEAN State // TRUE:事件对象初始化状态为激发。FALSE:事件对象初始化状态为未激发
);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
LONG KeSetEvent(
_Inout_ PRKEVENT Event,
_In_ KPRIORITY Increment,
_In_ BOOLEAN Wait
); Parameters Event [in, out]
A pointer to an initialized event object for which the caller provides the storage. Increment [in]
Specifies the priority increment to be applied if setting the event causes a wait to be satisfied. Wait [in]
Specifies whether the call to KeSetEvent is to be followed immediately by a call to one of the KeWaitXxx routines. If TRUE, the KeSetEvent call must be followed by a call to KeWaitForMultipleObjects, KeWaitForMutexObject, or KeWaitForSingleObject. For more information, see the following Remarks section. Return value
If the previous state of the event object was signaled, a nonzero value is returned.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
NTSTATUS KeWaitForSingleObject(
_In_ PVOID Object,
_In_ KWAIT_REASON WaitReason,
_In_ KPROCESSOR_MODE WaitMode,
_In_ BOOLEAN Alertable,
_In_opt_ PLARGE_INTEGER Timeout
); Parameters Object [in]
Pointer to an initialized dispatcher object (event, mutex, semaphore, thread, or timer) for which the caller supplies the storage. WaitReason [in]
Specifies the reason for the wait. A driver should set this value to Executive, unless it is doing work on behalf of a user and is running in the context of a user thread, in which case it should set this value to UserRequest. WaitMode [in]
Specifies whether the caller waits in KernelMode or UserMode. Lowest-level and intermediate drivers should specify KernelMode. If the given Object is a mutex, the caller must specify KernelMode. Alertable [in]
Specifies a Boolean value that is TRUE if the wait is alertable and FALSE otherwise. Timeout [in, optional]
Pointer to a time-out value that specifies the absolute or relative time, in 100-nanosecond units, at which the wait is to be completed.
A positive value specifies an absolute time, relative to January 1, 1601. A negative value specifies an interval relative to the current time. Absolute expiration times track any changes in the system time; relative expiration times are not affected by system time changes.
If *Timeout = 0, the routine returns without waiting. If the caller supplies a NULL pointer, the routine waits indefinitely until the dispatcher object is set to the signaled state. For more information, see the following Remarks section. Return value
KeWaitForSingleObject can return one of the following:
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
Return code Description
STATUS_SUCCESS The dispatcher object specified by the Object parameter satisfied the wait.
STATUS_ALERTED The wait was interrupted to deliver an alert to the calling thread.
STATUS_USER_APC The wait was interrupted to deliver a user asynchronous procedure call (APC) to the calling thread.
STATUS_TIMEOUT A time-out occurred before the object was set to a signaled state. This value can be returned when the specified set of wait conditions cannot be immediately met and Timeout is set to zero.

Note that the NT_SUCCESS macro recognizes all of these status values as “success” values.


4. 示例代码

static KEVENT s_Event

//程序说明开始
//==================================================================================
// 功能 : 测试线程函数
// 参数 :
// (入口)
// (出口) 无
// 返回 : VOID
// 主要思路 :
// 调用举例 :
// 日期 : 2016年7月7日 07:24:03 - 2016年7月7日 07:44:41
//==================================================================================
//程序说明结束
NTSTATUS
Thread()
{
static UNICODE_STRING str = RTL_CONSTANT_STRING(L"test thread");
HANDLE ThreadHandle = NULL;
NTSTATUS Status = STATUS_SUCCESS; KdPrint(("启动线程函数\n"));
//初始化事件
//第二个参数是事件的类型,一类是“通知事件”,对应参数是NotificationEvent。
//另一类是“同步事件”,对应是SynchronizationEvent
//第三个参数如果为真,事件对象的初始化状态为激发状态。
//如果为假,则事件对象的初始化状态为未激发状态
//如果创建的事件对象是“通知事件”,当事件对象变为激发状态时,
//程序员需要手动将其改回未激发
//如果创建的事件对象是“同步事件”,当事件对象为激发状态时,
//如果遇到KeWaitForXXX等内核函数,事件对象则自动变回未激发状态
// 当是TRUE 时初始化事件是有信号状态.,当是FALSE时初始化事件是没信号状态,
//如果此处为TRUE,则为有信号状态,KeWaitForSingleObject会直接通过,
//此时需要调用KeResetEvent来设置为无信号
KeInitializeEvent(&s_Event, SynchronizationEvent, FALSE);
//KeResetEvent(&s_Event);//指定的事件对象设置为无信号状态。 //启动线程
Status = PsCreateSystemThread(
&ThreadHandle,
0,NULL,NULL,NULL,
ThreadProc,
(PVOID)&str);
if (!NT_SUCCESS(Status))
{
DbgPrint("线程启动失败!!-%#X");
return Status;
} //Do Something
KdPrint(("做一些事!!\n")); KdPrint(("线程启动函数结束!!\n"));
ZwClose(ThreadHandle);
KeWaitForSingleObject(&s_Event, Executive, KernelMode, 0, 0);
KdPrint(("线程启动函数返回!!\n"));
return Status;
} //程序说明开始
//==================================================================================
// 功能 : 线程函数
// 参数 :
// (入口)
// (出口) 无
// 返回 : VOID
// 主要思路 :
// 调用举例 :
// 日期 : 2016年7月7日 07:44:29 - 2016年7月7日 08:51:17
//==================================================================================
//程序说明结束
VOID
ThreadProc(__in PVOID Context)
{
PUNICODE_STRING str = (PUNICODE_STRING)Context;
LARGE_INTEGER Interval;
LONG Msec = 3000; //打印字符串
KdPrint(("进入线程函数 : %wZ\n", str)); //Msec若为1000,则 睡眠的时间为: 1000 * 100 ns * 10 *1000 =1s
Interval.QuadPart = DELAY_ONE_MILLISECOND;
Interval.QuadPart *= Msec; GetTime();
GetTime();
KeDelayExecutionThread(KernelMode, 0, &Interval);
GetTime(); KdPrint(("线程函数结束\n"));
//设置事件
KeSetEvent(&s_Event, 0, TRUE);
//结束自己
PsTerminateSystemThread(STATUS_SUCCESS);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • jpg 改 rar 

Windows驱动开发之线程与同步事件的更多相关文章

  1. C++第三十三篇 -- 研究一下Windows驱动开发(一)内部构造介绍

    因为工作原因,需要做一些与网卡有关的测试,其中涉及到了驱动这一块的知识,虽然程序可以运行,但是不搞清楚,心里总是不安,觉得没理解清楚.因此想看一下驱动开发.查了很多资料,看到有人推荐Windows驱动 ...

  2. Windows 驱动开发 - 5

    上篇<Windows 驱动开发 - 4>我们已经完毕了硬件准备. 可是我们还没有详细的数据操作,比如接收读写操作. 在WDF中进行此类操作前须要进行设备的IO控制,已保持数据的完整性. 我 ...

  3. windows 驱动开发入门——驱动中的数据结构

    最近在学习驱动编程方面的内容,在这将自己的一些心得分享出来,供大家参考,与大家共同进步,本人学习驱动主要是通过两本书--<独钓寒江 windows安全编程> 和 <windows驱动 ...

  4. Windows 驱动开发 - 7

    在<Windows 驱动开发 - 5>我们所说的读写操作在本篇实现. 在WDF中实现此功能主要为:EvtIoRead和EvtIoWrite. 首先,在EvtDeviceAdd设置以上两个回 ...

  5. Windows 驱动开发 - 8

    最后的一点开发工作:跟踪驱动. 一.驱动跟踪 1. 包括TMH头文件 #include "step5.tmh" 2. 初始化跟踪 在DriverEntry中初始化. WPP_INI ...

  6. Windows驱动开发-IRP的完成例程

    <Windows驱动开发技术详解 >331页, 在将IRP发送给底层驱动或其他驱动之前,可以对IRP设置一个完成例程,一旦底层驱动将IRP完成后,IRP完成例程立刻被处罚,通过设置完成例程 ...

  7. Windows驱动开发(中间层)

    Windows驱动开发 一.前言 依据<Windows内核安全与驱动开发>及MSDN等网络质料进行学习开发. 二.初步环境 1.下载安装WDK7.1.0(WinDDK\7600.16385 ...

  8. [Windows驱动开发](一)序言

    笔者学习驱动编程是从两本书入门的.它们分别是<寒江独钓——内核安全编程>和<Windows驱动开发技术详解>.两本书分别从不同的角度介绍了驱动程序的制作方法. 在我理解,驱动程 ...

  9. windows驱动开发推荐书籍

    [作者] 猪头三 个人网站 :http://www.x86asm.com/ [序言] 很多人都对驱动开发有兴趣,但往往找不到正确的学习方式.当然这跟驱动开发的本土化资料少有关系.大多学的驱动开发资料都 ...

随机推荐

  1. 在命令行中运行JUnit测试

    可以在Eclipse之外运行JUnit测试,使用org.junit.runner.JUnitCore类. 这个类提供了runClasses()方法,它允许运行一个或多个测试类.runClasses() ...

  2. 异常之交叉编译---arm-vfp-linux-gnu/bin/ld: cgic.o: Relocations in generic ELF (EM: 3)

    /opt/arm-2009q1/bin/../lib/gcc/arm-none-linux-gnueabi/4.3.3/../../../../arm-none-linux-gnueabi/bin/l ...

  3. ASP.NET 网站超时跳转到登录界面

    利用actionFilter过滤器实现,超时跳转到登录界面 /// <summary> /// 登录超时跳转至登录界面 /// </summary> public class ...

  4. Oracle数据库order by排序查询分页比不分页还慢问题解决办法

    简单说下问题,有一个JDBC的查询SQL,分页查询语句中有一个排序order by create_time,理论上来说JDBC查询已经是比较底层的技术了,没有像Hibernate.MyBatis那样又 ...

  5. CSS :after、before、<!DOCTYPE>

    <!DOCTYPE> <!DOCTYPE> 声明必须是 HTML 文档的第一行,位于 <html> 标签之前. CSS :选择器 after,before

  6. CURL 常用参数

    在Linux中curl是一个利用URL规则在命令行下工作的文件传输工具,可以说是一款很强大的http命令行工具. 1.查看响应头信息: -I :显示http response的头信息. [root@l ...

  7. Drools 语法

    Drools 语法 规则语法 package: package 的名字是随意的,不必必须对应物理路径 import: 导入外部变量 规则的编译与运行要通过Drools 提供的各种API 来实现.API ...

  8. Druid搭配log4j2输出SQL语句和结果

    一.引言 其实Druid的内置了log4jdbc来显示SQL语句,虽然显示效果不如原生的log4jdbc效果好,但是因为内置所以不需要其他更多的配置. 二.使用 1. 创建基于druid的logger ...

  9. [Php] Deprecated: Function ereg_replace() is deprecated

    From: http://www.zxyf.net/n6805c18.shtml 这个问题是因为你用的php版本过高. 在php5.3中,正则函数ereg_replace已经废弃,而dedecms还继 ...

  10. vue如何加入百度联盟广告

    在百度联盟代码位管理中创建好对应的代码位之后,点击获取代码,会看到这样一段js 直接复制粘贴到自己网页中便可显示对应广告. 在vue中由于都是vue组件,不支持直接在组件中加入这样一段一段的js代码, ...