网络编程(46)—— windows内核对象的两种状态

一、 什么是内核对象?

        我们知道进程、线程、文件、互斥、信号量这些都是操作系统级别的资源。我们在使用这些资源时,实际上都是由操作系统进行创建和管理的。操作系统为了管理这些资

源,会在其内部创建一个数据块,也可以理解为一个结构体对象。这个数据块就是内核对象。

二、 内核对象有哪两种状态?

        内核对象的状态共有两种: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



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值