﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-Good Good code,Day Day up-文章分类-windows kernel</title><link>http://www.cppblog.com/dawnbreak/category/8979.html</link><description>PearLi's Blog</description><language>zh-cn</language><lastBuildDate>Fri, 14 Aug 2009 19:21:54 GMT</lastBuildDate><pubDate>Fri, 14 Aug 2009 19:21:54 GMT</pubDate><ttl>60</ttl><item><title>API Hook基本原理和实现[图文] </title><link>http://www.cppblog.com/dawnbreak/articles/93358.html</link><dc:creator>pear_li</dc:creator><author>pear_li</author><pubDate>Fri, 14 Aug 2009 10:28:00 GMT</pubDate><guid>http://www.cppblog.com/dawnbreak/articles/93358.html</guid><wfw:comment>http://www.cppblog.com/dawnbreak/comments/93358.html</wfw:comment><comments>http://www.cppblog.com/dawnbreak/articles/93358.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/dawnbreak/comments/commentRss/93358.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/dawnbreak/services/trackbacks/93358.html</trackback:ping><description><![CDATA[<strong>hook是什么？</strong> <br>&nbsp; &nbsp; windows系统下的编程，消息message的传递是贯穿其始终的。这个消息我们可以简单理解为一个有特定意义的整数，正如我们看过的老故事片中的&#8220;长江长江，我是黄河&#8221;一个含义。windows中定义的消息给初学者的印象似乎是&#8220;不计其数&#8221;的，常见的一部分消息在winuser.h头文件中定义。hook与消息有着非常密切的联系，它的中文含义是&#8220;钩子&#8221;，这样理解起来我们不难得出&#8220;<font color=red>hook是消息处理中的一个环节，用于监控消息在系统中的传递，并在这些消息到达最终的消息处理过程前，处 理某些特定的消息</font>&#8221;。这也是hook分为不同种类的原因。 <br>&nbsp; &nbsp; hook的这个本领，使它能够将自身的代码&#8220;融入&#8221;被hook住的程序的进程中，成为目标进程的一个部分。我们也知道，在windows2000以后的系统中，普通用户程序的进程空间都是独立的，程序的运行彼此间都不受干扰。这就使我们希望通过一个程序改变其他程序的某些行为的想法不能直接实现，但是hook的出现给我们开拓了解决此类问题的道路。 <br><br><strong>api hook是什么？</strong> <br>&nbsp; &nbsp; 在windows系统下编程，应该会接触到api函数的使用，常用的api函数大概有2000个左右。今天随着控件，stl等高效编程技术的出现，api的使用概率在普通的用户程序上就变得越来越小了。当诸如控件这些现成的手段不能实现的功能时，我们还需要借助api。最初有些人对某些api函数的功能不太满意，就产生了如何修改这些api，使之更好的服务于程序的想法，这样api hook就自然而然的出现了。我们可以通过api hook，改变一个系统api的原有功能。基本的方法就是通过hook&#8220;接触&#8221;到需要修改的api函数入口点，改变它的地址指向新的自定义的函数。api hook并不属于msdn上介绍的13类hook中的任何一种。<font color=red>所以说，api hook并不是什么特别不同的hook，它也需要通过基本的hook提高自己的权限，跨越不同进程间访问的限制，达到修改api函数地址的目的。</font>对于自身进程空间下使用到的api函数地址的修改，是不需要用到api hook技术就可以实现的。 <br><br><strong>api hook和pe格式的关系</strong> <br>api hook技术的难点，并不在于hook技术，初学者借助于资料&#8220;照葫芦画瓢&#8221;能够很容易就掌握hook的基本使用技术。但是如何修改api函数的入口地址？这就需要学习pe可执行文件（.exe，.dll等）如何被系统映射到进程空间中，这就需要学习pe格式的基本知识。windows已经提供了很多数据结构struct帮助我们访问pe格式，借助它们，我们就不要自己计算格式的具体字节位置这些繁琐的细节。但是从api hook的实现来看，pe格式的访问部分仍然是整个编程实现中最复杂的一部分，对于经常crack的朋友不在此列。 <br>假设我们已经了解了pe格式，那么我们在哪里修改api的函数入口点比较合适呢？这个就是输入符号表imported symbols table（间接）指向的输入符号地址。 <br>&nbsp; &nbsp;下面对于pe格式的介绍这一部分，对于没有接触过pe格式学习的朋友应该是看不太明白的，但我已经把精华部分提取出来了，学习了pe格式后再看这些就很容易了。 <br><br>pe格式的基本组成 <br>+-------------------+ <br>&nbsp; &nbsp; | DOS-stub&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp;|&nbsp; &nbsp; --DOS-头 <br>&nbsp; &nbsp; +-------------------+ <br>&nbsp; &nbsp; | file-header&nbsp; &nbsp; &nbsp; &nbsp;|&nbsp; &nbsp; --文件头 <br>&nbsp; &nbsp; +-------------------+ <br>&nbsp; &nbsp; | optional header&nbsp; &nbsp;|&nbsp; &nbsp; --可选头 <br>&nbsp; &nbsp; |- - - - - - - - - -| <br>&nbsp; &nbsp; |&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp;| <br>&nbsp; &nbsp; | data directories |&nbsp; &nbsp; --（可选头尾的）数据目录 <br>&nbsp; &nbsp; |&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp;| <br>&nbsp; &nbsp; +-------------------+ <br>&nbsp; &nbsp; |&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp;| <br>&nbsp; &nbsp; | section headers&nbsp; &nbsp;|&nbsp; &nbsp; &nbsp;--节头 <br>&nbsp; &nbsp; |&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp;| <br>&nbsp; &nbsp; +-------------------+ <br>&nbsp; &nbsp; |&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp;| <br>&nbsp; &nbsp; | section 1&nbsp; &nbsp; &nbsp; &nbsp; |&nbsp; &nbsp; &nbsp;--节1 <br>&nbsp; &nbsp; |&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp;| <br>&nbsp; &nbsp; +-------------------+ <br>&nbsp; &nbsp; |&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp;| <br>&nbsp; &nbsp; | section 2&nbsp; &nbsp; &nbsp; &nbsp; |&nbsp; &nbsp; &nbsp;--节2 <br>&nbsp; &nbsp; |&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp;| <br>&nbsp; &nbsp; +-------------------+ <br>&nbsp; &nbsp; |&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp;| <br>&nbsp; &nbsp; | ...&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; | <br>&nbsp; &nbsp; |&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp;| <br>&nbsp; &nbsp; +-------------------+ <br>&nbsp; &nbsp; |&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp;| <br>&nbsp; &nbsp; | section n&nbsp; &nbsp; &nbsp; &nbsp; |&nbsp; &nbsp; &nbsp;--节n <br>&nbsp; &nbsp; |&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp;| <br>&nbsp; &nbsp; +-------------------+ <br>&nbsp; &nbsp; 在上图中，我们需要从&#8220;可选头&#8221;尾的&#8220;数据目录&#8221;数组中的第二个元素——输入符号表的位置，它是一个IMAGE_DATA_DIRECTORY结构，从它中的VirtualAddress地址，&#8220;顺藤摸瓜&#8221;找到api函数的入口地点。 <br>&nbsp; &nbsp; 下图的简单说明如下： <br>OriginalFirstThunk 指向IMAGE_THUNK_DATA结构<font color=red>数组</font>，为方便只画了数组的一个元素，AddressOfData 指向IMAGE_IMPORT_BY_NAME结构。 <br>IMAGE_IMPORT_DESCRIPTOR数组：每个引入的dll文件都对应数组中的一个元素，以全0的元素（20个bytes的0）表示数组的结束 <br>IMAGE_THUNK_DATA32数组：同一组的以全0的元素（4个bytes的0）表示数组的结束，每个元素对应一个IMAGE_IMPORT_BY_NAME结构 <br>IMAGE_IMPORT_BY_NAME：如..@Consts@initialization$qqrv. 表示 <br>Unmangled Borland C++ Function: qualified function __fastcall Consts::initialization() <br><a title=点击查看大图 href="http://www.ccrun.com/!image/article/IMAGE_DATA_DIRECTORY.gif" target=_blank><img border=0 src="http://www.ccrun.com/!image/article/IMAGE_DATA_DIRECTORY.gif" width=550 height=250></a> <br>&nbsp; &nbsp; 为了减少这个图的大小，不得已将汇编和c++的结构都用上了。这个图是输入符号表初始化的情形，此时两个IMAGE_THUNK_DATA结构数组的对应元素都指向同一个IMAGE_IMPORT_BY_NAME结构。 <br>&nbsp; &nbsp; 程序加载到进程空间后，两个IMAGE_THUNK_DATA结构数组指向有所不同了。看下图： <br><br><img border=0 src="http://www.ccrun.com/!image/article/IMAGE_THUNK_DATA1.gif"> <br><span class=sp874>// 本文转自 C++Builder研究 - http://www.ccrun.com/article.asp?i=1036&amp;d=cf6de2</span><br>始化的，&#8220;两个结构都指向同一个IMAGE_IMPORT_BY_NAME&#8221;，此时还没有api函数地址 <br><br><img border=0 src="http://www.ccrun.com/!image/article/IMAGE_THUNK_DATA2.gif"> <br>当PE文件准备执行时，前图已转换成上图。一个结构指向不变，另一个出现api函数地址 <br><br>&nbsp; &nbsp; 如果PE文件从kernel32.dll中引入10个函数，那么IMAGE_IMPORT_DESCRIPTOR 结构的 Name1域包含指向字符串"kernel32.dll"的RVA，同时每个IMAGE_THUNK_DATA 数组有10个元素。(RVA是指相对地址，每一个可执行文件在加载到内存空间前，都以一个基址作为起点，其他地址以基址为准，均以相对地址表示。这样系统加载程序到不同的内存空间时，都可以方便的算出地址) <br>&nbsp; &nbsp; <font color=blue>上述这些结构可以在winnt.h头文件里查到。</font> <br><br><strong>具体编程实现</strong> <br>&nbsp; &nbsp; 我将手上的vc示例代码进行了适当修正，修改了一些资源泄漏的小问题，移植到c++builder6 &amp; update4上，经过测试已经可以完成基本的api hook功能。有几个知识点说明一下： <br>1、&nbsp; &nbsp; dll中共享内存变量的实现 <br>正常编译下的dll，它的变量使用到的内存是独立的。比如你同时运行两个调用了某个dll的用户程序，试图对某一个在dll中定义的全局变量修改赋值的时候，两个程序里的变量值仍然是不同的。 <br>共享的方法为：在.cpp文件（.h文件里如此设置会提示编译错误）的头部写上如上两行： <br>#pragma option -zRSHSEG&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; // 改变缺省数据段名 <br>#pragma option -zTSHCLASS&nbsp; &nbsp; &nbsp; &nbsp; // 改变缺省数据类名 <br><br>HINSTANCE hdll = NULL;&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; // 用来保存该动态连接库的句柄 <br>HHOOK hApiHook = NULL;&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; // 钩子句柄 <br>HHOOK hWndProc = NULL;&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; // 窗口过程钩子用来拦截SendMessage <br>int threadId = 0; <br><br>&nbsp; &nbsp; 另外建立一个与dll同名，不同后缀的def文件，如HookDll.def文件，写上： <br>LIBRARY HookDll.dll <br>EXPORTS <br>;... <br>SEGMENTS <br>&nbsp; &nbsp; SHSEG CLASS 'SHCLASS' SHARED <br>;end <br><br>&nbsp; &nbsp; 这样设置后在.cpp文件中定义的变量，如果进行了初始化，将进入&#8220;SHCLASS&#8221;共享内存段（如果不初始化，将不改变其默认段属性）。 <br><a title=点击查看大图 href="http://www.ccrun.com/!image/article/share.gif" target=_blank><img border=0 src="http://www.ccrun.com/!image/article/share.gif" width=550 height=127></a> <br>&nbsp; &nbsp; 上述的共享对于本示例代码并不是必须的，只是稍微演示了一下。 <br><br>2、&nbsp; &nbsp; api hook修改api函数入口点地址的时机 <br>&nbsp; &nbsp; 很显然，我们必须通过hook进入目标进程的地址空间后，再在位于该地址空间里的hook消息处理过程里修改输入符号表&#8220;指向&#8221;的api函数入口点地址，退出hook前也必须在这个消息处理过程里恢复原来的地址。只要我们牢记修改的过程发生在目标进程的地址空间中，就不会发生访问违例的错误了。 <br>&nbsp; &nbsp; 示例代码使用了WH_GETMESSAGE、WH_CALLWNDPROC两中hook来演示如何hook api，但WH_GETMESSAGE实际上并没有完成具体的功能。 <br>&nbsp; &nbsp; 为了让初学者尽快的掌握重点，我将代码进行了简化，是一个不健壮、不灵活的演示示例。 <br><br>3、&nbsp; &nbsp; 函数的内外部表现形式 <br>&nbsp; &nbsp; 例如api函数MessageBox，这个形式是我们通常用到的，但到了dll里，它的名字很可能出现了两个形式，一个是MessageBoxA，另一个是MessageBoxW，这是因为系统需要适应Ansi和Unicode编码的两种形式，我们不在函数尾端添加&#8220;A&#8221;或&#8220;W&#8221;，是不能hook到需要的函数的。 <br><br>4、&nbsp; &nbsp; 辅助pe格式查看工具 <br>&nbsp; &nbsp; PE Explorer是一个非常好的查看pe资源的工具，通过它可以验证自己手工计算的pe地址，可以更快的掌握pe格式。 <br>&nbsp; &nbsp; 调试器ollydbg也是非常好的辅助工具，例如查看输入符号表中的api函数。 <br><br>5、&nbsp; &nbsp; 程序文件列表 <br>dll基本文件：Hook.h，Hook.cpp，HookDll.def <br>client验证方基本文件：HookTest.h，HookTest.cpp，ApiHookTest.cpp <br><img border=0 src="http://www.ccrun.com/!image/article/dll.gif">&nbsp; &nbsp; <br><img border=0 src="http://www.ccrun.com/!image/article/client.gif"> <br><br>6、&nbsp; &nbsp; 实现的功能 <br>&nbsp; &nbsp; 对记事本的MessageBoxW函数进行了hook，先执行自定义的 <br>int WINAPI MyMessageBoxW(HWND hWnd, LPCWSTR M1, LPCWSTR M2, UINT M3) <br>{ <br>&nbsp; &nbsp; return oldMessageBoxW(hWnd, M1, L"my api hook", M3); <br>} <br>&nbsp; &nbsp; 从这里可以看到，由于目标进程空间中的执行线程并不知道你已经改变了api函数的实际入口地址，它在调用时仍旧将参数一成不变的压入堆栈（这个说法是汇编代码时看到的等价情形），事实上你已经提前接收到了函数调用的所有参数。这里就是篇首帖子的回复了。 <br><br><img border=0 src="http://www.ccrun.com/!image/article/m1.gif">&nbsp; &nbsp; <br>hook之前 <br><br><img border=0 src="http://www.ccrun.com/!image/article/m2.gif">&nbsp; &nbsp; <br>hook以后 <br><br><strong>示例代码</strong> <br>1、client验证方的代码非常简单。建立一个Application工程，在窗体上放一个memo（提示信息），两个button（一个SetHook，另一个RemoveHook）。 <br>void __fastcall TForm1::Button1Click(TObject *Sender) <br>{ <br>&nbsp; &nbsp; DWORD dwProcessId, dwThreadID; <br><br>&nbsp; &nbsp; HWND hWnd = FindWindow("Notepad", NULL); <br>&nbsp; &nbsp; if (!hWnd) <br>&nbsp; &nbsp; { <br>&nbsp; &nbsp; &nbsp; &nbsp; Memo1-&gt;Lines-&gt;Add("Nodepad is not found"); <br>&nbsp; &nbsp; } <br>&nbsp; &nbsp; else <br>&nbsp; &nbsp; { <br>&nbsp; &nbsp; &nbsp; &nbsp; dwThreadID = GetWindowThreadProcessId(hWnd, &amp;dwProcessId); <br>&nbsp; &nbsp; &nbsp; &nbsp; Memo1-&gt;Lines-&gt;Add(dwThreadID); <br>&nbsp; &nbsp; &nbsp; &nbsp; SetHook(dwThreadID); <br>&nbsp; &nbsp; } <br>} <br>//--------------------------------------------------------------------------- <br>void __fastcall TForm1::Button2Click(TObject *Sender) <br>{ <br>&nbsp; &nbsp; RemoveHook(); <br>} <br>//--------------------------------------------------------------------------- <br><br>2、api hook dll稍微复杂些，建立一个dll工程之后，修改之。代码中有一些函数并未用上，<font color=red>ReplaceApiAddress</font>是核心函数，完整代码提供下载： <br><a href="http://www.ccrun.com/!image/article/apihook.rar" target=_blank><u><font color=#0066cc>ApiHook.rar</font></u></a> <br><br><strong>参考文献</strong> <br>1、《iczelion汇编程序设计教程》pe专题部分 <br>2、《WINDOWS核心编程》第22章 <br>3、《PE文件格式 1.9版》汉译版，原著B. Luevelsmeyer <br>4、《跨进程API Hook》，出自http://blog.csdn.net/detrox/archive/2004/01/29/17511.aspx，作者detrox <br>5、《DLL木马注入程序》，出自http://www.mydown.com/code/245/245731.html <br>6、另有两vc6下的源代码包，APIHOOK与pw，因时间久远，出处不明。在此对原作者的辛勤工作表示真挚的谢意。 <!-- end of divCodeArea -->
<img src ="http://www.cppblog.com/dawnbreak/aggbug/93358.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/dawnbreak/" target="_blank">pear_li</a> 2009-08-14 18:28 <a href="http://www.cppblog.com/dawnbreak/articles/93358.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Sessions, Desktops and Windows Stations </title><link>http://www.cppblog.com/dawnbreak/articles/90278.html</link><dc:creator>pear_li</dc:creator><author>pear_li</author><pubDate>Thu, 16 Jul 2009 13:17:00 GMT</pubDate><guid>http://www.cppblog.com/dawnbreak/articles/90278.html</guid><wfw:comment>http://www.cppblog.com/dawnbreak/comments/90278.html</wfw:comment><comments>http://www.cppblog.com/dawnbreak/articles/90278.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/dawnbreak/comments/commentRss/90278.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/dawnbreak/services/trackbacks/90278.html</trackback:ping><description><![CDATA[<h2>Sessions, Desktops and Windows Stations </h2>
<div class=postcontent>
<p><img style="MARGIN: 0px 10px 5px 0px" align=left src="http://askperf.members.winisp.net/BlogImages/Windows_Logo.gif" width=85 height=75> Today we are going to briefly go over the basics of some concepts that can be pretty confusing even at the best of times - Sessions, Desktops and Windows Stations.&nbsp; So let's dive right in ...</p>
<p>A session consists of all of the processes and other system objects that represent a single user&#8217;s logon session.&nbsp; These objects include all windows, desktops and windows stations.&nbsp; A desktop is a session-specific paged pool area and loads in the kernel memory space.&nbsp; This area is where session-private GUI objects are allocated from.&nbsp; A windows station is basically a security boundary to contain desktops and processes.&nbsp; So, a session may contain more than one Windows Station and each windows station can have multiple desktops. </p>
<p>Only one windows station is permitted to interact with the user at the console; this is called Winsta0. Under Winsta0 there are three desktops loaded: Winlogon (the logon screen), Default (the user desktop) and Disconnect.&nbsp; All three of these have separate logical displays, which is why your main desktop disappears if you lock the workstation.&nbsp; When you lock the workstation, the display switches from Default to Winlogon and there is no user interaction between the two.&nbsp; In Windows Vista this is even a bit more extreme.&nbsp; When you get a UAC prompt for instance, it takes a screenshot of your Default desktop and then displays it dimmed out behind the UAC window in the foreground.&nbsp; The UAC window is part of the Secure Desktop (new for Vista and similar to the logon desktop) and will not allow you to interact with the Default desktop until you provide input. </p>
<p>Other windows stations exist that do not interact with the user.&nbsp; For example, services load under the &#8216;Service-0x0-3e7$&#8217; non-interactive windows station. The exceptions to this are services that need to interact with the console user, so these load into Winsta0 instead. </p>
<p>All pages mapped to a specific user use the same memory pages, but each user has their own session space mapped in virtual memory. Session space is divided into four different areas: </p>
<ul>
    <li>Session Structure &#8211; Memory management control structures including session Working Set List.
    <li>Session Image Space &#8211; holds a private copy of Win32k.sys modified data, a single copy of Win32k.sys code and unmodified data and various session drivers.
    <li>Session View Space &#8211; session mapped views including desktop heap
    <li>Session Paged Pool &#8211; paged pool memory used for this session </li>
