领先的中文IT技术网站    IT技术从现在起飞

飞诺旗下: 技术社区 | 在线电子书 | 在线试题 | 资源下载 | 飞诺搜索 | 技术博客
用户名: 密   码:
   飞诺网 加入收藏
飞诺网 C++ 新闻频道 开发频道 系统频道 服务器 网络频道 网络安全 Java频道 C/C++ PHP开发 电子书 资源下载 社 区 博 客 在线试题
软件编程 C C++ Java VB Delphi Foxpro 汇编语言 游戏开发 移动开发 软件工程师 软工与管理 VC shell编程 C#
编程开发 JAVA C/C++ C++ VC C语言 VB C# Delphi Foxpro 汇编 shell编程 游戏开发 软件工程师 WEB开发 PHP ASP Asp.net JSP AJAX CGI JavaScript HTML CSS 数据库 MSSQL Mysql Oracle Access Sybase DB2 sql2005 Office Word Excel Powerpoint Wps 认证考试 二级C语言 三级网络 程序员 网络工程师 思科认证

您当前的位置:飞诺网 >> c/c++ >> C++技术文章

Win32 临界区实现原理浅析

www.firnow.com    时间 : 2008-12-01  作者:佚名   编辑:辉辉 点击:   [ 评论 ]

Win32 临界区实现原理浅析

http://www.blogcn.com/user8/flier_lu/index.html?id=1205525&run=.0748049

    去年11月的MSDN杂志曾刊登过一篇文章 Break Free of Code Deadlocks in Critical Sections Under Windows ,Matt Pietrek 和 Russ Osterlund 两位对临界区(Critical Section)的内部实现做了一次简短的介绍,但点到为止,没有继续深入下去,当时给我的感觉就是痒痒的,呵呵,于是用IDA和SoftIce大致分析了一下临界区的实现,大致弄明白了原理后也就没有深究。现在乘着Win2k源码的东风,重新分析一下这块的内容,做个小小的总结吧 :P
     临界区(Critical Section)是Win32中提供的一种轻量级的同步机制,与互斥(Mutex)和事件(Event)等内核同步对象相比,临界区是完全在用户态维护的,所以仅能在同一进程内供线程同步使用,但也因此无需在使用时进行用户态和核心态之间的切换,工作效率大大高于其它同步机制。
     临界区的使用方法非常简单,使用 InitializeCriticalSection  InitializeCriticalSectionAndSpinCount 函数初始化一个 CRITICAL_SECTION 结构;使用 SetCriticalSectionSpinCount 函数设置临界区的Spin计数器;然后使用 EnterCriticalSection  TryEnterCriticalSection 获取临界区的所有权;完成需要同步的操作后,使用 LeaveCriticalSection 函数释放临界区;最后使用 DeleteCriticalSection 函数析构临界区结构。
     以下是MSDN中提供的一个简单的例子

 

 

以下为引用:

 // Global variable
 CRITICAL_SECTION CriticalSection;

 

 void main()
 {
     ...

     // Initialize the critical section one time only.
     if (!InitializeCriticalSectionAndSpinCount(&CriticalSection, 0x80000400) )
         return;
     ...

     // Release resources used by the critical section object.
     DeleteCriticalSection(&CriticalSection)
 }

 DWORD WINAPI ThreadProc( LPVOID lpParameter )
 {
     ...

     // Request ownership of the critical section.
     EnterCriticalSection(&CriticalSection);

     // Access the shared resource.

     // Release ownership of the critical section.
     LeaveCriticalSection(&CriticalSection);

     ...
 }
 


 

     首先看看构造和析构临界区结构的函数。
     InitializeCriticalSection 函数(ntosdll esource.c:1210)实际上是调用 InitializeCriticalSectionAndSpinCount 函数(resource.c:1266)完成功能的,只不过传入一个值为0的初始Spin计数器;InitializeCriticalSectionAndSpinCount 函数主要完成两部分工作:初始化 RTL_CRITICAL_SECTION 结构和 RTL_CRITICAL_SECTION_DEBUG 结构。前者是临界区的核心结构,下面将着重讨论;后者是调试用结构,Matt 那篇文章里面分析的很清楚了,我这儿就不罗嗦了 :P
     RTL_CRITICAL_SECTION结构在winnt.h中定义如下:

 

以下为引用:

 typedef struct _RTL_CRITICAL_SECTION {
     PRTL_CRITICAL_SECTION_DEBUG DebugInfo;

 

     //
     //  The following three fields control entering and exiting the critical
     //  section for the resource
     //

     LONG LockCount;
     LONG RecursionCount;
     HANDLE OwningThread;        // from the thread''s ClientId->UniqueThread
     HANDLE LockSemaphore;
     ULONG_PTR SpinCount;        // force size on 64-bit systems when packed
 } RTL_CRITICAL_SECTION, *PRTL_CRITICAL_SECTION;
 


 

     InitializeCriticalSectionAndSpinCount 函数中首先对临界区结构进行了初始化

     DebugInfo 字段指向初始化临界区时分配的RTL_CRITICAL_SECTION_DEBUG结构;
     LockCount 字段是临界区中最重要的字段,初始值为-1,当临界区被获取(Hold)时此字段大于等于0;
     RecursionCount 字段保存当前临界区所有者线程的获取缓冲区嵌套层数,初始值为0;
     OwningThread 字段保存当前临界区所有者线程的句柄,初始值为0;
     LockSemaphore 字段实际上是一个auto-reset的事件句柄,用于唤醒等待获取临界区的阻塞线程,初始值为0;
     SpinCount 字段用于在多处理器环境下完成轻量级的CPU见同步,单处理器时没有使用(初始值为0),多处理器时设置为SpinCount参数值(最大为MAX_SPIN_COUNT=0x00ffffff)。此外 RtlSetCriticalSectionSpinCount 函数(resource.c:1374)的代码与这儿设置SpinCount的代码完全一样。

   

 1 2
如果图片或页面不能正常显示请点击这里
C++技术文章推荐文章

文章评论