网络编程(46)—— windows内核对象的两种状态
2016-12-27 08:52
337 查看
一、 什么是内核对象?
我们知道进程、线程、文件、互斥、信号量这些都是操作系统级别的资源。我们在使用这些资源时,实际上都是由操作系统进行创建和管理的。操作系统为了管理这些资源,会在其内部创建一个数据块,也可以理解为一个结构体对象。这个数据块就是内核对象。
二、 内核对象有哪两种状态?
内核对象的状态共有两种:signaled(有信号)状态和non-signaled(无信号)状态。以线程为例:当一个线程正在运行时,管理它内核对象处于non-signaled状态;而当线程结束运行时,管理它的内核对象将处于signaled状态。
三、 内核对象的两种模式
Auto-reset模式 —— 当发生了某事件(如线程结束),内核对象进入signaled状态后,我们调用WaitForSingleObjec返回后,内核对象会自动进入non-signaled状态,内核对象的这种模式就叫做auto-reset模式。
Manual-reset 模式 —— 当内核对象进入signaled状态后,WaitForSingleObjec返回,内核对象也不会自动进入non-signaled状态,除非我们手动将其设置为non-signaled状态,它
的的这种模式叫做manual-reset模式。
四、 获取内核对象状态的两个API
我们可利用WaitForSingleObject和WaitForMultipleObjects来获取内核对象的状态,如果这两个是阻塞函数,如果所监视的内核对象状态为signaled时,函数将会返回。下面是WaitForSingleObject的函数原型:
DWORD WINAPI WaitForSingleObject( __in HANDLE hHandle, __in DWORD dwMilliseconds );
hHandle —— 表示要监视的线程、事件等内核对象管理的资源的Handle值。
dwMilliseconds —— 设置等待超时,单位是毫秒。如果设置成INFINITE表示一直等到内核对象状态变成signaled为止。
函数返回值 —— 若内核对象变成signaled状态,函数返回WAIT_OBJECT_0;若等待超时,函数返回WAIT_TIMEOUT
WaitForMultipleObjects的功能和WaitForSingleObject类似,只不过它可以同时等待多个内核对象状态的改变。其函数原型如下:
DWORD WINAPI WaitForMultipleObjects( __in DWORD nCount, __in const HANDLE *lpHandles, __in BOOL bWaitAll, __in DWORD dwMilliseconds );
nCount —— 等待的内核对象的个数。
lpHandles —— 存放内核对象句柄的数组的首地址。
bWaitAll —— 设置是否全部等待。若为True,表示所有的内核对象变成signaled状态后返回;若为False,表示只要有一个内核对象变成signaled 状态即返回。
dwMilliseconds —— 设置等待超时,单位是毫秒。如果设置成INFINITE表示一直等到内核对象状态变成signaled为止。
函数返回值 —— 若内核对象变成signaled状态,函数返回WAIT_OBJECT_0;若等待超时,函数返回WAIT_TIMEOUT
以下是使用WaitForMultipleObjects等待线程的实例。主要功能是启动两个线程,然后使用等待WaitForMultipleObjects两个线程结束,最后根据WaitForMultipleObjects的返回值打印输出线程是正常结束还是等待超时。
#include "stdafx.h" #include "windows.h" #include<process.h> unsigned WINAPI ThreadFunc1(void* args) { int i=0; while(1) { puts("ThreadFunc1 called ..."); if(++i==5) { puts("ThreadFunc1 Ended"); ExitThread(1); } Sleep(1000); } } unsigned WINAPI ThreadFunc2(void* args) { int i=0; while(1) { puts("ThreadFunc2 called ..."); if(++i==10) { puts("ThreadFunc2 Ended"); ExitThread(2); } Sleep(1000); } } int _tmain(int argc, _TCHAR* argv[]) { DWORD thredID1,thredID2; HANDLE handles[2]; handles[0]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadFunc1,NULL,0,&thredID1); handles[1]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadFunc2,NULL,0,&thredID2); DWORD dr = WaitForMultipleObjects(2,handles,true,INFINITE); if(dr==WAIT_OBJECT_0) { puts("两¢?个?内¨²核?对?象¨®都?进?入¨?signaled状Á¡ä态¬?。¡ê"); } else if(dr==WAIT_TIMEOUT) { puts("等̨¨待äy超?时º¡À。¡ê"); } return 0; }
main函数里,我们分别启动了两个线程,此时管理线程的内核对象将进入non-signaled状态。我们调用WaitForMultipleObjects等待线程结束进入signaled状态。当线程结束进入signaled状态后,WaitForMultipleObjects返回,开始执行其后面的语句。但是由于管理线程的内核对象不是Auto-Reset对象,这两个内核对象将一直保持signaled状态。
程序运行结果:
Github位置:
https://github.com/HymanLiuTS/NetDevelopment
克隆本项目:
git clone
git@github.com:HymanLiuTS/NetDevelopment.git
获取本文源代码:
git checkout NL46
相关文章推荐
- Windows编程那些事----线程与内核对象同步之【信标对象】
- WINDOWS核心编程学习1------内核对象
- Windows核心编程_3.内核对象
- Windows编程_Lesson007_内核对象之二
- Windows编程--线程和内核对象的同步-事件内核对象
- 内核对象的两种状态 激活 未激活
- Windows 核心编程之6 线程内核对象
- Windows编程--线程和内核对象的同步-信标(信号量)内核对象
- Windows-核心编程-09-如何用内核对象进行线程同步-事件内核对象
- 【Windows 核心编程】Windows 核心编程 -- 内核对象
- windows核心编程-事件内核对象
- windows核心编程--内核对象
- windows内核对象的信号状态
- Windows核心编程--用内核对象进行线程同步(一)
- windows核心编程---用内核对象进行线程同步
- windows编程(1)-句柄,内核对象
- windows 核心编程之9 内核对象用于线程同步
- Windows-核心编程-09-如何用内核对象进行线程同步-信号内核对象
- Windows核心编程学习八:事件内核对象
- Windows高级编程之线程与内核对象的同步