《Windows内核编程》---系统线程和同步事件

windows内核编程基础篇之使用同步事件 内核中的事件是一个数据结构,这个结构的指针可以当作一个参数传入一个等待函数中。若这个事件不被“设置”,则这个等待函数不会返回。这个线程被阻塞,若这个事件被“设置”,则等待结束,可以继续下去。        这个常常用于多线程之间的同步,若一个线程需要等待另外一个线程完成某事后才能做某事,则可以使用事件等待,另一个线程完成后设置事件即可。        该数据结构是KEVENT, 器被  K 阅读详情

系统线程:

在驱动中生成的线程一般是系统线程,系统线程所在的进程名为“System”,用到的内核API函数是:

NTSTATUS PsCreateSystemThread(

OUT PHANDLE ThreadHandle,

IN ULONG DesiredAccess,

IN POBJECT_ATTRIBUTES objectAttributes OPTIONAL,

IN HANDLE ProcessHandle OPTIONAL,

OUT PCLIENT_ID ClientId OPTIONAL,

IN PKSTART_ROUTINE StartRoutine,

IN PVOID StartContext

);

一般情况下,ThreadHandle用来返回句柄,放入一个句柄指针即可;DesiredAccess赋值为0;接着三个可选参数都赋值为0;StartRoutine参数是用于该线程启动时执行的函数;StartContext是线程函数的参数。线程函数的原型如下:

VOID CustomThreadProc(IN PVOID context); //context自然就是由上面的StartContext传入的

注意:线程在结束时应该自己调用PsTerminateSystemThread函数来完成,此外得到的线程句柄ThreadHandle要使用ZwClose来关闭。(关闭句柄并不等于结束线程)

下面的函数演示怎样创建并使用系统线程:

//线程函数

VOID ASCEThreadProc(PVOID context)

{

         PUNICODE_STRING str = (PUNICODE_STRING)context;

         //打印字符串

         KdPrint((“Print In ASCEThead:%wZ/r/n”, str));

         //结束自己

         PsTerminateSystemThread(STATUS_SUCCESS);

}

 

VOID ASCEFunction()

{

         UNICODE_STRING str = RTL_CONSTANT_STRING(L”ASCE!”);

         HANDLE thread = NULL;

         NTSTATUS status;

         status = PsCreateSystemThread(

&thread, 0L, NULL, NULL, NULL, ASCEThreadProc, (PVOID)&str);

         if(!NT_SUCCESS(status))

         {

                   //错误处理

                   …-.

}

//成功了,则做自己的事

…-..

//最后关闭句柄

ZwClose(thread);

}

上面代码存在如下错误:ASCEThreadProc执行时,ASCEFunction可能已经执行完了。而执行完之后,堆栈中的str就无效了。此时再执行KdPrint打印str一定会蓝屏。

合理的方法是在堆中分配str的空间,或者str必须在全局空间中。当然,我们也可以在PsCreateSystemThread结束之后,在它的后面加上一个等待线程结束的语句。

 

在线程中睡眠:

在驱动编程中使用到的用于睡眠的内核函数是:

NTSTATUE KeDelayExecutionThread(

IN KPROCESSOR_MODE WaitMode,

IN BOOLEAN Alertable,

IN PLARGE_INTEGER Interval

);

其中参数WaitMode应该总是赋值为KernelMode,因为我们现在是在内核编程;Alertable表示是否允许线程报警(用于重新唤醒);Interval表示要睡眠多长时间。

下面是简单的睡眠函数,它可以指定睡眠多少毫秒:

#define DELAY_ONE_MICROSECOND (-10)

#define DELAY_ONE_MILLISECOND (DELAY_ONE_MICROSECOND*1000)

VOID ASCESleep(LONG msec)

{

         LARGE_INTEGER asceInterval;

         asceInterval.QuadPart = DELAY_ONE_MILLISECOND;

         asceInterval.QuadPart *= msec;

         KeDelayExecutionThread(KernelMode, 0, &asceInterval);

}

 

同步对象:

内核中的事件是一个数据结构,这个结构的指针可以当作一个参数传入一个等待函数中。如果这个事件不被“设置”,则这个等待函数不会返回,这个线程被阻塞;如果这个事件被“设置”,则等待结束,线程可以继续执行。

如果一个线程需要等待另一个线程完成某事之后才能做某事,则可以使用事件等待。这个数据结构就是KEVENT,这个结构总是用KeInitializeEvent初始化:

