Chapter09-内核模式下的线程同步之事件内核对象
有两种事件内核对象:自动事件和手动事件。当手动事件被触发时,所以该事件的等待线程都编程可调度状态;而自动事件被触发时,只有个一个等待该事件线程变成可调度状态。
下面再逐个讲解Event的相关函数:
a) 创建事件函数——CreateEvent函数:
HANDLE CreateEvent(
PSECURITY_ATTRIBUTESpsa,
BOOLbManualReset,
BOOLbInitialState,
PCTSTRpszName);
具体的函数参数及用法,请查看上面的超链接。
b) 第二创建事件的函数——CreateEventEx函数:
HANDLE CreateEventEx(
PSECURITY_ATTRIBUTESpsa,
PCTSTRpszName,
DWORDdwFlags,
DWORDdwDesiredAccess);
c) 访问某个打开的事件(Event)——OpenEvent函数:
HANDLE OpenEvent(
DWORDdwDesiredAccess,
BOOLbInherit,
PCTSTRpszName)
在pszName传递创建事件时函数的pszName参数值。
d) 使得某个事件处于触发状态——SetEvent函数:
BOOL SetEvent(HANDLE hEvent);
e) 将某个事件设置为非触发状态——ResetEvent函数:
BOOL ResetEvent(HANDLE hEvent);
f) 特别的函数——PluseEvent函数:
BOOL PulseEvent(HANDLE hEvent);
其作用相当于在调用SetEvent函数后立即调用ResetEvent函数,功能就是一次启用一个线程。因为手动方式的事件时,当事件触发时,所有的该事件阻塞的线程都会转为可调度状态。如果你调用PluseEvent函数后,在系统调用某一个线程后,由于立马将事件设置为非触发状态,这是其他线程也就再次被阻塞了。解释起来好像比较麻烦,不过该函数在实际使用过程中也少有用到。
看一个创建事件时设置手动方式的事件(manual-reset events)示例:
// Create a global handle to a manual-reset, nonsignaled event. HANDLE g_hEvent; int WINAPI _tWinMain(...) { // Create the manual-reset, nonsignaled event. g_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); // Spawn 3 new threads. HANDLE hThread[3]; DWORD dwThreadID; hThread[0] = _beginthreadex(NULL, 0, WordCount, NULL, 0, &dwThreadID); hThread[1] = _beginthreadex(NULL, 0, SpellCheck, NULL, 0, &dwThreadID); hThread[2] = _beginthreadex(NULL, 0, GrammarCheck, NULL, 0, &dwThreadID); OpenFileAndReadContentsIntoMemory(...); // Allow all 3 threads to access the memory. SetEvent(g_hEvent); ... } DWORD WINAPI WordCount(PVOID pvParam) { // Wait until the file's data is in memory. WaitForSingleObject(g_hEvent, INFINITE); // Access the memory block. ... return(0); } DWORD WINAPI SpellCheck (PVOID pvParam) { // Wait until the file's data is in memory. WaitForSingleObject(g_hEvent, INFINITE); // Access the memory block. ... return(0); } DWORD WINAPI GrammarCheck (PVOID pvParam) { // Wait until the file's data is in memory. WaitForSingleObject(g_hEvent, INFINITE); // Access the memory block. ... return(0); }
创建事件时设置为自动方式时的事件(auto-reset event)示例:
// Create a global handle to a auto-reset, nonsignaled event. HANDLE g_hEvent; int WINAPI _tWinMain(...) { // Create the auto-reset, nonsignaled event. g_hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); // Spawn 3 new threads. HANDLE hThread[3]; DWORD dwThreadID; hThread[0] = _beginthreadex(NULL, 0, WordCount, NULL, 0, &dwThreadID); hThread[1] = _beginthreadex(NULL, 0, SpellCheck, NULL, 0, &dwThreadID); hThread[2] = _beginthreadex(NULL, 0, GrammarCheck, NULL, 0, &dwThreadID); OpenFileAndReadContentsIntoMemory(...); // Allow all 3 threads to access the memory. SetEvent(g_hEvent); ... } DWORD WINAPI WordCount(PVOID pvParam) { // Wait until the file's data is in memory. WaitForSingleObject(g_hEvent, INFINITE); // Access the memory block. ... SetEvent(g_hEvent); return(0); } DWORD WINAPI SpellCheck (PVOID pvParam) { // Wait until the file's data is in memory. WaitForSingleObject(g_hEvent, INFINITE); // Access the memory block. ... SetEvent(g_hEvent); return(0); } DWORD WINAPI GrammarCheck (PVOID pvParam) { // Wait until the file's data is in memory. WaitForSingleObject(g_hEvent, INFINITE); // Access the memory block. ... SetEvent(g_hEvent); return(0); }
分析:
对比上面的代码示例,细心的话你会发现:在自动方式下的代码中,每个线程在返回前都会调用SetEvent函数将事件设置为触发状态;而手动方式事件对应的函数中没有调用这个函数。
这是因为在自动方式下,事件每次转化为触发状态时只能使一个线程变成可调度状态,为了让其他线程也能被执行,所以在每个线程返回前再次将事件设置为触发状态,使得其他等待该事件的线程转为可调度状态从而被执行。
而手动方式下,则不同,当手动方式事件被SetEvent函数触发一次,它就一直保持触发态,直到再次调用ReSetEvent函数将它设为非触发态。
转载于:https://www.cnblogs.com/java20130722/archive/2012/08/05/3207198.html
Chapter09-内核模式下的线程同步之事件内核对象相关推荐
- 用户模式下的线程同步
在以下两种基本情况下,线程之间需要相互通信 1.需要让多个线程同时访问一个共享资源,同时不能破坏资源的完整性 2.一个线程需要通知其他线程某项任务已经完成. 原子访问相关的内容就直接略过了,因为感觉实 ...
- Windows用户模式下的线程同步
Interlocked系列函数 原子访问:线程在访问某个资源的时候能保证没有其他线程会在同一时刻访问同一资源 函数名 功能 InterlockedExchangeAdd InterlockedExch ...
- linux 返回非法指令,linux – ARM Cortex A7在内核模式下返回PMCCNTR = 0,在用户模式下返回非法指令(即使在PMUSERENR = 1之后)...
我想在Raspberry Pi 2上读取循环计数寄存器(PMCCNTR),它有一个ARM Cortex A7内核.我为它编译了一个内核模块,如下所示: #include #include int in ...
- 在windows内核模式下隐藏进程
进程隐藏之内核实现 1.在内核模式下,系统为每个进程维护了一个EPROCESS结构体,系统所有的进程是通过EPROCESS结构体中的一个ActiveProcessLinks指向的双端链表连接起来的,通 ...
- 【Linux下】 线程同步 生产者与消费者模型
文章目录 [Linux下] 线程同步 生产者与消费者模型 线程同步 同步概念与竞态条件 条件变量 条件变量本质 操作条件变量 初始化和销毁条件变量 等待 唤醒 通过条件变量实现的简单线程同步例子 为什 ...
- Windows8内核模式下开发NDIS应用 NDIS Filter讲解
分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 在Win ...
- 达梦DM8单进程多线程架构模式下各线程详解
达梦数据库进程管理方式类似于Mysql,属于单进程多线程模式.数据库服务进程包含:DmServer(主服务进程)和DmAPService(备份服务进程).线程主要包括:监听线程.IO线程.工作线程.调 ...
- Android内核模式下对当前进程的cred结构的获取方式
大家好,最近一直在研究android下的溢出获取root权限,目前研究的成果是: 已经对一个设备进行溢出,让pc指针跳入了预定好的函数中:在获取要获取权限的时候遇到了如下难题. 1.在4.3+ 开启S ...
- 内核模式下关闭/开启写保护(WriteProtect)
在内核态下,数据段受到写保护,并非可以直接修改,控制写保护的就是一个比特位,其位于CR0寄存器的第17位(即索引为16). 在x86下可以通过内联汇编来修改该位.但是在64位下无法使用内联汇编了.还是 ...
最新文章
- Spring MVC配置
- 在C#中如何在客户端接收信件
- LeetCode-数组-54. 螺旋矩阵
- php session写入数据库_php session 写入数据库,phpsession
- box-shadow IE8兼容处理
- 专题导读:学术大数据
- [有限元]虚位移原理和虚力原理的证明的统一逻辑
- 2个recordset合并_史上最全!8种办法玩转Excel文字合并,总有一款适合你!
- 计算机盘中文件夹丢失,电脑装机后原区分f盘内文件夹丢失如何找回
- 结构体全局变量_nginx源码分析—内存池结构ngx_pool_t及内存管理
- 【ACC编码】基于FPGA的音频ACC编码实现
- Java核心技术36讲(整理)
- python项目实例-实例分享 | 4个Python实战项目(一)
- 论文中的Matlab画图常用技巧
- 设置电脑的保护色(绿豆沙色)
- 一文详解:中信银行java笔试题库
- 利用 QTcpSocket 实现的进程间通信
- python 拦截windows弹窗广告_Win10如何拦截桌面弹窗广告?流氓软件怎么彻底清除?...
- c语言中strlen什么作用,strlen函数在c语言中的用法是什么
- 解决新版本谷歌浏览器CROS跨域问题
热门文章
- 《程序设计与数据结构》第四周学习总结
- Shiro和SpringBoot简单集成
- JAVA知识积累 JSP第一篇【JSP介绍、工作原理、生命周期、语法、指令、行为】...
- 百度地图拖动标注后获取坐标
- [Qt-creator]实用技巧----基于ubuntu
- $(document).ready、body.Onload()和 $(window).load的区别
- 通过错误的sql来测试推理sql的解析过程
- 安装并测试nvenc linux sdk
- Linux 文件安全之随机数生成器
- 13.7 手柄(Handle)