</ul>
<p>As mentioned above, a desktop is an object under which a logical display surface loads.&nbsp; This contains windows, menus and hooks. Session 0 is the base session where services run and is typically also the console session.&nbsp; In Windows Vista this has been changed to exclusively run services, and the console session is typically Session 1.&nbsp; The diagrams below show the relationships between sessions, windows stations, desktops and services in Windows Vista as compared to earlier operating systems (this is from <a href="http://blogs.technet.com/askperf/archive/2007/04/27/application-compatibility-session-0-isolation.aspx" target=_blank>our earlier post on Session 0 Application Compatibility Issues</a>)</p>
<table border=0 cellSpacing=0 cellPadding=2 width=400 unselectable="on">
    <tbody>
        <tr>
            <td vAlign=top width=398><img style="MARGIN: 0px 10px 5px 0px" border=0 alt=image src="http://blogs.technet.com/blogfiles/askperf/WindowsLiveWriter/SessionsDesktopsandWindowsStations_6A91/image_5aef41e5-0495-4e29-9349-620a6f95bf9c.png" width=240 height=237> <br><em>Session 0 in Windows XP / Windows Server 2003</em></td>
        </tr>
        <tr>
            <td vAlign=top width=398><br><img style="MARGIN: 0px 10px 5px 0px" border=0 alt=image src="http://blogs.technet.com/blogfiles/askperf/WindowsLiveWriter/SessionsDesktopsandWindowsStations_6A91/image_44123d8a-343f-4cb1-9074-09a953835594.png" width=720 height=290> <br><em>Session 0 / Session 1 in Windows Vista </em></td>
        </tr>
    </tbody>
</table>
<p>So now let's dig a little deeper using an example.&nbsp; In the diagram below, we are looking at Session 0 with a user logged in named Bob.&nbsp; As you can see, Winsta0 contains both processes from the user console session as well as any service that is marked as Interactive.&nbsp; In this case, that includes Winlogon.exe, Explorer.exe and others that need to interact with the user.&nbsp; The Service-0x0-3e7$ windows station owns any service that loads under Local System and is non-interactive.&nbsp; In this case I have shown Services.exe.&nbsp; As you can see by the connecting bars, it is possible for processes from different virtual sessions to load into a single windows station.&nbsp; The SQL process loads under its own windows station and credentials, so it is not included in either of the other windows stations.</p>
<p><img style="MARGIN: 0px 10px 5px 0px" alt=image src="http://blogs.technet.com/blogfiles/askperf/WindowsLiveWriter/SessionsDesktopsandWindowsStations_6A91/image_14c7b24d-d3e0-4c6d-b3f5-c98707077cf6.png" width=445 height=327></p>
<p>So, to reiterate what is going on in the diagram above: </p>
<ol>
    <li>The whole diagram is Session 0.
    <li>Processes that start under the Bob account all load in Winsta0.
    <li>Interactive processes that start under Local System load in Winsta0
    <li>Non-interactive processes that start under Local System load in the Service-0x0-3e7% windows station
    <li>Processes that start under their own credentials start in their own windows station (like SQL) </li>
</ol>
<p>A single desktop object will have a single desktop heap set aside for it.&nbsp; This heap stores various user interface objects, such as the windows, menus and hooks.&nbsp; When an application needs to draw a user interface object, it calls User32.dll to allocate this object. As I am sure you can guess, each of these interface elements requires resources out of desktop heap.&nbsp; If the desktop heap becomes depleted, you will get symptoms such as a corrupt display or other anomalies.&nbsp; Also, if the Session View Space becomes depleted, it will not be able to create more desktop heaps. Either of these of course is very bad. This is partially why you can still get Out Of Memory errors even on a machine with a lot of free RAM. </p>
<p>When this occurs, you may get initialization errors in addition to visual corruption.&nbsp; A typical error you may see is 0xc0000142, which means STATUS_DLL_INIT_FAILED.&nbsp; You can tell if the problem is with a single desktop heap or the entire session based on the symptom; if the desktop heap is depleted, you will only see the problem with processes that are out of heap.&nbsp; If the Session View Space is depleted, you will have a problem with that entire session. </p>
<p>Win32k.sys has a fixed kernel address space of 48MB set aside for desktop heaps.&nbsp; With Terminal Services, this space is shared with per-session storage, so that leaves 20MB for desktop heaps.&nbsp; So, as you can see, it is possible to run out of desktop heap resources easier on a terminal server than a standard machine.&nbsp; This is true for pre-Vista operating systems.&nbsp; In Windows Vista and Windows Server 2008 desktop heap is allocated dynamically and the 48MB constraint is not there.</p>
<p>There is a registry setting that allows limited modification of how this memory is handled:<em> </em>In the <em>HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems</em> key, look for the </p>
<p><em>Windows</em> value.&nbsp; There's a long string for this value that will look similar to this: <em>%SystemRoot%system32csrss.exe ObjectDirectory=Windows SharedSection=1024,3072,512 Windows </em>&#8230; </p>
<p>The portion of interest is "SharedSection=1024,3072,512".&nbsp; The three values under Shared Section determines how much memory in kilobytes (KB) is allocated to each component of the desktop heap.&nbsp; At this point, there is a major caveat here: <font color=#ff0000>Please do not modify these values on a whim. Changing the second or third value too high can put you in a no-boot situation due to the kernel not being able to allocate memory properly to even get Session 0 set up</font>.&nbsp; Values up to about 8mb are generally safe, but may be pushing it, and frankly settings that high are not usually needed unless an installed program is misbehaving in the first place.&nbsp; We recommend raising these values in 512kb increments and only enough to alleviate whatever problem you are experiencing. </p>
<p>The first value is the shared heap size, common to all desktops. It's used to store the global handle table and shared system settings. By default, it's set to 1024KB. You generally do not need to modify this value.&nbsp; The second value is the desktop heap size for each desktop associated with the "interactive" window station.&nbsp; It is used to store user objects like hooks, menus, strings and windows.&nbsp; By default, it's set to 3072KB.&nbsp; The more users that log into the system, the more desktops are created.&nbsp; Consequently, the total "interactive" desktop heap size will increase to reflect the number of desktops created.&nbsp; However, each desktop will only have an "interactive" desktop heap of 3072KB.&nbsp; The third value is the desktop heap size for each desktop associated with the "non-interactive" window station.&nbsp; By default, it's set to 512KB. But if this value is not present, the size of the "non-interactive" window station will be the same as that of the "interactive" window station. </p>
<p>Every service process created under a user account will be given a new desktop in a "non-interactive" window station created by the Service Control Manager (SCM).&nbsp; Therefore, each of these services will consume the amount of desktop heap, as specified in the third SharedSection value.&nbsp; The total desktop heap used in both interactive and non-interactive window stations must fit into the 48MB system-wide buffer.&nbsp; Consequently, decreasing the second or third SharedSection values will increase the number of desktops that can be created. However, it will reduce the number of hooks, menus, strings and windows that can be created within each desktop.&nbsp; Conversely, increasing the second of third SharedSection values will reduce the number of desktops that can be created and increases the number of hooks, menus, strings and windows that can be created within each desktop.&nbsp; Also, increasing the third SharedSection value will reduce the number of user account services that can run successfully on the system. </p>
<p>So, hopefully this has shed at least a little light on how Sessions, Windows Stations and Desktops interact with each other.&nbsp; The following MS articles all talk about various aspects of this subject.&nbsp; There's also an in-depth blog post on the NT Debugging blog on Desktop Heap. </p>
<p>Additional Resources: </p>
<ul>
    <li><a href="http://support.microsoft.com/default.aspx?scid=kb;EN-US;126962" target=_blank>KB126962 "Out of Memory" error message appears when you have a large number of programs running</a>
    <li><a href="http://support.microsoft.com/default.aspx?scid=kb;EN-US;142676" target=_blank>KB142676 Overcoming User32.dll Initialization Failure Errors</a>
    <li><a href="http://blogs.msdn.com/ntdebugging/archive/2007/01/04/desktop-heap-overview.aspx" target=_blank>NT Debugging Blog: Desktop Heap Overview</a> </li>
</ul>
</div>
<img src ="http://www.cppblog.com/dawnbreak/aggbug/90278.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/dawnbreak/" target="_blank">pear_li</a> 2009-07-16 21:17 <a href="http://www.cppblog.com/dawnbreak/articles/90278.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>创建一块命名的进程共享存储空间</title><link>http://www.cppblog.com/dawnbreak/articles/68038.html</link><dc:creator>pear_li</dc:creator><author>pear_li</author><pubDate>Thu, 27 Nov 2008 14:51:00 GMT</pubDate><guid>http://www.cppblog.com/dawnbreak/articles/68038.html</guid><wfw:comment>http://www.cppblog.com/dawnbreak/comments/68038.html</wfw:comment><comments>http://www.cppblog.com/dawnbreak/articles/68038.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/dawnbreak/comments/commentRss/68038.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/dawnbreak/services/trackbacks/68038.html</trackback:ping><description><![CDATA[<p>多个进程可以通过在系统页面文件中存储的内存映射文件来实现多个进程共享数据。</p>
<h4><a name=first_process></a>第一个进程</h4>
<p>The first process creates the file mapping object by calling the <a href="ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.chs/memory/base/createfilemapping.htm"><strong><u><font color=#800080>CreateFileMapping</font></u></strong></a> function with INVALID_HANDLE_VALUE and a name for the object. By using the PAGE_READWRITE flag, the process has read/write permission to the memory through any file views that are created. </p>
<p>Then the process uses the file mapping object handle that <a href="ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.chs/memory/base/createfilemapping.htm"><strong><u><font color=#800080>CreateFileMapping</font></u></strong></a> returns in a call to <a href="ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.chs/memory/base/mapviewoffile.htm"><strong><u><font color=#0066cc>MapViewOfFile</font></u></strong></a> to create a view of the file in the process address space. The <strong>MapViewOfFile</strong> function returns a pointer to the file view, pBuf. The process then uses the <a href="ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.chs/memory/base/copymemory.htm"><strong><u><font color=#0066cc>CopyMemory</font></u></strong></a> function to write a string to the view that can be accessed by other processes.</p>
<p>When the process no longer needs access to the file mapping object, it should call the <mshelp:link tabIndex=0 keywords="base.closehandle" errorURL="../common/badjump.htm"><strong>CloseHandle</strong></mshelp:link> function. When all handles are closed, the system can free the section of the paging file that the object uses.</p>
第一个进程通过调用以INVALID_HANDLE_VALUE 为参数的CreateFileMapping方法创建一个命名的内存映射文件对象。通过使用PAGE_READWRITE 标识，进程可通过任何以创建文件视图获得文件读写权限。<br>然后进程使用<a href="ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.chs/memory/base/createfilemapping.htm"><strong><u><font color=#800080>CreateFileMapping</font></u></strong></a> 返回的对象句柄作为参数调用<a href="ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.chs/memory/base/mapviewoffile.htm"><strong><u><font color=#0066cc>MapViewOfFile</font></u></strong></a> 方法在进程地址空间内创建一个文件视图。<a href="ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.chs/memory/base/mapviewoffile.htm"><strong><u><font color=#0066cc>MapViewOfFile</font></u></strong></a> 返回一个文件视图的指针。进程可以调用<a href="ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.chs/memory/base/copymemory.htm"><strong><u><font color=#0066cc>CopyMemory</font></u></strong></a> 方法写一段字串到文件视图，而该视图可以被其他进程访问。<br>当进程不在需要访文件映射对象是，应该调用<strong>CloseHandle</strong> 方法。当所有的进程都关闭后，系统会释放对象所使用的页面文件。<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">&nbsp;1</span><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">windows.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;2</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">stdio.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;3</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">conio.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;4</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br></span><span style="COLOR: #008080">&nbsp;5</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;BUF_SIZE&nbsp;256</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;6</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>TCHAR&nbsp;szName[]</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">TEXT(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Global\\MyFileMappingObject</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">&nbsp;7</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>TCHAR&nbsp;szMsg[]</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">TEXT(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Message&nbsp;from&nbsp;first&nbsp;process</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">&nbsp;8</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br></span><span style="COLOR: #008080">&nbsp;9</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main()<br></span><span style="COLOR: #008080">10</span><span style="COLOR: #000000"><img id=Codehighlighter1_197_1343_Open_Image onclick="this.style.display='none'; Codehighlighter1_197_1343_Open_Text.style.display='none'; Codehighlighter1_197_1343_Closed_Image.style.display='inline'; Codehighlighter1_197_1343_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_197_1343_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_197_1343_Closed_Text.style.display='none'; Codehighlighter1_197_1343_Open_Image.style.display='inline'; Codehighlighter1_197_1343_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_197_1343_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_197_1343_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">11</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;HANDLE&nbsp;hMapFile;<br></span><span style="COLOR: #008080">12</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;LPCTSTR&nbsp;pBuf;<br></span><span style="COLOR: #008080">13</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br></span><span style="COLOR: #008080">14</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;hMapFile&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;CreateFileMapping(<br></span><span style="COLOR: #008080">15</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;INVALID_HANDLE_VALUE,&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;use&nbsp;paging&nbsp;file使用系统页面文件</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">16</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NULL,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;default&nbsp;security&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">17</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PAGE_READWRITE,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;read/write&nbsp;access</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">18</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;max.&nbsp;object&nbsp;size&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">19</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BUF_SIZE,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;buffer&nbsp;size&nbsp;&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">20</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;szName);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;name&nbsp;of&nbsp;mapping&nbsp;object</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">21</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;<br></span><span style="COLOR: #008080">22</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(hMapFile&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;NULL)&nbsp;<br></span><span style="COLOR: #008080">23</span><span style="COLOR: #000000"><img id=Codehighlighter1_678_793_Open_Image onclick="this.style.display='none'; Codehighlighter1_678_793_Open_Text.style.display='none'; Codehighlighter1_678_793_Closed_Image.style.display='inline'; Codehighlighter1_678_793_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_678_793_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_678_793_Closed_Text.style.display='none'; Codehighlighter1_678_793_Open_Image.style.display='inline'; Codehighlighter1_678_793_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_678_793_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_678_793_Open_Text><span style="COLOR: #000000">{&nbsp;<br></span><span style="COLOR: #008080">24</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Could&nbsp;not&nbsp;create&nbsp;file&nbsp;mapping&nbsp;object&nbsp;(%d).\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;<br></span><span style="COLOR: #008080">25</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GetLastError());<br></span><span style="COLOR: #008080">26</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">27</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">28</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;pBuf&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(LPTSTR)&nbsp;MapViewOfFile(hMapFile,&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;handle&nbsp;to&nbsp;map&nbsp;object</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">29</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FILE_MAP_ALL_ACCESS,&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;read/write&nbsp;permission</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">30</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">31</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">32</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BUF_SIZE);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">33</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;<br></span><span style="COLOR: #008080">34</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(pBuf&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;NULL)&nbsp;<br></span><span style="COLOR: #008080">35</span><span style="COLOR: #000000"><img id=Codehighlighter1_1099_1205_Open_Image onclick="this.style.display='none'; Codehighlighter1_1099_1205_Open_Text.style.display='none'; Codehighlighter1_1099_1205_Closed_Image.style.display='inline'; Codehighlighter1_1099_1205_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1099_1205_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1099_1205_Closed_Text.style.display='none'; Codehighlighter1_1099_1205_Open_Image.style.display='inline'; Codehighlighter1_1099_1205_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_1099_1205_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_1099_1205_Open_Text><span style="COLOR: #000000">{&nbsp;<br></span><span style="COLOR: #008080">36</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Could&nbsp;not&nbsp;map&nbsp;view&nbsp;of&nbsp;file&nbsp;(%d).\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;<br></span><span style="COLOR: #008080">37</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GetLastError());&nbsp;<br></span><span style="COLOR: #008080">38</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">39</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">40</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br></span><span style="COLOR: #008080">41</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">42</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;CopyMemory((PVOID)pBuf,&nbsp;szMsg,&nbsp;strlen(szMsg));<br></span><span style="COLOR: #008080">43</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;_getch();<br></span><span style="COLOR: #008080">44</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br></span><span style="COLOR: #008080">45</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;UnmapViewOfFile(pBuf);<br></span><span style="COLOR: #008080">46</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br></span><span style="COLOR: #008080">47</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;CloseHandle(hMapFile);<br></span><span style="COLOR: #008080">48</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br></span><span style="COLOR: #008080">49</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">50</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">51</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<br>
<h4><a name=second_process></a>第二个进程</h4>
<p>A second process can access the string written to the shared memory by the first process by calling the <a href="ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.chs/memory/base/openfilemapping.htm"><strong>OpenFileMapping</strong></a> function specifying the same name for the mapping object as the first process. Then it can use the <strong>MapViewOfFile</strong> function to obtain a pointer to the file view, pBuf. The process can display this string as it would any other string. In this example, the message box displayed contains the message "Message from first process" that was written by the first process.<br>第二个进程可以通过<a href="ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.chs/memory/base/openfilemapping.htm"><strong>OpenFileMapping</strong></a> 方法并且指定与第一个进程中相同的内存映射文件对象名称来访问共享内存中的字串。然后可通过<strong>MapViewOfFile</strong> 方法得到文件视图的指针pBuf<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">&nbsp;1</span><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">windows.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;2</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">stdio.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;3</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">conio.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;4</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br></span><span style="COLOR: #008080">&nbsp;5</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;BUF_SIZE&nbsp;256</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;6</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>TCHAR&nbsp;szName[]</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">TEXT(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Global\\MyFileMappingObject</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">&nbsp;7</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br></span><span style="COLOR: #008080">&nbsp;8</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main()<br></span><span style="COLOR: #008080">&nbsp;9</span><span style="COLOR: #000000"><img id=Codehighlighter1_147_1075_Open_Image onclick="this.style.display='none'; Codehighlighter1_147_1075_Open_Text.style.display='none'; Codehighlighter1_147_1075_Closed_Image.style.display='inline'; Codehighlighter1_147_1075_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_147_1075_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_147_1075_Closed_Text.style.display='none'; Codehighlighter1_147_1075_Open_Image.style.display='inline'; Codehighlighter1_147_1075_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_147_1075_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_147_1075_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">10</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;HANDLE&nbsp;hMapFile;<br></span><span style="COLOR: #008080">11</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;LPCTSTR&nbsp;pBuf;<br></span><span style="COLOR: #008080">12</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br></span><span style="COLOR: #008080">13</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;hMapFile&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;OpenFileMapping(<br></span><span style="COLOR: #008080">14</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FILE_MAP_ALL_ACCESS,&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;read/write&nbsp;access</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">15</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FALSE,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;do&nbsp;not&nbsp;inherit&nbsp;the&nbsp;name</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">16</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;szName);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;name&nbsp;of&nbsp;mapping&nbsp;object&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">17</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;<br></span><span style="COLOR: #008080">18</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(hMapFile&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;NULL)&nbsp;<br></span><span style="COLOR: #008080">19</span><span style="COLOR: #000000"><img id=Codehighlighter1_450_563_Open_Image onclick="this.style.display='none'; Codehighlighter1_450_563_Open_Text.style.display='none'; Codehighlighter1_450_563_Closed_Image.style.display='inline'; Codehighlighter1_450_563_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_450_563_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_450_563_Closed_Text.style.display='none'; Codehighlighter1_450_563_Open_Image.style.display='inline'; Codehighlighter1_450_563_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_450_563_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_450_563_Open_Text><span style="COLOR: #000000">{&nbsp;<br></span><span style="COLOR: #008080">20</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Could&nbsp;not&nbsp;open&nbsp;file&nbsp;mapping&nbsp;object&nbsp;(%d).\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;<br></span><span style="COLOR: #008080">21</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GetLastError());<br></span><span style="COLOR: #008080">22</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">23</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;<br></span><span style="COLOR: #008080">24</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;<br></span><span style="COLOR: #008080">25</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;pBuf&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(LPTSTR)&nbsp;MapViewOfFile(hMapFile,&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;handle&nbsp;to&nbsp;map&nbsp;object</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">26</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FILE_MAP_ALL_ACCESS,&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;read/write&nbsp;permission</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">27</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">28</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">29</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BUF_SIZE);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">30</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;<br></span><span style="COLOR: #008080">31</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(pBuf&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;NULL)&nbsp;<br></span><span style="COLOR: #008080">32</span><span style="COLOR: #000000"><img id=Codehighlighter1_845_951_Open_Image onclick="this.style.display='none'; Codehighlighter1_845_951_Open_Text.style.display='none'; Codehighlighter1_845_951_Closed_Image.style.display='inline'; Codehighlighter1_845_951_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_845_951_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_845_951_Closed_Text.style.display='none'; Codehighlighter1_845_951_Open_Image.style.display='inline'; Codehighlighter1_845_951_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_845_951_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_845_951_Open_Text><span style="COLOR: #000000">{&nbsp;<br></span><span style="COLOR: #008080">33</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Could&nbsp;not&nbsp;map&nbsp;view&nbsp;of&nbsp;file&nbsp;(%d).\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;<br></span><span style="COLOR: #008080">34</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GetLastError());&nbsp;<br></span><span style="COLOR: #008080">35</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">36</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">37</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br></span><span style="COLOR: #008080">38</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;MessageBox(NULL,&nbsp;pBuf,&nbsp;TEXT(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Process2</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">),&nbsp;MB_OK);<br></span><span style="COLOR: #008080">39</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br></span><span style="COLOR: #008080">40</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;UnmapViewOfFile(pBuf);<br></span><span style="COLOR: #008080">41</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br></span><span style="COLOR: #008080">42</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;CloseHandle(hMapFile);<br></span><span style="COLOR: #008080">43</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;<br></span><span style="COLOR: #008080">44</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">45</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">46</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<br>更多内容参照<a href="http://baike.baidu.com/view/394293.htm">http://baike.baidu.com/view/394293.htm</a>
<img src ="http://www.cppblog.com/dawnbreak/aggbug/68038.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/dawnbreak/" target="_blank">pear_li</a> 2008-11-27 22:51 <a href="http://www.cppblog.com/dawnbreak/articles/68038.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用线程局部存储TLS</title><link>http://www.cppblog.com/dawnbreak/articles/68027.html</link><dc:creator>pear_li</dc:creator><author>pear_li</author><pubDate>Thu, 27 Nov 2008 13:46:00 GMT</pubDate><guid>http://www.cppblog.com/dawnbreak/articles/68027.html</guid><wfw:comment>http://www.cppblog.com/dawnbreak/comments/68027.html</wfw:comment><comments>http://www.cppblog.com/dawnbreak/articles/68027.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/dawnbreak/comments/commentRss/68027.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/dawnbreak/services/trackbacks/68027.html</trackback:ping><description><![CDATA[<p><a href="ms-help://MS.MSDNQTR.v90.chs/dllproc/base/thread_local_storage.htm"><u><font color=#0066cc>Thread local storage</font></u></a> (TLS)统一进程的多个线程可以通过由TlsAlloc方法返回的索引值在线程自身的空间内存储和取回一个值。在以下这个例子里，索引值在进程开始时创建，当各个线程启动时，会各自申请一块动态内存并且将内存指针通过TlsSetValue方法存储到各自的TLS空间中（由先前的索引值标定）。CommonFunc方法使用TlsGetValue方法通过索引取得数据指针。在各个线程结束前，释放动态内存块。在进程结束见，调用TlsFree方法释放索引。<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">&nbsp;1</span><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">windows.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;<br></span><span style="COLOR: #008080">&nbsp;2</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">stdio.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;<br></span><span style="COLOR: #008080">&nbsp;3</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;<br></span><span style="COLOR: #008080">&nbsp;4</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;THREADCOUNT&nbsp;4&nbsp;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;5</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>DWORD&nbsp;dwTlsIndex;&nbsp;<br></span><span style="COLOR: #008080">&nbsp;6</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;<br></span><span style="COLOR: #008080">&nbsp;7</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>VOID&nbsp;ErrorExit(LPSTR);&nbsp;<br></span><span style="COLOR: #008080">&nbsp;8</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;<br></span><span style="COLOR: #008080">&nbsp;9</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>VOID&nbsp;CommonFunc(VOID)&nbsp;<br></span><span style="COLOR: #008080">10</span><span style="COLOR: #000000"><img id=Codehighlighter1_137_513_Open_Image onclick="this.style.display='none'; Codehighlighter1_137_513_Open_Text.style.display='none'; Codehighlighter1_137_513_Closed_Image.style.display='inline'; Codehighlighter1_137_513_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_137_513_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_137_513_Closed_Text.style.display='none'; Codehighlighter1_137_513_Open_Image.style.display='inline'; Codehighlighter1_137_513_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_137_513_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_137_513_Open_Text><span style="COLOR: #000000">{&nbsp;<br></span><span style="COLOR: #008080">11</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;LPVOID&nbsp;lpvData;&nbsp;<br></span><span style="COLOR: #008080">12</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;<br></span><span style="COLOR: #008080">13</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Retrieve&nbsp;a&nbsp;data&nbsp;pointer&nbsp;for&nbsp;the&nbsp;current&nbsp;thread.&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">14</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;<br></span><span style="COLOR: #008080">15</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;lpvData&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;TlsGetValue(dwTlsIndex);&nbsp;<br></span><span style="COLOR: #008080">16</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;((lpvData&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)&nbsp;</span><span style="COLOR: #000000">&amp;&amp;</span><span style="COLOR: #000000">&nbsp;(GetLastError()&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;ERROR_SUCCESS))&nbsp;<br></span><span style="COLOR: #008080">17</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ErrorExit(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">TlsGetValue&nbsp;error</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);&nbsp;<br></span><span style="COLOR: #008080">18</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;<br></span><span style="COLOR: #008080">19</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Use&nbsp;the&nbsp;data&nbsp;stored&nbsp;for&nbsp;the&nbsp;current&nbsp;thread.&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">20</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;<br></span><span style="COLOR: #008080">21</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">common:&nbsp;thread&nbsp;%d:&nbsp;lpvData=%lx\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;<br></span><span style="COLOR: #008080">22</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GetCurrentThreadId(),&nbsp;lpvData);&nbsp;<br></span><span style="COLOR: #008080">23</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;<br></span><span style="COLOR: #008080">24</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;Sleep(</span><span style="COLOR: #000000">5000</span><span style="COLOR: #000000">);&nbsp;<br></span><span style="COLOR: #008080">25</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">&nbsp;<br></span><span style="COLOR: #008080">26</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;<br></span><span style="COLOR: #008080">27</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>DWORD&nbsp;WINAPI&nbsp;ThreadFunc(VOID)&nbsp;<br></span><span style="COLOR: #008080">28</span><span style="COLOR: #000000"><img id=Codehighlighter1_549_1020_Open_Image onclick="this.style.display='none'; Codehighlighter1_549_1020_Open_Text.style.display='none'; Codehighlighter1_549_1020_Closed_Image.style.display='inline'; Codehighlighter1_549_1020_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_549_1020_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_549_1020_Closed_Text.style.display='none'; Codehighlighter1_549_1020_Open_Image.style.display='inline'; Codehighlighter1_549_1020_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_549_1020_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_549_1020_Open_Text><span style="COLOR: #000000">{&nbsp;<br></span><span style="COLOR: #008080">29</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;LPVOID&nbsp;lpvData;&nbsp;<br></span><span style="COLOR: #008080">30</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;<br></span><span style="COLOR: #008080">31</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Initialize&nbsp;the&nbsp;TLS&nbsp;index&nbsp;for&nbsp;this&nbsp;thread.&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">32</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;<br></span><span style="COLOR: #008080">33</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;lpvData&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(LPVOID)&nbsp;LocalAlloc(LPTR,&nbsp;</span><span style="COLOR: #000000">256</span><span style="COLOR: #000000">);&nbsp;<br></span><span style="COLOR: #008080">34</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">&nbsp;TlsSetValue(dwTlsIndex,&nbsp;lpvData))&nbsp;<br></span><span style="COLOR: #008080">35</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ErrorExit(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">TlsSetValue&nbsp;error</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);&nbsp;<br></span><span style="COLOR: #008080">36</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;<br></span><span style="COLOR: #008080">37</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">thread&nbsp;%d:&nbsp;lpvData=%lx\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;GetCurrentThreadId(),&nbsp;lpvData);&nbsp;<br></span><span style="COLOR: #008080">38</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;<br></span><span style="COLOR: #008080">39</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;CommonFunc();&nbsp;<br></span><span style="COLOR: #008080">40</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;<br></span><span style="COLOR: #008080">41</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Release&nbsp;the&nbsp;dynamic&nbsp;memory&nbsp;before&nbsp;the&nbsp;thread&nbsp;returns.&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">42</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;<br></span><span style="COLOR: #008080">43</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;lpvData&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;TlsGetValue(dwTlsIndex);&nbsp;<br></span><span style="COLOR: #008080">44</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(lpvData&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)&nbsp;<br></span><span style="COLOR: #008080">45</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LocalFree((HLOCAL)&nbsp;lpvData);&nbsp;<br></span><span style="COLOR: #008080">46</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;<br></span><span style="COLOR: #008080">47</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;<br></span><span style="COLOR: #008080">48</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">&nbsp;<br></span><span style="COLOR: #008080">49</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;<br></span><span style="COLOR: #008080">50</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main(VOID)&nbsp;<br></span><span style="COLOR: #008080">51</span><span style="COLOR: #000000"><img id=Codehighlighter1_1041_1964_Open_Image onclick="this.style.display='none'; Codehighlighter1_1041_1964_Open_Text.style.display='none'; Codehighlighter1_1041_1964_Closed_Image.style.display='inline'; Codehighlighter1_1041_1964_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_1041_1964_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1041_1964_Closed_Text.style.display='none'; Codehighlighter1_1041_1964_Open_Image.style.display='inline'; Codehighlighter1_1041_1964_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_1041_1964_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_1041_1964_Open_Text><span style="COLOR: #000000">{&nbsp;<br></span><span style="COLOR: #008080">52</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;DWORD&nbsp;IDThread;&nbsp;<br></span><span style="COLOR: #008080">53</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;HANDLE&nbsp;hThread[THREADCOUNT];&nbsp;<br></span><span style="COLOR: #008080">54</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i;&nbsp;<br></span><span style="COLOR: #008080">55</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;<br></span><span style="COLOR: #008080">56</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Allocate&nbsp;a&nbsp;TLS&nbsp;index.&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">57</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;<br></span><span style="COLOR: #008080">58</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;((dwTlsIndex&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;TlsAlloc())&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;TLS_OUT_OF_INDEXES)&nbsp;<br></span><span style="COLOR: #008080">59</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ErrorExit(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">TlsAlloc&nbsp;failed</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);&nbsp;<br></span><span style="COLOR: #008080">60</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;<br></span><span style="COLOR: #008080">61</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Create&nbsp;multiple&nbsp;threads.&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">62</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;<br></span><span style="COLOR: #008080">63</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">&nbsp;(i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">&nbsp;THREADCOUNT;&nbsp;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)&nbsp;<br></span><span style="COLOR: #008080">64</span><span style="COLOR: #000000"><img id=Codehighlighter1_1306_1830_Open_Image onclick="this.style.display='none'; Codehighlighter1_1306_1830_Open_Text.style.display='none'; Codehighlighter1_1306_1830_Closed_Image.style.display='inline'; Codehighlighter1_1306_1830_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1306_1830_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1306_1830_Closed_Text.style.display='none'; Codehighlighter1_1306_1830_Open_Image.style.display='inline'; Codehighlighter1_1306_1830_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_1306_1830_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_1306_1830_Open_Text><span style="COLOR: #000000">{&nbsp;<br></span><span style="COLOR: #008080">65</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hThread[i]&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;CreateThread(NULL,&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;default&nbsp;security&nbsp;attributes&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">66</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;use&nbsp;default&nbsp;stack&nbsp;size&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">67</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(LPTHREAD_START_ROUTINE)&nbsp;ThreadFunc,&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;thread&nbsp;function&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">68</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NULL,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;no&nbsp;thread&nbsp;function&nbsp;argument&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">69</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;use&nbsp;default&nbsp;creation&nbsp;flags&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">70</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">IDThread);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;returns&nbsp;thread&nbsp;identifier&nbsp;<br></span><span style="COLOR: #008080">71</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;<br></span><span style="COLOR: #008080">72</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Check&nbsp;the&nbsp;return&nbsp;value&nbsp;for&nbsp;success.&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">73</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(hThread[i]&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;NULL)&nbsp;<br></span><span style="COLOR: #008080">74</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ErrorExit(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">CreateThread&nbsp;error\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);&nbsp;<br></span><span style="COLOR: #008080">75</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;<br></span><span style="COLOR: #008080">76</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;<br></span><span style="COLOR: #008080">77</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">&nbsp;(i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">&nbsp;THREADCOUNT;&nbsp;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)&nbsp;<br></span><span style="COLOR: #008080">78</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WaitForSingleObject(hThread[i],&nbsp;INFINITE);&nbsp;<br></span><span style="COLOR: #008080">79</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;<br></span><span style="COLOR: #008080">80</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;TlsFree(dwTlsIndex);<br></span><span style="COLOR: #008080">81</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br></span><span style="COLOR: #008080">82</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;<br></span><span style="COLOR: #008080">83</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">&nbsp;<br></span><span style="COLOR: #008080">84</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;<br></span><span style="COLOR: #008080">85</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>VOID&nbsp;ErrorExit&nbsp;(LPSTR&nbsp;lpszMessage)&nbsp;<br></span><span style="COLOR: #008080">86</span><span style="COLOR: #000000"><img id=Codehighlighter1_2005_2071_Open_Image onclick="this.style.display='none'; Codehighlighter1_2005_2071_Open_Text.style.display='none'; Codehighlighter1_2005_2071_Closed_Image.style.display='inline'; Codehighlighter1_2005_2071_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_2005_2071_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_2005_2071_Closed_Text.style.display='none'; Codehighlighter1_2005_2071_Open_Image.style.display='inline'; Codehighlighter1_2005_2071_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_2005_2071_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_2005_2071_Open_Text><span style="COLOR: #000000">{&nbsp;<br></span><span style="COLOR: #008080">87</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;fprintf(stderr,&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">%s\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;lpszMessage);&nbsp;<br></span><span style="COLOR: #008080">88</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;ExitProcess(</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">);&nbsp;<br></span><span style="COLOR: #008080">89</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">90</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<br><span>常用情景：<br>各个线程所处理的对象有所不同，但是所需要的处理却可能类似，例如多个线程同时处理多个文件，就可以将文件句柄存在在相应的Tls中，在使用相同的接口进行处理<br>背景知识：<br>每个线程除了共享进程的资源外还拥有各自的私有资源：一个寄存器组（或者说是线程上下文）；一个专属的堆栈；一个专属的消息队列；一个专属的Thread Local Storage（TLS）；一个专属的结构化异常处理串链。<br>TLS 是一个良好的Win32 特质，让多线程程序设计更容易一些。TLS 是一个机制，经由它，程序可以拥有全域变量，但在不同的线程里有不同的值。也就是说，进程中的所有线程都可以拥有全域变量，但这些变量其实是特定对某个线程才有意义。例如，你可能有一个多线程程序，每一个线程都对不同的文件写文件（也因此它们使用不同的文件handle）。这种情况下，把每一个线程所使用的文件handle 储存在TLS 中，将会十分方便。当线程需要知道所使用的handle，它可以从TLS 获得。重点在于：线程用来取得文件handle 的那一段码在任何情况下都是相同的，而从TLS中取出的文件handle 却各不相同。非常灵巧，不是吗？有全域变数的便利，却又分属各线程。
<p>&nbsp;</p>
<p>&nbsp;　虽然TLS 很方便，它并不是毫无限制。在Windows NT 和Windows 95 之中，有64 个DWORD slots 供每一个线程使用。这意思是一个进程最多可以有64 个「对各线程有不同意义」的DWORDs。 虽然TLS 可以存放单一数值如文件handle，更常的用途是放置指针，指向线程的私有资料。有许多情况，多线程程序需要储存一堆数据，而它们又都是与各线程相关。许多程序员对此的作法是把这些变量包装为C 结构，然后把结构指针储存在TLS 中。当新的线程诞生，程序就配置一些内存给该结构使用，并且把指针储存在为线程保留下来的TLS 中。一旦线程结束，程序代码就释放所有配置来的区块。既然每一个线程都有64 个slots 用来储存线程自己的数据，那么这些空间到底打哪儿来？在线程的学习中我们可以从结构TDB中看到，每一个thread database 都有64 个DWORDs 给TLS 使用。当你以TLS 函式设定或取出数据，事实上你真正面对的就是那64 DWORDs。好，现在我们知道了原来那些&#8220;对各线程有不同意义的全局变量&#8221;是存放在线程各自的TDB中阿。<br>&nbsp;<wbr><br>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 接下来你也许会问：我怎么存取这64个DWORDS呢？我又怎么知道哪个DWORDS被占用了，哪个没有被占用呢？首先我们要理解这样一个事实：系统之所以给我们提供TLS这一功能，就是为了方便的实现&#8220;<font color=#ff0000>对各线程有不同意义的全局变量</font>&#8221;这一功能；既然要达到&#8220;全局变量&#8221;的效果，那么也就是说每个线程都要用到这个变量，既然这样那么我们就不需要对每个线程的那64个DWORDS的占用情况分别标记了，因为那64个DWORDS中的某一个一旦占用，是所有线程的那个DWORD都被占用了，于是KERNEL32 使用两个DWORDs（总共64 个位）来记录哪一个slot 是可用的、哪一个slot 已经被用。这两个DWORDs 可想象成为一个64 位数组，如果某个位设立，就表示它对应的TLS slot 已被使用。这64 位TLS slot 数组存放在process database 中（在进程一节中的PDB结构中我们列出了那两个DWORDs）。<br>&nbsp;<wbr><br>下面的四个函数就是对TLS进行操作的：</p>
<p>&nbsp;<wbr>&nbsp;（1）TlsAlloc&nbsp;<wbr>&nbsp;<wbr></p>
<p>上面我们说过了KERNEL32 使用两个DWORDs（总共64 个位）来记录哪一个slot 是可用的、哪一个slot 已经被用。当你需要使用一个TLS slot 的时候，你就可以用这个函数将相应的TLS slot位置１。&nbsp;<wbr></p>
<p>&nbsp;（2）TlsSetValue&nbsp;<wbr>&nbsp;<wbr></p>
<p>TlsSetValue 可以把数据放入先前配置到的TLS slot 中。两个参数分别是TLS slot 索引值以及欲写入的数据内容。TlsSetValue 就把你指定的数据放入64 DWORDs 所组成的数组（位于目前的thread database）的适当位置中。&nbsp;<wbr>&nbsp;<wbr></p>
<p>&nbsp;（3）TlsGetValue&nbsp;<wbr>&nbsp;<wbr></p>
<p>这个函数几乎是TlsSetValue 的一面镜子，最大的差异是它取出数据而非设定数据。和TlsSetValue 一样，这个函数也是先检查TLS 索引值合法与否。如果是，TlsGetValue 就使用这个索引值找到64 DWORDs 数组（位于thread database 中）的对应数据项，并将其内容传回。&nbsp;<wbr>&nbsp;<wbr></p>
<p>&nbsp;（4）TlsFree&nbsp;<wbr>&nbsp;<wbr></p>
<p>这个函数将TlsAlloc 和TlsSetValue 的努力全部抹消掉。TlsFree 先检验你交给它的索引值是否的确被配置过。如果是，它将对应的64 位TLS slots 位关闭。然后，为了避免那个已经不再合法的内容被使用，TlsFree 巡访进程中的每一个线程，把0 放到刚刚被释放的那个TLS slot 上头。于是呢，如果有某个TLS 索引后来又被重新配置，所有用到该索引的线程就保证会取回一个0 值，除非它们再调用TlsSetValue。<br></p>
</span>
<img src ="http://www.cppblog.com/dawnbreak/aggbug/68027.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/dawnbreak/" target="_blank">pear_li</a> 2008-11-27 21:46 <a href="http://www.cppblog.com/dawnbreak/articles/68027.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>