VOID KeInitializeEvent(

IN PRKEVENT Event,

IN EVENT_TYPE Type,

IN BOOLEAN State

);

参数Event是要初始化的事件;Type是事件类型;参数State是初始化状态,一般设置为FALSE,也就是未设置状态,这样等待线程需要等待。注意,事件不需要销毁。

设置事件使用函数KeSetEvent:

LONG KeSetEvent(

IN PRKEVENT Event,       //要设置的事件

IN KPRIORITY Increment,      //用于提升优先权,可设为0

IN BOOLEAN Wait //表示函数后面是否紧接着一个KeWaitSingleObject来等待这个事件,

//一般设置为TRUE(事件初始化后,一般就要开始等待了)

);

 

使用事件的简单代码如下:

//等待一个事件

KEVENT event;

//事件初始化

KeInitializeEvent(&event, SynchronizationEvent, TRUE);

…-…-

//事件初始化之后就可以使用了,在一个函数中,我们可以等待某个事件

//如果这个事件没有被人设置,那就会阻塞在这里继续等待

KeWaitForSingleObject(&event, Executive, KernelMode, 0, 0);

…-..

 

//在另一个函数或其他地方,设置了这个事件。而一旦设置了这个事件

//前面等待的地方就会开始继续执行

KeSetEvent(&event);

上面代码中KeInitializeEvent中使用了SynchronizationEvent,导致这个事件成为所谓的“自动重设”事件。一个事件如果被设置,那么所有KeWaitForSingleObject等待这个事件的地方都会通过。如果要继续重复使用这个事件,必须重设这个事件。当KeInitializeEvent第二个参数设置为NotificationEvent时,这个事件必须要手动重设才能使用。手动重设使用函数:

LONG KeResetEvent(

IN PRKEVENT Event

);

上面代码中的事件初始化为SynchronizationEvent事件,因此只有一个线程的KeWaitForSingleObject可以通过,通过之后被自动重设,其他的线程只能继续等待,这就是一个同步事件。

不能起到同步作用的是通知事件(NotificationEvent),注意,不能用手工设置通知事件的方式来取代同步事件,Don’t be stupid, ok?

 

下面使用同步事件来改进上面系统线程中的例子,即在线程中打印结束之后,设置同步事件,外面的函数再返回:

static KEVENT asceEvent;

//线程函数

VOID ASCEThreadProc(PVOID context)

{

         PUNICODE_STRING str = (PUNICODE_STRING)context;

         KdPrint(("Print in ASCEThread: %wZ/r/n", str));

         KeSetEvent(&asceEvent);     //设置事件

         PsTerminateSystemThread(STATUS_SUCCESS);

}

 

//生成线程的函数

VOID ASCEFunction()

{

         UNICODE_STRING str = RTL_CONSTANT_STRING(L"SEE YOU IN ANOTHER LIFE BROTHER");

         HANDLE thread = NULL;

         NTSTATUS status;

         KeInitializeEvent(&asceEvent, SynchronizationEvent, TRUE);       //初始化事件

         status = PsCreateSystemThread(

                   &thread, 0L, NULL, NULL, NULL, ASCEThreadProc, (PVOID)&str);

         if(!NT_SUCCESS(status))

         {

                   //错误处理

         }

         ZwClose(thread);

         //等待事件结束在返回

         KeWaitForSingleObject(&asceEvent, Executive, KernelMode, 0, 0);

}

注意,等待线程结束不一定要用事件,线程本身也可以用来等待。上面函数的缺点是不能起到并发执行的作用。

Windows进程同步之事件内核对象(Event) 在所有的内核对象中,事件内核对象比其他的简单的多,可以用事件内核对象对不同进程进行同步。 事件内核对象主要包括三个部分:使用计数,一个表示是自动还是手动重置事件的布尔值,一个表示是否有信号的布尔值。 使用计数:和其他内核对象一样,用来标识使用该事件对象的不同线程个数。表示自动或手动重置事件的布尔值:当一个事件是自动重置事件,事件被触发后,只有一个等待的线程会变成可调度状态(根据系统的调度策 阅读详情

相关推荐

波束形成算法:LCMV实现(MATLAB)

阵列信号处理,波束成形,

weixin_43601588的博客 1万+

KEINITIALIZEEVENT内核模式下事件对象

内核模式下事件对象 VOID KeInitializeEvent( IN PRKEVENT Event, // 这个参数是初始化事件对象的指针 IN EVENT_TYPE Type, // 这个参数是事件的类型。一类是“通知事件”对应参数为 NotificationEvent。另一类是“同步事件”,对应参数 SynchronizationEvent IN BOOLEAN State // TRUE:事件对象初始化状态为激发。FALSE:事件对象初始化状态为未激发 ); 解释1...

hutao1101175783的专栏 946

Unity游戏开发实战:如何用科大讯飞离线语音合成SDK实现NPC对话(附完整代码)

本文详细介绍了如何在Unity游戏开发中使用科大讯飞离线语音合成SDK实现NPC对话系统。通过完整的代码示例和优化技巧,开发者可以快速集成本地语音合成功能,提升游戏沉浸感,同时避免网络延迟问题。文章涵盖SDK集成、核心语音合成模块实现以及高级应用技巧,特别适合RPG游戏开发者参考。

weixin_29268385的博客 181

阴沟里翻船之KeSetEvent

阴沟里翻船之KeSetEvent KeSetEvent是个使用频率很高的内核支持函数,但经常使用未必意味着确实了解它。上周就曾遇到一件怪事,系统线程在调用KeSetEvent后线程IRQL竟然从PASSIVE_LEVEL提升至DISPATCH_LEVEL,以至后续的操作出错:Bug Check 0xA: IRQL_NOT_LESS_OR_EQUAL。 先看看它的函数声明:

vbsourcecode的专栏 1万+

RK3588上从零部署Facenet人脸识别:PyTorch转ONNX再到RKNN的完整避坑指南

本文提供了在RK3588开发板上从零部署Facenet人脸识别模型的完整指南。详细介绍了从PyTorch模型导出、转换为ONNX格式,再通过RKNN-Toolkit2转换为RKNN格式的完整流程,并重点分享了环境配置、算子兼容性处理、量化调优及板端部署中的关键步骤与避坑经验。

river的博客 464

java三角套利_三角对冲套利-EA原理全解析

它是两个直盘货币和一个交叉盘货币之间的相互对冲,交易员往往受到外界因素的影响无法严格执行造成亏损。该系统经过大量数据统计分析和严格的科学论证计算,并通过多年实盘交易验证可以达到稳定盈利。希望交易员严格按照交易规则执行。此策略利用交叉外汇对的市场价格与其合成价格的价差来实现套利,还以EUR/USD和GBP为例:1,我们关注三个外汇对:EUR/USD,GBP/USD,以及GBP/EUR2,计算GBP/...

weixin_29531897的博客 2418

内核同步对象

Windows NT提供了五种内核同步对象(Kernel Dispatcher Object),你可以用它们控制非任意线程(普通线程)的流程。表4-1列出了这些内核同步对象的类型及它们的用途。在任何时刻,任何对象都处于两种状态中的一种:信号态或非信号态。有时,当代码运行在某个线程的上下文中时,它可以阻塞这个线程的执行,调用KeWaitForSingleObject或KeWaitForMultipl

~。~||| 9075

Coze工作流实战:Coze一键生成沉浸式历史故事视频

【coze工作流实战】一键生成火爆的沉浸式历史故事视频!短短3分钟,顶替你3天的工作量!

bickys的博客 1004

在内核下使用事件对象KeInitializeEvent

VOID MyProcessThread( IN PVOID StartContext) { #if DBG _asm int 3 #endif PKEVENT pEvent=(PKEVENT)StartContext; DbgPrint("11111111111111!\n"); //设置事件 KeSetEvent(pEvent,IO_NO_INCREMENT,FALSE);

125096 5104

先进封装类别分析与典型案例

当制程微缩逼近物理极限、单颗大芯片(reticle limit)面积受限于光罩尺寸,且逻辑、存储、射频、传感等功能无法用同一套工艺最经济地制造时,性能增益的来源从 "晶体管密度" 转向 "互连密度"。先进封装的本质,是在芯片外部用更短、更密、更宽的路径把多个裸 die(die)互连起来,换取更高带宽、更低延迟、更小体积和异构集成能力。行业通常按划分为 2D、2.5D、3D、扇出、SiP 五大谱系,Chiplet/UCIe 则是贯穿其上的设计方法论,玻璃基板、共封装光学(CPO)是正在成型的新分支。

0 31

win10锁屏或登录时会自动弹出触摸按键的问题解决办法

本篇文章主要讲解win10锁屏或登录时会自动弹出触摸按键的问题解决方式。日期:2023年5月17日作者:任聪聪。

任聪聪的博客 1万+

《TCP/IP网络编程》学习笔记 | Chapter 20:Windows 中的线程同步

《TCP/IP网络编程》学习笔记 | Chapter 20:Windows 中的线程同步

ProgramNovice的博客 607

Pyhon在振动信号处理中的高级应用(一):振动信号特征(时域、频域)提取

文章目录一、概述二、算法原理2.1 时域统计特征三、python代码实现 一、概述 二、算法原理   这里我们借鉴西安交通大学机械学院雷教授的论文《Fault diagnosis of rotating machinery based on multiple ANFIS combination with GAs》相关研究成果。雷教授在论文中共列举了4类共24种振动信号的时域和频域特征。 2.1 时域统计特征 p1=∑n=1Nx(n)NP2=∑n=1N(x(n)−p1)2N−1p3=(∑n=1N∣x(n)∣N

白银时代的博客 1万+

Windows核心编程 第九章 线程与内核对象的同步(下)

9.4 等待定时器内核对象 等待定时器是在某个时间或按规定的间隔时间发出自己的信号通知的内核对象。它们通常用来在某个时间执行某个操作。 若要创建等待定时器,只需要调用C r e a t e Wa i t a b l e Ti m e r函数: HANDLE CreateWaitableTi...

墨鱼菜鸡 419

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

windows同步原理与调试(PPT)

最近在公司做了一次关于windows同步方面的培训,以下是本次培训的PPT文字。      Windows同步原理与调试      richard     2012.10.9    主要内容与讲解方式 ..用户态同步技术  ..内核态同步技术  ..使用windbg调试用户态线程死锁  ..讲解不面面俱到,不讲API使用  ..讲原理的同时穿插windbg的使

Changju博客 1149

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

事件与信号量

事件和信号量

qq_33004187的博客 247

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Windows 线程资源同步对象

由于同一时刻只有一个线程可以进入临界区,因此这种对资源的操作是排他的,即对于同一个临界区对象,不会出现多个线程同时操作该资源,哪怕是资源本身可以在同一时刻被多个线程进行操作,如多个线程对资源进行读操作,这就带来了效率问题。细心的读者会发现上述输出中存在同一个的线程连续两次进入临界区,这是有可能的。也就是说,当其中一个线程离开临界区,即使此时有其他线程在这个临界区外面等待,由于线程调度的不确定性,此时正在等待的线程也不会有先进入临界区的优势,它和刚离开这个临界区的线程再次竞争进入临界区是机会均等的。

一个时代的落幕,一个时代的开启。 152

Windows API一日一练(45)CreateEvent和SetEvent函数

 Windows API一日一练(45)CreateEvent和SetEvent函数     当你创建一个线程时,其实那个线程是一个循环,不像上面那样只运行一次的。这样就带来了一个问题,在那个死循环里要找到合适的条件退出那个死循环,那么是怎么样实现它的呢?在Windows里往往是采用事件的方式,当然还可以采用其它的方式。在这里先介绍采用事件的方式来通知从线程运行函数退出来,它的实现原理是这样,在那

679

Windows的4种主要的同步对象(原)

同步对象Windows共设置了4种主要的同步对象,分别是临界区(Critical Section)、互斥量(Mutex)、信号量(Semaphore)和事件(Event)。MFC封装了它们,分别是类CCriticalSection、CMutex、CSemaphore和CEvent,它们都以CSyncObject为基类。1、临界区(1)创建:CCriticalSection myCritical

893

Windows核心编程:用内核对象进行线程同步

 作者:shenzi链接:http://blog.youkuaiyun.com/shenziWindows核心编程:用内核对象进行线程同步1.概述    用户模式下的同步让线程保持在用户模式下,在用户模式下的进行线程同步的最大好处就是速度非常快。然而它们的确存在一些局限性,使用内核对象进行线程同步用途要广泛得多。然而使用内核对象进行线

shenzi的天空 2326
上一篇: 《Windows核心编程》---文件操作
下一篇: 《Windows内核编程》---系统时间和定时器
ACE1985
博客等级 码龄17年 1307粉丝 308原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值