资讯
安全
论坛
下载
读书
程序开发
数据库
系统
网络
电子书
微信学院
站长学院
QQ
手机软件
考试
安全
|
web开发
|
软件开发
|
移动开发
|
数据库
|
网络
|
系统
|
网站
|
考试认证
|
其他
|
读书频道
>
网站
>
网页设计
>
网络分析技术揭秘:原理、实践与WinPcap深入解析
3.1.5 同步处理
12-08-11
叶孤城
收藏
我要投稿
本文所属图书 >
网络分析技术揭秘:原理、实践与WinPcap深入解析
本书结合著名的开源软件库WinPcap来说明网络分析技术的实现原理及使用方法。其中包括WinPcap内核驱动,编译与使用,数据包的捕获、发送、内核过滤与接收,以及网络流量的统计与网络状态的分析等重要内容,而且作...
立即去当当网订购
Windows是多任务抢占式的操作系统,如果多个线程要求操作同一个资源,这时就需要同步处理了。如果没有同步机制的控制,所有的线程将会任意运行。如果驱动程序没有处理好同步问题,会出现程序出错、操作系统性能下降甚至死锁等现象。
下面将简要介绍在WinPcap中所涉及的同步处理机制。
1. 用户模式下的等待
在应用程序中,可以使用WaitForSingleObject函数等待一个同步对象,其原型如下:
DWORD WaitForSingleObject(
HANDLE hHandle, //同步对象句柄
DWORD dwMilliseconds //等待时间
);
参数dwMilliseconds是等待的超时时间,单位为毫秒(ms)。
同步对象有两种状态,一种是激发状态,一种是未激发状态。如果同步对象处于未激发状态,WaitForSingleObject则进入休眠状态,等待同步对象被激发。如果同步对象在指定的等待时间内,还是没有处于激发状态,则自动停止休眠。dwMilliseconds也可以设定为INFINITE,表示无限期地等待下去,直到等待的同步对象被激发为止。另外,dwMilliseconds也可以为0,其作用是强迫操作系统从当前线程上切换到其他线程上。
2. 用户模式下的事件
事件是一种典型的同步对象。用户模式下的事件和内核模式的事件对象紧密相连。在使用事件之前,需要对事件进行初始化,可使用CreateEvent函数完成这项任务,该函数的原型如下:
HANDLE CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes, //
BOOL bManualReset, // 复位方式
BOOL bInitialState, // 初始化状态
LPCTSTR lpName // 对象名称
);
CreateEvent函数会使操作系统创建一个内核事件对象,此函数返回的句柄就代表了这个内核事件对象。一般情况下,CreateEvent函数的安全属性会设置为NULL。它的第二个参数bManualReset表示创建的事件是否是手动模式。如果是手动模式的事件,事件处于激发状态后,则需要手动设置才能回到未激发状态;如果是自动模式,在事件处于激发状态后,遇到任意一个等待(如WaitForSingleObject)操作,则自动变回未激发状态。
下面为WinPcap中创建一个事件的代码:
HANDLE hEvent;
hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
3. 用户模式下的互斥体
互斥体是一种常用的同步对象,可以避免多个线程争夺同一个资源。也就是说,多线程环境中只能有一个线程占有互斥体。获得互斥体的线程如果不释放互斥体,其他线程永远不会获得该互斥体。同一个线程可以递归获得互斥体,递归获得互斥体的意思是,得到互斥体的线程还可以再次获得这个互斥体,也就是说互斥体对于已经获得互斥体的线程不产生“互斥”作用。
互斥体也有两种状态,激发态和未激发态。如果线程获得互斥体时的状态是未激发态,当释放互斥体时,互斥体的状态则为激发态。
初始化互斥体的函数是CreateMutex,其原型如下;
HANDLE CreateMutex(
LPSECURITY_ATTRIBUTES lpMutexAttributes, //
BOOL bInitialOwner, //
LPCTSTR lpName //
);
上述函数中第二个参数bInitialOwner表示互斥体初始化时是否被占有。如果没有被占有,为激发态,否则为未激发态。
获得互斥体的函数是WaitForSingleObject,而释放互斥体的函数是ReleaseMutex。
下面为WinPcap中使用互斥体的代码:
//原型互斥体
HANDLE g_AdaptersInfoMutex = NULL;
?
//
g_AdaptersInfoMutex = CreateMutex(NULL, FALSE, NULL);
?
//
WaitForSingleObject(g_AdaptersInfoMutex, INFINITE);
?
//
ReleaseMutex(g_AdaptersInfoMutex);
4. 自旋锁
自旋锁是一种同步处理机制,它能保证某个资源只能被一个线程所拥有,可用于驱动程序的同步处理。自旋锁的作用一般是使各个派遣函数之间同步。
初始化的自旋锁处于解锁状态时,它可以被程序获取。获取后的自旋锁处于锁住状态,不能被再次获取。锁住的自旋锁必须被释放后,才能再次被获取。如果自旋锁已被锁住,这时有程序申请获取这个自旋锁,则程序会处于“自旋”状态。所谓自旋状态,就是不停地询问是否可以获取自旋锁。
自旋锁不同于线程中的等待事件。在线程中如果等待某个事件,操作系统会使这个线程进入休眠状态,CPU会运行其他的线程。自旋锁则不同,CPU不会切换到别的线程,而是让这个线程一直“自旋”等待。因此,对自旋锁的占用时间不宜过长,否则会导致申请自旋锁的其他线程长时间处于自旋,浪费CPU的处理时间。
NDIS库使用NDIS_SPIN_LOCK数据结构表示自旋锁。使用自旋锁前,首先要对其初始化,可使用NdisAllocateSpinLock函数进行。申请获得自旋锁可使用NdisAcquireSpinLock函数,释放自旋锁可使用NdisReleaseSpinLock函数。这些函数的原型如下:
VOID NdisAllocateSpinLock( IN PNDIS_SPIN_LOCK SpinLock );
VOID NdisAcquireSpinLock( IN PNDIS_SPIN_LOCK SpinLock );
VOID NdisReleaseSpinLock(IN PNDIS_SPIN_LOCK SpinLock );
下面为WinPcap驱动程序中使用自旋锁的代码:
NDIS_SPIN_LOCK WriteLock; //_OPEN_INSTANCE结构体中的自旋锁字段
NdisAllocateSpinLock(&Open->WriteLock); //初始化自旋锁
NdisAcquireSpinLock(&Open->WriteLock); //申请获得自旋锁
if(Open->WriteInProgress)
{
NdisAcquireSpinLock(&Open->WriteLock); //释放自旋锁
SET_FAILURE_UNSUCCESSFUL();
break;
}
else
{
Open->WriteInProgress = TRUE;
}
NdisAcquireSpinLock(&Open->WriteLock); //释放自旋锁
5. NDIS库提供的事件
NDIS库提供的事件用NDIS_EVENT数据结构表示。使用事件前,首先要对其初始化,可使用NdisInitializeEvent函数完成。另外,可以使用NdisWaitEvent函数把调用者置为等待状态,直到给定事件为激发态或等待超时;也可使用NdisSetEvent函数把一个给定的事件设为激发态;还可使用NdisResetEvent函数清除一个给定事件的状态。各函数的原型如下:
VOID NdisInitializeEvent(IN PNDIS_EVENT Event);
BOOLEAN NdisWaitEvent(IN PNDIS_EVENT Event,IN UINT MsToWait);
VOID NdisSetEvent(IN PNDIS_EVENT Event);
VOID NdisResetEvent(IN PNDIS_EVENT Event);
下面为WinPcap中使用NDIS库事件的代码:
//_OPEN_INSTANCE结构体中的事件字段
NDIS_EVENT NdisWriteCompleteEvent;
NTSTATUS NPF_Open(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
?
//
NdisInitializeEvent(&Open->NdisWriteCompleteEvent);
?
}
NTSTATUS NPF_Write(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
{
?
//
NdisResetEvent(&Open->NdisWriteCompleteEvent);
?
//
NdisWaitEvent(&Open->NdisWriteCompleteEvent, 0);
?
}
VOID NPF_SendComplete(IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_PACKET pPacket,IN NDIS_STATUS Status)
{
?
//
NdisSetEvent(&Open->NdisWriteCompleteEvent);
?
}
6. 变量的原子操作
内核提供了对一个变量进行原子操作的函数,诸如对变量原子进行递增、递减操作,或者设置指定的值。
对一个变量进行原子递增操作时,可使用InterlockedIncrement函数,其原型如下:
LONG InterlockedIncrement(IN PLONG Addend);
上述函数中,参数Addend指向一个LONG型变量,函数返回递增后的值。
对一个变量进行原子递减操作时,可使用InterlockedDecrement函数,函数原型如下:
LONG InterlockedDecrement(IN PLONG Addend);
上述函数中,参数Addend指向一个LONG型变量,函数返回递减后的值。
对一个变量进行原子设置指定值的操作时,可使用InterlockedExchange函数,其原型如下:
LONG InterlockedExchange(IN OUT PLONG Target,IN LONG Value);
上述函数中,参数Target指向一个需要进行设置的LONG型变量;参数Value为需要设置的值。InterlockedExchange函数返回参数Target所指的初始值。
下面为WinPcap中使用原子操作的代码:
//申明需要原子操作的变量
ULONG g_NumOpenedInstances = 0;
NTSTATUS NPF_Open(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
?
//
localNumOpenedInstances =
InterlockedIncrement(&g_NumOpenedInstances);
?
}
NTSTATUS NPF_Cleanup(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
?
//
localNumOpenInstances =
InterlockedDecrement(&g_NumOpenedInstances);
?
}
点击复制链接 与好友分享!
回本站首页
分享到:
更多
您对本文章有什么意见或着疑问吗?请到
论坛讨论
您的关注和建议是我们前行的参考和动力
上一篇:
1.3 功能
下一篇:
1.5 小结
相关文章
图文推荐
JavaScript网页动画设
1.9 响应式
1.8 登陆页式
1.7 主题式
排行
热门
112 |
1.6 本书概要
112 |
1.5.5 软件
112 |
1.5.4 可扩展性
112 |
1.5.3 融合
112 |
1.5.2 虚拟化
112 |
1.5.1 以太网的使用
112 |
1.5 云网络的特征
112 |
1.4 什么是云网络
3.2.3 Bootstrap栅格系统
3.4.4 自适应显示/隐藏页面内容
3.3.1 固定式布局
2.1.1 下载Bootstrap
3.3.2 流式布局
3.4.6 响应式Bootstrap
3.4.2 设计响应式图片
3.2.4 响应式Bootstrap栅格系统
文章
下载
读书
·
Win2000下关闭无用端口
·
禁止非法用户登录综合设置 [win9x篇]
·
关上可恶的后门——消除NetBIOS隐患
·
网络入侵检测系统
·
潜伏在Windows默认设置中的陷井
·
调制解调器的不安全
·
构建Windows 2000服务器的安全防护林
·
SQL Server 2000的安全配置
·
Windows优化大师注册机源码
·
Aspcode动画教程
·
WIN 2000服务器防止ICMP数据包攻击教程
·
实现网络隐身的简单方法
·
手工进行克隆帐号
·
用W32DASM破解网页合并器的密码
·
注册表操作动画教程
·
冰河陷阱v1.2
·
黑客攻防技术宝典:Web实战篇(第2版)
·
超级网管员——网络安全
·
代码大全(第二版)
·
软件之道:软件开发争议问题剖析
·
CSS插件工具箱
·
CSS入门经典(第3版)
·
C#并行编程高级教程:精通.NET 4 Pa
·
CMMI+敏捷整合开发
关于我们
|
联系我们
|
广告服务
|
投资合作
|
版权申明
|
在线帮助
|
网站地图
|
作品发布
|
Vip技术培训
版权所有:
红黑联盟
--致力于做最好的IT技术学习网站