您的位置:首页 > 理论基础 > 计算机网络

网络编程(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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: