未加星标

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

字体大小 | |
[系统(windows) 所属分类 系统(windows) | 发布者 店小二05 | 时间 2016 | 作者 红领巾 ] 0人收藏点击收藏
windows核心编程 第九章 线程与内核对象的同步

昨天来源:CSDN博客

9.4 等待定时器内核对象

等待定时器是在某个时间或按规定的间隔时间发出自己的信号通知的内核对象。它们通常用来在某个时间执行某个操作。

若要创建等待定时器,只需要调用C r e a t e Wa i t a b l e Ti m e r函数:

HANDLE CreateWaitableTimer(

PSECURITY_ATTRIBUTES psa,

BOOL fManualReset,

PCTSTR pszName

);

p s a和p s z N a m e这两个参数在第3章中做过介绍。当然,进程可以获得它自己的与进程相关的现有等待定时器的句柄,方法是调用O p e n Wa i t a b l e Ti m e r函数:

HANDLE OpenWaitableTimer(

DWORD dwDesiredAccess,

BOOL bInheritHandle,

PCTSTR pszName

);

与事件的情况一样,f M a n u a l R e s e t参数用于指明人工重置的定时器或自动重置的定时器。当发出人工重置的定时器信号通知时,等待该定时器的所有线程均变为可调度线程。当发出自动重置的定时器信号通知时,只有一个等待的线程变为可调度线程。

等待定时器对象总是在未通知状态中创建。必须调用 S e t Wa i t a b l e Ti m e r函数来告诉定时器你想在何时让它成为已通知状态:


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

这个函数带有若干个参数,使用时很容易搞混。显然, h Ti m e r参数用于指明你要设置的定时器。p D u e Ti m e和l P e r i o d两个参数是一道使用的。P D u e Ti m e r参数用于指明定时器何时应该第一次报时,而l P e r i o d参数则用于指明此后定时器应该间隔多长时间报时一次。下面的代码用于将定时器的第一次报时的时间设置在2 0 0 2年1月1日的下午1点钟,然后每隔6小时报时一次:


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

代码首先对S Y S T E M T I M E结构进行初始化,该结构用于指明定时器何时第一次报时(发出信号通知) 。我将该时间设置为本地时间,即计算机所在时区的正确时间。 S e t Wa i t a b l e Ti m e r的第二个参数的原型是个常量LARGE_INTEGER *,因此它不能直接接受S Y S T E M T I M E结构。但是,F I L E T I M E结构和L A R G E _ I N T E G E R结构拥有相同的二进制格式,都包含两个 3 2位的值。因此,我们可以将S Y S T E M T I M E结构转换成F I L E T I M E结构。再一个问题是,希望传递给它的时间始终都采用世界协调时( U T C)的时间。调用L o c a l F i l e Ti m e To F i l e Ti m e函数,就可以很容易地进行时间的转换。

由于F I L E T I M E和L A R G E _ I N T E G E R结构具有相同的二进制格式,因此可以像下面这样将F I L E T I M E结构的地址直接传递给S e t Wa i t a b l e Ti m e r:

实际上,这是我最初的做法。但是这是个大错误。虽然 F I L E T I M E和L A R G E _ I N T E G E R结构采用相同的二进制格式,但是这两个结构的调整要求不同。所有 F I L E T I M E结构的地址必须从一个3 2位的边界开始,而所有 结构的地址则必须从 6 4位的边界开始。调用S e t Wa i t a b l e Ti m e r函数和给它传递一个 F I L E T I M E结构时是否能够正确地运行,取决于F I L E T I M E结构是否恰好位于6 4位的边界上。但是,编译器能够确保结构总是从6 4位的边界开始,因此要进行的正确操作(也就是所有时间都能保证起作用的操作)是将F I L E T I M E的成员拷贝到的成员中,然后将的地址传递给。

注意 x 8 6处理器能够悄悄地处理未对齐的数据引用。因此当应用程序在 x86 CPU上运行时,将F I L E T I M E的地址传递给S e t Wa i t a b l r Ti m e r总是可行的。但是,其他处理器,如A l p h a处理器,则无法像x 8 6处理器那样悄悄地处理未对齐的数据引用。实际上,大多数其他处理器都会产生一个 E X C E P T I O N _ D ATAT Y P E _ M I S A L I G N M E N T异常,它会导致进程终止运行。当你将 x 8 6计算机上运行的代码移植到其他处理器时,产生问题的最大原因是出现了对齐错误。如果现在注意对齐方面的问题,就能够在以后省去几个月的代码移植工作。关于对齐问题的详细说明,参见第 1 3章。

现在,若要使定时器在2 0 0 2年1月1日下午1点之后每隔6 h进行一次报时,我们应该将注意力转向l P e r i o d参数。该参数用于指明定时器在初次报时后每隔多长时间(以毫秒为单位)进行一次报时。如果是每隔6 h进行一次报时,那么我传递 21 600 000(6 h×每小时6 0 m i n×每分钟6 0 s×每秒1 0 0 0 m s) 。另外,如果给它传递了以前的一个绝对时间,比如1 9 7 5年1月1日下午1点,那么S e t Wa i t a b l e Ti m e r的运行就会失败。

如果不设置定时器应该第一次报时的绝对时间,也可以让定时器在一个相对于调用S e t Wa i t a b l e Ti m e r的时间进行报时。只需要在p D u e Ti m e参数中传递一个负值。传递的值必须是以1 0 0 n s为间隔。由于我们通常并不以 1 0 0 n s的间隔来思考问题,因此我们要说明一下 1 0 0 n s的具体概念:1 s = 1 0 0 0 m s = 1 0 0 0 0 0 0 s = 1 0 0 0 0 0 0 0 0 0 n s 。

下面的代码用于将定时器设置为在调用S e t Wa i t a b l e Ti m e r函数后5 s第一次报时:


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

通常情况下,你可能想要一个一次报时的定时器,它只是发出一次报时信号,此后再也不发出报时信号。若要做到这一点,只需要为 l P e r i o d参数传递0即可。然后可以调用C l o s e H a n d l e函数,关闭定时器,或者再次调用 S e t Wa i t a b l e Ti m e r函数,重新设置时间,为它规定一个需要遵循的新条件。

S e t Wa i t a b l e Ti m e r的最后一个参数是f R e s u m e,它可以用于支持暂停和恢复的计算机。通常可以为该参数传递FA L S E,就像我在上面这个代码段中设置的那样。但是,如果你编写了一个会议安排类型的应用程序,在这个应用程序在中,你想设置一个为用户提醒会议时间安排的定时器,那么应该传递T R U E。当定时器报时的时候,它将使计算机摆脱暂停方式(如果它处于暂停状态的话) ,并唤醒等待定时器报时的线程。然后该应用程序运行一个波形文件,并显示一个消息框,告诉用户即将举行的会议。如果为 f R e s u m e参数传递FA L S E,定时器对象就变为已通知状态,但是它唤醒的线程必须等到计算机恢复运行(通常由用户将它唤醒)之后才能得到C P U时间。

除了上面介绍的定时器函数外,最后还有一个C a n c e l Wa i t a b l e Ti m e r函数:

BOOL CancelWaitableTimer(HANDLE hTimer);

这个简单的函数用于取出定时器的句柄并将它撤消,这样,除非接着调用 S e t Wa i t a b l e Ti m e r函数以便重新设置定时器,否则定时器决不会进行报时。如果想要改变定时器的报时条件,不必在调用函数之前调用C a n c e l Wa i t a b l e Ti m e r函数。每次调用函数,都会在设置新的报时条件之前撤消定时器原来的报时条件。

9.4.1 让等待定时器给A P C项排队

到现在为止,你已经学会了如何创建定时器和如何设置定时器。你还知道如何通过将定时器的句柄传递给 Wa i t F o r S i n g l e O b j e c t或Wa i t F o r M u l t i p l e O b j e c t s函数,以便等待定时器报时。M i c r o s o f t还允许定时器给在定时器得到通知信号时调用 S e t Wa i t a b l e Ti m e r函数的线程的异步过程调用(A P C)进行排队。

一般来说,当调用 S e t Wa i t a b l e Ti m e r函数时,你将同时为 p f n C o m p l e t i o n R o u t i n e和p v A rg C o m p l e t i o n R o u t i n e参数传递

本文系统(windows)相关术语:三级网络技术 计算机三级网络技术 网络技术基础 计算机网络技术

主题: Windows编译器SDNCPU数据CUUT博客
分页:12
转载请注明
本文标题:Windows核心编程 第九章 线程与内核对象的同步
本站链接:http://www.codesec.net/view/480748.html
分享请点击:


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 系统(windows) | 评论(0) | 阅读(32)