﻿<?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++博客-beautykingdom-随笔分类-OS</title><link>http://www.cppblog.com/beautykingdom/category/7623.html</link><description /><language>zh-cn</language><lastBuildDate>Sat, 13 Oct 2012 12:05:15 GMT</lastBuildDate><pubDate>Sat, 13 Oct 2012 12:05:15 GMT</pubDate><ttl>60</ttl><item><title>memcached完全剖析系列教程《转》</title><link>http://www.cppblog.com/beautykingdom/archive/2012/06/16/179023.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Sat, 16 Jun 2012 01:17:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2012/06/16/179023.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/179023.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2012/06/16/179023.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/179023.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/179023.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: memcached完全剖析系列教程&#8211;1.&nbsp;memcached的基础memcached是什么？memcached&nbsp;是以LiveJournal&nbsp;旗下Danga&nbsp;Interactive&nbsp;公司的Brad&nbsp;Fitzpatric&nbsp;为首开发的一款软件。现在已成为&nbsp;豆瓣、Facebook、&nbsp;Vox&nbsp;等众...&nbsp;&nbsp;<a href='http://www.cppblog.com/beautykingdom/archive/2012/06/16/179023.html'>阅读全文</a><img src ="http://www.cppblog.com/beautykingdom/aggbug/179023.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2012-06-16 09:17 <a href="http://www.cppblog.com/beautykingdom/archive/2012/06/16/179023.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>死锁和活锁 deadlock and livelock</title><link>http://www.cppblog.com/beautykingdom/archive/2012/06/08/178097.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Fri, 08 Jun 2012 09:15:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2012/06/08/178097.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/178097.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2012/06/08/178097.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/178097.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/178097.html</trackback:ping><description><![CDATA[<div class="content" sizset="2" sizcache="13"><pre id="best-answer-content" class="reply-text mb10">一、活锁 
如果事务T1封锁了数据R，事务T2又请求封锁R，于是T2等待。T3也请求封锁R，</pre><pre class="reply-text mb10">当T1释放了R上的封锁之后系统首先批准了T3的请求，T2仍然等待。然后T4又</pre><pre class="reply-text mb10">请求封锁R，当T3释放了R上的封锁之后系统又批准了T4的请求，...，T2有可</pre><pre class="reply-text mb10">能永远等待，这就是活锁的情形,避免活锁的简单方法是采用先来先服务的策略。</pre><pre class="reply-text mb10">
二、死锁 
如果事务T1封锁了数据R1，T2封锁了数据R2，然后T1又请求封锁R2，因T2已</pre><pre class="reply-text mb10">封锁了R2，于是T1等待T2释放R2上的锁。接着T2又申请封锁R1，因T1已封锁了R1，</pre><pre class="reply-text mb10">T2也只能等待T1释放R1上的锁。这样就出现了T1在等待T2，而T2又在等待T1的局面，</pre><pre class="reply-text mb10">T1和T2两个事务永远不能结束，形成死锁。 
1. 死锁的预防
在数据库中，产生死锁的原因是两个或多个事务都已封锁了一些数据对象，然后又都</pre><pre class="reply-text mb10">请求对已为其他事务封锁的数据对象加锁，从而出现死等待。防止死锁的发生其实就</pre><pre class="reply-text mb10">是要破坏产生死锁的条件。预防死锁通常有两种方法： 
&#9312; 一次封锁法  
一次封锁法要求每个事务必须一次将所有要使用的数据全部加锁，否则就不能继续执行。

一次封锁法虽然可以有效地防止死锁的发生，但也存在问题，一次就将以后要用到的全</pre><pre class="reply-text mb10">部数据加锁，势必扩大了封锁的范围，从而降低了系统的并发度。
&#9313; 顺序封锁法 
顺序封锁法是预先对数据对象规定一个封锁顺序，所有事务都按这个顺序实行封锁。

顺序封锁法可以有效地防止死锁，但也同样存在问题。事务的封锁请求可以随着事务的</pre><pre class="reply-text mb10">执行而动态地决定，很难事先确定每一个事务要封锁哪些对象，因此也就很难按规定的</pre><pre class="reply-text mb10">顺序去施加封锁。
 
可见，在操作系统中广为采用的预防死锁的策略并不很适合数据库的特点，因此DBMS在</pre><pre class="reply-text mb10">解决死锁的问题上普遍采用的是诊断并解除死锁的方法。

 2. 死锁的诊断与解除
 
&#9312; 超时法

 如果一个事务的等待时间超过了规定的时限，就认为发生了死锁。超时法实现简单，但</pre><pre class="reply-text mb10">其不足也很明显。一是有可能误判死锁，事务因为其他原因使等待时间超过时限，系统会</pre><pre class="reply-text mb10">误认为发生了死锁。二是时限若设置得太长，死锁发生后不能及时发现。
 
&#9313; 等待图法
 
事务等待图是一个有向图G=(T,U)。 T为结点的集合，每个结点表示正运行的事务；U为</pre><pre class="reply-text mb10">边的集合，每条边表示事务等待的情况。若T1等待T2,则T1、T2之间划一条有向边，从T1</pre><pre class="reply-text mb10">指向T2。事务等待图动态地反映了所有事务的等待情况。并发控制子系统周期性地（比如</pre><pre class="reply-text mb10">每隔1分钟）检测事务等待图，如果发现图中存在回路，则表示系统中出现了死锁。
 
DBMS的并发控制子系统一旦检测到系统中存在死锁，就要设法解除。通常采用的方法是选择</pre><pre class="reply-text mb10">一个处理死锁代价最小的事务，将其撤消，释放此事务持有的所有的锁，使其它事务得以继续</pre><pre class="reply-text mb10">运行下去。当然，对撤消的事务所执行的数据修改操作必须加以恢复。</pre></div><img src ="http://www.cppblog.com/beautykingdom/aggbug/178097.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2012-06-08 17:15 <a href="http://www.cppblog.com/beautykingdom/archive/2012/06/08/178097.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>为 C/C++ 项目构建您自己的内存管理器&lt;forward&gt;</title><link>http://www.cppblog.com/beautykingdom/archive/2012/05/26/176285.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Sat, 26 May 2012 14:41:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2012/05/26/176285.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/176285.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2012/05/26/176285.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/176285.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/176285.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Arpan Sen, 技术负责人, Synapti Computer Aided Design Pvt LtdRahul Kumar Kardam&nbsp;(rahul@syncad.com), 高级软件工程师, Synapti Computer Aided Design Pvt Ltd简介：&nbsp; 代码的性能优化是一项非常重要的工作。经常可以看到，采用 C 或 C++ 编写的、功能正确的...&nbsp;&nbsp;<a href='http://www.cppblog.com/beautykingdom/archive/2012/05/26/176285.html'>阅读全文</a><img src ="http://www.cppblog.com/beautykingdom/aggbug/176285.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2012-05-26 22:41 <a href="http://www.cppblog.com/beautykingdom/archive/2012/05/26/176285.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>TCMalloc : Thread-Caching Malloc</title><link>http://www.cppblog.com/beautykingdom/archive/2012/04/04/170077.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Wed, 04 Apr 2012 13:15:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2012/04/04/170077.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/170077.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2012/04/04/170077.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/170077.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/170077.html</trackback:ping><description><![CDATA[<h1 style="line-height: normal; widows: 2; text-transform: none; font-variant: normal; font-style: normal; text-indent: 0px; letter-spacing: normal; font-family: Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">from:&nbsp;</h1>
<h1 style="line-height: normal; widows: 2; text-transform: none; font-variant: normal; font-style: normal; text-indent: 0px; letter-spacing: normal; font-family: Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><a href="http://goog-perftools.sourceforge.net/doc/tcmalloc.html"><span style="font-size: 12pt">http://goog-perftools.sourceforge.net/doc/tcmalloc.html</span></a></h1>
<p style="line-height: normal; widows: 2; text-transform: none; font-variant: normal; font-style: normal; text-indent: 0px; letter-spacing: normal; font-family: Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p>
<h1 style="line-height: normal; widows: 2; text-transform: none; font-variant: normal; font-style: normal; text-indent: 0px; letter-spacing: normal; font-family: Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">TCMalloc : Thread-Caching Malloc</h1>
<address style="line-height: normal; widows: 2; text-transform: none; font-variant: normal; text-indent: 0px; letter-spacing: normal; font-family: Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); font-size: medium; font-weight: normal; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">Sanjay Ghemawat, Paul Menage &lt;opensource@google.com&gt;</address>
<h2 style="line-height: normal; widows: 2; text-transform: none; font-variant: normal; font-style: normal; text-indent: 0px; letter-spacing: normal; font-family: Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">Motivation</h2><span style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; display: inline !important; font: medium Simsun; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">TCMalloc is faster than the glibc 2.3 malloc (available as a separate library called ptmalloc2) and other mallocs that I have tested. ptmalloc2 takes approximately 300 nanoseconds to execute a malloc/free pair on a 2.8 GHz P4 (for small objects). The TCMalloc implementation takes approximately 50 nanoseconds for the same operation pair. Speed is important for a malloc implementation because if malloc is not fast enough, application writers are inclined to write their own custom free lists on top of malloc. This can lead to extra complexity, and more memory usage unless the application writer is very careful to appropriately size the free lists and scavenge idle objects out of the free list</span> 
<p style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; font: medium Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">TCMalloc also reduces lock contention for multi-threaded programs. For small objects, there is virtually zero contention. For large objects, TCMalloc tries to use fine grained and efficient spinlocks. ptmalloc2 also reduces lock contention by using per-thread arenas but there is a big problem with ptmalloc2's use of per-thread arenas. In ptmalloc2 memory can never move from one arena to another. This can lead to huge amounts of wasted space. For example, in one Google application, the first phase would allocate approximately 300MB of memory for its data structures. When the first phase finished, a second phase would be started in the same address space. If this second phase was assigned a different arena than the one used by the first phase, this phase would not reuse any of the memory left after the first phase and would add another 300MB to the address space. Similar memory blowup problems were also noticed in other applications.</p>
<p style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; font: medium Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">Another benefit of TCMalloc is space-efficient representation of small objects. For example, N 8-byte objects can be allocated while using space approximately<span class="Apple-converted-space">&nbsp;</span><code>8N * 1.01</code><span class="Apple-converted-space">&nbsp;</span>bytes. I.e., a one-percent space overhead. ptmalloc2 uses a four-byte header for each object and (I think) rounds up the size to a multiple of 8 bytes and ends up using<span class="Apple-converted-space">&nbsp;</span><code>16N</code><span class="Apple-converted-space">&nbsp;</span>bytes.</p>
<h2 style="line-height: normal; widows: 2; text-transform: none; font-variant: normal; font-style: normal; text-indent: 0px; letter-spacing: normal; font-family: Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">Usage</h2>
<p style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; font: medium Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">To use TCmalloc, just link tcmalloc into your application via the "-ltcmalloc" linker flag.</p>
<p style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; font: medium Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">You can use tcmalloc in applications you didn't compile yourself, by using LD_PRELOAD:</p><pre style="line-height: normal; widows: 2; text-transform: none; font-variant: normal; font-style: normal; text-indent: 0px; letter-spacing: normal; orphans: 2; color: rgb(0,0,0); font-weight: normal; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">   $ LD_PRELOAD="/usr/lib/libtcmalloc.so" <binary>
</binary></pre>
<p style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; font: medium Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">LD_PRELOAD is tricky, and we don't necessarily recommend this mode of usage.</p>
<p style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; font: medium Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">TCMalloc includes a<span class="Apple-converted-space">&nbsp;</span><a href="http://goog-perftools.sourceforge.net/doc/heap_checker.html">heap checker</a><span class="Apple-converted-space">&nbsp;</span>and<span class="Apple-converted-space">&nbsp;</span><a href="http://goog-perftools.sourceforge.net/doc/heap_profiler.html">heap profiler</a><span class="Apple-converted-space">&nbsp;</span>as well.</p>
<p style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; font: medium Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">If you'd rather link in a version of TCMalloc that does not include the heap profiler and checker (perhaps to reduce binary size for a static binary), you can link in<span class="Apple-converted-space">&nbsp;</span><code>libtcmalloc_minimal</code><span class="Apple-converted-space">&nbsp;</span>instead.</p>
<h2 style="line-height: normal; widows: 2; text-transform: none; font-variant: normal; font-style: normal; text-indent: 0px; letter-spacing: normal; font-family: Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">Overview</h2><span style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; display: inline !important; font: medium Simsun; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">TCMalloc assigns each thread a thread-local cache. Small allocations are satisfied from the thread-local cache. Objects are moved from central data structures into a thread-local cache as needed, and periodic garbage collections are used to migrate memory back from a thread-local cache into the central data structures.</span> 
<center style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; font: medium Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><img src="http://goog-perftools.sourceforge.net/doc/overview.gif"  alt="" /></center>
<p style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; font: medium Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">TCMalloc treates objects with size &lt;= 32K ("small" objects) differently from larger objects. Large objects are allocated directly from the central heap using a page-level allocator (a page is a 4K aligned region of memory). I.e., a large object is always page-aligned and occupies an integral number of pages.</p>
<p style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; font: medium Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">A run of pages can be carved up into a sequence of small objects, each equally sized. For example a run of one page (4K) can be carved up into 32 objects of size 128 bytes each.</p>
<h2 style="line-height: normal; widows: 2; text-transform: none; font-variant: normal; font-style: normal; text-indent: 0px; letter-spacing: normal; font-family: Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">Small Object Allocation</h2><span style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; display: inline !important; font: medium Simsun; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">Each small object size maps to one of approximately 170 allocatable size-classes. For example, all allocations in the range 961 to 1024 bytes are rounded up to 1024. The size-classes are spaced so that small sizes are separated by 8 bytes, larger sizes by 16 bytes, even larger sizes by 32 bytes, and so forth. The maximal spacing (for sizes &gt;= ~2K) is 256 bytes.</span> 
<p style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; font: medium Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">A thread cache contains a singly linked list of free objects per size-class.</p>
<center style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; font: medium Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><img src="http://goog-perftools.sourceforge.net/doc/threadheap.gif"  alt="" /></center><span style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; display: inline !important; font: medium Simsun; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">When allocating a small object: (1) We map its size to the corresponding size-class. (2) Look in the corresponding free list in the thread cache for the current thread. (3) If the free list is not empty, we remove the first object from the list and return it. When following this fast path, TCMalloc acquires no locks at all. This helps speed-up allocation significantly because a lock/unlock pair takes approximately 100 nanoseconds on a 2.8 GHz Xeon.</span> 
<p style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; font: medium Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">If the free list is empty: (1) We fetch a bunch of objects from a central free list for this size-class (the central free list is shared by all threads). (2) Place them in the thread-local free list. (3) Return one of the newly fetched objects to the applications.</p>
<p style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; font: medium Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">If the central free list is also empty: (1) We allocate a run of pages from the central page allocator. (2) Split the run into a set of objects of this size-class. (3) Place the new objects on the central free list. (4) As before, move some of these objects to the thread-local free list.</p>
<h2 style="line-height: normal; widows: 2; text-transform: none; font-variant: normal; font-style: normal; text-indent: 0px; letter-spacing: normal; font-family: Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">Large Object Allocation</h2><span style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; display: inline !important; font: medium Simsun; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">A large object size (&gt; 32K) is rounded up to a page size (4K) and is handled by a central page heap. The central page heap is again an array of free lists. For<span class="Apple-converted-space">&nbsp;</span></span><code style="line-height: normal; widows: 2; text-transform: none; font-variant: normal; font-style: normal; text-indent: 0px; letter-spacing: normal; white-space: normal; orphans: 2; color: rgb(0,0,0); font-weight: normal; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">i &lt; 256</code><span style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; display: inline !important; font: medium Simsun; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">, the<span class="Apple-converted-space">&nbsp;</span></span><code style="line-height: normal; widows: 2; text-transform: none; font-variant: normal; font-style: normal; text-indent: 0px; letter-spacing: normal; white-space: normal; orphans: 2; color: rgb(0,0,0); font-weight: normal; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">k</code><span style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; display: inline !important; font: medium Simsun; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">th entry is a free list of runs that consist of<span class="Apple-converted-space">&nbsp;</span></span><code style="line-height: normal; widows: 2; text-transform: none; font-variant: normal; font-style: normal; text-indent: 0px; letter-spacing: normal; white-space: normal; orphans: 2; color: rgb(0,0,0); font-weight: normal; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">k</code><span style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; display: inline !important; font: medium Simsun; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span class="Apple-converted-space">&nbsp;</span>pages. The<span class="Apple-converted-space">&nbsp;</span></span><code style="line-height: normal; widows: 2; text-transform: none; font-variant: normal; font-style: normal; text-indent: 0px; letter-spacing: normal; white-space: normal; orphans: 2; color: rgb(0,0,0); font-weight: normal; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">256</code><span style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; display: inline !important; font: medium Simsun; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">th entry is a free list of runs that have length<span class="Apple-converted-space">&nbsp;</span></span><code style="line-height: normal; widows: 2; text-transform: none; font-variant: normal; font-style: normal; text-indent: 0px; letter-spacing: normal; white-space: normal; orphans: 2; color: rgb(0,0,0); font-weight: normal; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&gt;= 256</code><span style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; display: inline !important; font: medium Simsun; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span class="Apple-converted-space">&nbsp;</span>pages:</span> 
<center style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; font: medium Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><img src="http://goog-perftools.sourceforge.net/doc/pageheap.gif"  alt="" /></center>
<p style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; font: medium Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">An allocation for<span class="Apple-converted-space">&nbsp;</span><code>k</code><span class="Apple-converted-space">&nbsp;</span>pages is satisfied by looking in the<span class="Apple-converted-space">&nbsp;</span><code>k</code>th free list. If that free list is empty, we look in the next free list, and so forth. Eventually, we look in the last free list if necessary. If that fails, we fetch memory from the system (using sbrk, mmap, or by mapping in portions of /dev/mem).</p>
<p style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; font: medium Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">If an allocation for<span class="Apple-converted-space">&nbsp;</span><code>k</code><span class="Apple-converted-space">&nbsp;</span>pages is satisfied by a run of pages of length &gt;<span class="Apple-converted-space">&nbsp;</span><code>k</code>, the remainder of the run is re-inserted back into the appropriate free list in the page heap.</p>
<h2 style="line-height: normal; widows: 2; text-transform: none; font-variant: normal; font-style: normal; text-indent: 0px; letter-spacing: normal; font-family: Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">Spans</h2><span style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; display: inline !important; font: medium Simsun; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">The heap managed by TCMalloc consists of a set of pages. A run of contiguous pages is represented by a<span class="Apple-converted-space">&nbsp;</span></span><code style="line-height: normal; widows: 2; text-transform: none; font-variant: normal; font-style: normal; text-indent: 0px; letter-spacing: normal; white-space: normal; orphans: 2; color: rgb(0,0,0); font-weight: normal; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">Span</code><span style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; display: inline !important; font: medium Simsun; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span class="Apple-converted-space">&nbsp;</span>object. A span can either be<span class="Apple-converted-space">&nbsp;</span></span><em style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; font: medium Simsun; white-space: normal; orphans: 2; color: red; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">allocated</em><span style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; display: inline !important; font: medium Simsun; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">, or<span class="Apple-converted-space">&nbsp;</span></span><em style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; font: medium Simsun; white-space: normal; orphans: 2; color: red; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">free</em><span style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; display: inline !important; font: medium Simsun; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">. If free, the span is one of the entries in a page heap linked-list. If allocated, it is either a large object that has been handed off to the application, or a run of pages that have been split up into a sequence of small objects. If split into small objects, the size-class of the objects is recorded in the span.</span> 
<p style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; font: medium Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">A central array indexed by page number can be used to find the span to which a page belongs. For example, span<span class="Apple-converted-space">&nbsp;</span><em style="font-style: normal; color: red">a</em><span class="Apple-converted-space">&nbsp;</span>below occupies 2 pages, span<span class="Apple-converted-space">&nbsp;</span><em style="font-style: normal; color: red">b</em><span class="Apple-converted-space">&nbsp;</span>occupies 1 page, span<span class="Apple-converted-space">&nbsp;</span><em style="font-style: normal; color: red">c</em><span class="Apple-converted-space">&nbsp;</span>occupies 5 pages and span<span class="Apple-converted-space">&nbsp;</span><em style="font-style: normal; color: red">d</em><span class="Apple-converted-space">&nbsp;</span>occupies 3 pages.</p>
<center style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; font: medium Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><img src="http://goog-perftools.sourceforge.net/doc/spanmap.gif"  alt="" /></center><span style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; display: inline !important; font: medium Simsun; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">A 32-bit address space can fit 2^20 4K pages, so this central array takes 4MB of space, which seems acceptable. On 64-bit machines, we use a 3-level radix tree instead of an array to map from a page number to the corresponding span pointer.</span> 
<h2 style="line-height: normal; widows: 2; text-transform: none; font-variant: normal; font-style: normal; text-indent: 0px; letter-spacing: normal; font-family: Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">Deallocation</h2><span style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; display: inline !important; font: medium Simsun; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">When an object is deallocated, we compute its page number and look it up in the central array to find the corresponding span object. The span tells us whether or not the object is small, and its size-class if it is small. If the object is small, we insert it into the appropriate free list in the current thread's thread cache. If the thread cache now exceeds a predetermined size (2MB by default), we run a garbage collector that moves unused objects from the thread cache into central free lists.</span> 
<p style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; font: medium Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">If the object is large, the span tells us the range of pages covered by the object. Suppose this range is<span class="Apple-converted-space">&nbsp;</span><code>[p,q]</code>. We also lookup the spans for pages<span class="Apple-converted-space">&nbsp;</span><code>p-1</code><span class="Apple-converted-space">&nbsp;</span>and<code>q+1</code>. If either of these neighboring spans are free, we coalesce them with the<span class="Apple-converted-space">&nbsp;</span><code>[p,q]</code><span class="Apple-converted-space">&nbsp;</span>span. The resulting span is inserted into the appropriate free list in the page heap.</p>
<h2 style="line-height: normal; widows: 2; text-transform: none; font-variant: normal; font-style: normal; text-indent: 0px; letter-spacing: normal; font-family: Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">Central Free Lists for Small Objects</h2><span style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; display: inline !important; font: medium Simsun; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">As mentioned before, we keep a central free list for each size-class. Each central free list is organized as a two-level data structure: a set of spans, and a linked list of free objects per span.</span> 
<p style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; font: medium Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">An object is allocated from a central free list by removing the first entry from the linked list of some span. (If all spans have empty linked lists, a suitably sized span is first allocated from the central page heap.)</p>
<p style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; font: medium Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">An object is returned to a central free list by adding it to the linked list of its containing span. If the linked list length now equals the total number of small objects in the span, this span is now completely free and is returned to the page heap.</p>
<h2 style="line-height: normal; widows: 2; text-transform: none; font-variant: normal; font-style: normal; text-indent: 0px; letter-spacing: normal; font-family: Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">Garbage Collection of Thread Caches</h2><span style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; display: inline !important; font: medium Simsun; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">A thread cache is garbage collected when the combined size of all objects in the cache exceeds 2MB. The garbage collection threshold is automatically decreased as the number of threads increases so that we don't waste an inordinate amount of memory in a program with lots of threads.</span> 
<p style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; font: medium Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">We walk over all free lists in the cache and move some number of objects from the free list to the corresponding central list.</p>
<p style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; font: medium Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">The number of objects to be moved from a free list is determined using a per-list low-water-mark<span class="Apple-converted-space">&nbsp;</span><code>L</code>.<span class="Apple-converted-space">&nbsp;</span><code>L</code><span class="Apple-converted-space">&nbsp;</span>records the minimum length of the list since the last garbage collection. Note that we could have shortened the list by<span class="Apple-converted-space">&nbsp;</span><code>L</code><span class="Apple-converted-space">&nbsp;</span>objects at the last garbage collection without requiring any extra accesses to the central list. We use this past history as a predictor of future accesses and move<span class="Apple-converted-space">&nbsp;</span><code>L/2</code><span class="Apple-converted-space">&nbsp;</span>objects from the thread cache free list to the corresponding central free list. This algorithm has the nice property that if a thread stops using a particular size, all objects of that size will quickly move from the thread cache to the central free list where they can be used by other threads.</p>
<h2 style="line-height: normal; widows: 2; text-transform: none; font-variant: normal; font-style: normal; text-indent: 0px; letter-spacing: normal; font-family: Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">Performance Notes</h2>
<h3 style="line-height: normal; widows: 2; text-transform: none; font-variant: normal; font-style: normal; text-indent: 0px; letter-spacing: normal; font-family: Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">PTMalloc2 unittest</h3><span style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; display: inline !important; font: medium Simsun; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">The PTMalloc2 package (now part of glibc) contains a unittest program t-test1.c. This forks a number of threads and performs a series of allocations and deallocations in each thread; the threads do not communicate other than by synchronization in the memory allocator.</span> 
<p style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; font: medium Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">t-test1 (included in google-perftools/tests/tcmalloc, and compiled as ptmalloc_unittest1) was run with a varying numbers of threads (1-20) and maximum allocation sizes (64 bytes - 32Kbytes). These tests were run on a 2.4GHz dual Xeon system with hyper-threading enabled, using Linux glibc-2.3.2 from RedHat 9, with one million operations per thread in each test. In each case, the test was run once normally, and once with LD_PRELOAD=libtcmalloc.so.</p>
<p style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; font: medium Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">The graphs below show the performance of TCMalloc vs PTMalloc2 for several different metrics. Firstly, total operations (millions) per elapsed second vs max allocation size, for varying numbers of threads. The raw data used to generate these graphs (the output of the "time" utility) is available in t-test1.times.txt.</p>
<p style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; font: medium Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">
<table>
<tbody>
<tr>
<td><img src="http://goog-perftools.sourceforge.net/doc/tcmalloc-opspersec.vs.size.1.threads.png"  alt="" /></td>
<td><img src="http://goog-perftools.sourceforge.net/doc/tcmalloc-opspersec.vs.size.2.threads.png"  alt="" /></td>
<td><img src="http://goog-perftools.sourceforge.net/doc/tcmalloc-opspersec.vs.size.3.threads.png"  alt="" /></td></tr>
<tr>
<td><img src="http://goog-perftools.sourceforge.net/doc/tcmalloc-opspersec.vs.size.4.threads.png"  alt="" /></td>
<td><img src="http://goog-perftools.sourceforge.net/doc/tcmalloc-opspersec.vs.size.5.threads.png"  alt="" /></td>
<td><img src="http://goog-perftools.sourceforge.net/doc/tcmalloc-opspersec.vs.size.8.threads.png"  alt="" /></td></tr>
<tr>
<td><img src="http://goog-perftools.sourceforge.net/doc/tcmalloc-opspersec.vs.size.12.threads.png"  alt="" /></td>
<td><img src="http://goog-perftools.sourceforge.net/doc/tcmalloc-opspersec.vs.size.16.threads.png"  alt="" /></td>
<td><img src="http://goog-perftools.sourceforge.net/doc/tcmalloc-opspersec.vs.size.20.threads.png"  alt="" /></td></tr></tbody></table></p>
<ul style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; font: medium Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><li>TCMalloc is much more consistently scalable than PTMalloc2 - for all thread counts &gt;1 it achieves ~7-9 million ops/sec for small allocations, falling to ~2 million ops/sec for larger allocations. The single-thread case is an obvious outlier, since it is only able to keep a single processor busy and hence can achieve fewer ops/sec. PTMalloc2 has a much higher variance on operations/sec - peaking somewhere around 4 million ops/sec for small allocations and falling to &lt;1 million ops/sec for larger allocations.</li><li>TCMalloc is faster than PTMalloc2 in the vast majority of cases, and particularly for small allocations. Contention between threads is less of a problem in TCMalloc.</li><li>TCMalloc's performance drops off as the allocation size increases. This is because the per-thread cache is garbage-collected when it hits a threshold (defaulting to 2MB). With larger allocation sizes, fewer objects can be stored in the cache before it is garbage-collected.</li><li>There is a noticeably drop in the TCMalloc performance at ~32K maximum allocation size; at larger sizes performance drops less quickly. This is due to the 32K maximum size of objects in the per-thread caches; for objects larger than this tcmalloc allocates from the central page heap.</li></ul>
<p style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; font: medium Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">Next, operations (millions) per second of CPU time vs number of threads, for max allocation size 64 bytes - 128 Kbytes.</p>
<p style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; font: medium Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">
<table>
<tbody>
<tr>
<td><img src="http://goog-perftools.sourceforge.net/doc/tcmalloc-opspercpusec.vs.threads.64.bytes.png"  alt="" /></td>
<td><img src="http://goog-perftools.sourceforge.net/doc/tcmalloc-opspercpusec.vs.threads.256.bytes.png"  alt="" /></td>
<td><img src="http://goog-perftools.sourceforge.net/doc/tcmalloc-opspercpusec.vs.threads.1024.bytes.png"  alt="" /></td></tr>
<tr>
<td><img src="http://goog-perftools.sourceforge.net/doc/tcmalloc-opspercpusec.vs.threads.4096.bytes.png"  alt="" /></td>
<td><img src="http://goog-perftools.sourceforge.net/doc/tcmalloc-opspercpusec.vs.threads.8192.bytes.png"  alt="" /></td>
<td><img src="http://goog-perftools.sourceforge.net/doc/tcmalloc-opspercpusec.vs.threads.16384.bytes.png"  alt="" /></td></tr>
<tr>
<td><img src="http://goog-perftools.sourceforge.net/doc/tcmalloc-opspercpusec.vs.threads.32768.bytes.png"  alt="" /></td>
<td><img src="http://goog-perftools.sourceforge.net/doc/tcmalloc-opspercpusec.vs.threads.65536.bytes.png"  alt="" /></td>
<td><img src="http://goog-perftools.sourceforge.net/doc/tcmalloc-opspercpusec.vs.threads.131072.bytes.png"  alt="" /></td></tr></tbody></table></p>
<p style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; font: medium Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">Here we see again that TCMalloc is both more consistent and more efficient than PTMalloc2. For max allocation sizes &lt;32K, TCMalloc typically achieves ~2-2.5 million ops per second of CPU time with a large number of threads, whereas PTMalloc achieves generally 0.5-1 million ops per second of CPU time, with a lot of cases achieving much less than this figure. Above 32K max allocation size, TCMalloc drops to 1-1.5 million ops per second of CPU time, and PTMalloc drops almost to zero for large numbers of threads (i.e. with PTMalloc, lots of CPU time is being burned spinning waiting for locks in the heavily multi-threaded case).</p>
<h2 style="line-height: normal; widows: 2; text-transform: none; font-variant: normal; font-style: normal; text-indent: 0px; letter-spacing: normal; font-family: Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">Caveats</h2>
<p style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; font: medium Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">For some systems, TCMalloc may not work correctly on with applications that aren't linked against libpthread.so (or the equivalent on your OS). It should work on Linux using glibc 2.3, but other OS/libc combinations have not been tested.</p>
<p style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; font: medium Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">TCMalloc may be somewhat more memory hungry than other mallocs, though it tends not to have the huge blowups that can happen with other mallocs. In particular, at startup TCMalloc allocates approximately 6 MB of memory. It would be easy to roll a specialized version that trades a little bit of speed for more space efficiency.</p>
<p style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; font: medium Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">TCMalloc currently does not return any memory to the system.</p>
<p style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; font: medium Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">Don't try to load TCMalloc into a running binary (e.g., using JNI in Java programs). The binary will have allocated some objects using the system malloc, and may try to pass them to TCMalloc for deallocation. TCMalloc will not be able to handle such objects.</p><img src ="http://www.cppblog.com/beautykingdom/aggbug/170077.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2012-04-04 21:15 <a href="http://www.cppblog.com/beautykingdom/archive/2012/04/04/170077.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>How does the DMA work</title><link>http://www.cppblog.com/beautykingdom/archive/2010/11/14/133602.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Sun, 14 Nov 2010 11:23:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/11/14/133602.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/133602.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/11/14/133602.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/133602.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/133602.html</trackback:ping><description><![CDATA[

<div><p style="font-family: arial, verdana, tahoma, sans-serif; font-size: 16px; ">The DMA is another two chips on your motherboard (usually is an Intel 8237A-5 chips) that allow you (the programmer) to offload data transfers between I/O boards. DMA actually stands for 'Direct Memory Access'.</p><p style="font-family: arial, verdana, tahoma, sans-serif; font-size: 16px; ">DMA can work: memory-&gt;I/O, I/O-&gt;memory. The memory-&gt;memory transfer doesn't work. It doesn't matter because ISA DMA is slow as hell and thus is unusable. Futhermore, using DMA for zeroing out memory would massacre the contents of memory caches.</p><p style="font-family: arial, verdana, tahoma, sans-serif; font-size: 16px; ">What about caches and DMA? L1 and L2 caches work absolutely transparently. When DMA writes to memory, caches autmatically load or least invalidate the data that go into the memory. When DMA reads memory, caches supply the unwritten bytes so not old but new values are tranferred to the peripheral.</p><p style="font-family: arial, verdana, tahoma, sans-serif; font-size: 16px; ">There are signals DACK<number>, DRQ<number>, and TC. When a peripheral wants to move a byte or 2 bytes into memory (is dependent on whether 8 bit or 16 bit DMA channel is in use -- 0,1,2,3 are 8-bit, 5,6,7 are 16-bit), it issues DRQ. DMA controller chats with CPU and after some time DMA controller issues DACK. Seeing DACK, the peripheral puts it's byte on data bus, DMA controller takes it and puts it in memory. If it was the last byte/word to move, DMA controller sets up also TC during the DACK. When peripheral sees TC, it is possible it will not want any more movements,</number></number></p><p style="font-family: arial, verdana, tahoma, sans-serif; font-size: 16px; ">In the other direction, everything is the same, but first the byte/word is fetched from the memory and then DACK is generated and the peripheral takes the data.</p><p style="font-family: arial, verdana, tahoma, sans-serif; font-size: 16px; ">DMA controller has only 8-bit address counter inside. There is external ALS573 counter for each chip so it makes programmer see it as DMA controller had 16 bits of address counter per channel inside. There are more 8 bits of address per channel of so called page register in LS612 that unfortunately do not increment as those in ALS573. All these 24 bits can address 16777216 of distict addresses.</p><p style="font-family: arial, verdana, tahoma, sans-serif; font-size: 16px; ">Recapitulation: for each channel, independently, you see 16 bits of auto-incrementing counter, and 8 bits of page register which doesn't increment.</p><p style="font-family: arial, verdana, tahoma, sans-serif; font-size: 16px; ">The difference between 16-bit DMA channels and 8-bit DMA channels is that the address bits for 16-bit channels are wired one bit left to the address bus so every address is 2 times bigger. The lowest bit is 0. The highest bit of page register would fit into bit 24 which is not on ISA so that it is left unconnected. The bus control logic is wired for 16-bit channels in a manner every single DMA transfer, a 16-bit cycle is generated, so ISA device puts 16 bits onto the bus at the time. I don't know what happens if you use 16-bit DMA channel with XT peripheral. I guess it could work but only be slower.</p><p style="font-family: arial, verdana, tahoma, sans-serif; font-size: 16px; ">8-bit DMA: increments by 1, cycles inside 65536 bytes, addresses 16MB, moves 8 bits a time.</p><p style="font-family: arial, verdana, tahoma, sans-serif; font-size: 16px; ">16-bit DMA: increments by 2, goes only over even addresses, cycles inside 131072 bytes, addresses 16MB, moves 16 bits a time. Uses 16-bit ISA I/O cycle so it takes less ticks to make one move that the 8-bit DMA.</p><p style="font-family: arial, verdana, tahoma, sans-serif; font-size: 16px; ">An example of DMA usage would be the Sound Blaster's ability to play samples in the background. The CPU sets up the sound card and the DMA. When the DMA is told to 'go', it simply shovels the data from RAM to the card. Since this is done off-CPU, the CPU can do other things while the data is being transferred.</p><p style="font-family: arial, verdana, tahoma, sans-serif; font-size: 16px; ">Enough basics. Here's how you program the DMA chip.</p><hr style="font-family: arial, verdana, tahoma, sans-serif; font-size: 16px; "><p style="font-family: arial, verdana, tahoma, sans-serif; font-size: 16px; ">When you want to start a DMA transfer, you need to know several things:</p><ul style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; list-style-type: none; list-style-position: initial; list-style-image: initial; font-family: arial, verdana, tahoma, sans-serif; font-size: 16px; "><li style="list-style-type: none; list-style-position: initial; list-style-image: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 20px; margin-left: 0px; ">Number of DMA channel you want to use</li><li style="list-style-type: none; list-style-position: initial; list-style-image: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 20px; margin-left: 0px; ">What page to use</li><li style="list-style-type: none; list-style-position: initial; list-style-image: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 20px; margin-left: 0px; ">The offset in the page</li><li style="list-style-type: none; list-style-position: initial; list-style-image: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 20px; margin-left: 0px; ">The length</li><li style="list-style-type: none; list-style-position: initial; list-style-image: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 20px; margin-left: 0px; ">How to tell you peripheral to ask for DMA</li></ul><p style="font-family: arial, verdana, tahoma, sans-serif; font-size: 16px; "></p><ul style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; list-style-type: none; list-style-position: initial; list-style-image: initial; font-family: arial, verdana, tahoma, sans-serif; font-size: 16px; "><li style="list-style-type: none; list-style-position: initial; list-style-image: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 20px; margin-left: 0px; ">You cannot transfer more than 64K or 128K of data in one shot, and</li><li style="list-style-type: none; list-style-position: initial; list-style-image: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 20px; margin-left: 0px; ">You cannot cross a page boundary. If you cross it, the lower 16 or 17 bits of address will simply wrap and you only suddenly jump 65536 or 131072 bytes lower that where you expected. It will be absolutely OK and no screw up will be performed. If you will take it in account in your program you can use it.</li></ul><p style="font-family: arial, verdana, tahoma, sans-serif; font-size: 16px; ">Restriction #1 is rather easy to get around. Simply transfer the first block, and when the transfer is done, send the next block.</p><p style="font-family: arial, verdana, tahoma, sans-serif; font-size: 16px; ">For those of you not familiar with pages, I'll try to explain.</p><p style="font-family: arial, verdana, tahoma, sans-serif; font-size: 16px; ">Picture the first 16MB region of memory in your system. It is divided into 256 pages of 64K or 128 pages of 128K. Every page starts at a multiple of 65536 or 131072. They are numbered from 0 to 255 or from 0 to 127.</p><p style="font-family: arial, verdana, tahoma, sans-serif; font-size: 16px; ">In plain English, the page is the highest 8 bits or 7 bits of the absolute 24 bit address of our memory location. The offset is the lower 16 or 17 bits of the absolute 24 bit address.</p><p style="font-family: arial, verdana, tahoma, sans-serif; font-size: 16px; ">Now that we know where our data is, we need to find the length.</p><p style="font-family: arial, verdana, tahoma, sans-serif; font-size: 16px; ">The DMA has a little quirk on length. The true length sent to the DMA is actually length + 1. So if you send a zero length to the DMA, it actually transfers one byte or word, whereas if you send 0xFFFF, it transfers 64K or 128K. I guess they made it this way because it would be pretty senseless to program the DMA to do nothing (a length of zero), and in doing it this way, it allowed a full 64K or 128K span of data to be transferred.</p><p style="font-family: arial, verdana, tahoma, sans-serif; font-size: 16px; ">Now that you know what to send to the DMA, how do you actually start it? This enters us into the different DMA channels.</p><p style="font-family: arial, verdana, tahoma, sans-serif; font-size: 16px; ">The following chart will describe each channel and it's corresponding port number:</p><table style="font-family: arial, verdana, tahoma, sans-serif; font-size: 16px; "><tbody><tr><td>DMA Channel</td><td>Page</td><td>Address</td><td>Count</td></tr><tr><td>0</td><td>87h</td><td>0h</td><td>1h</td></tr><tr><td>1</td><td>83h</td><td>2h</td><td>3h</td></tr><tr><td>2</td><td>81h</td><td>4h</td><td>5h</td></tr><tr><td>3</td><td>82h</td><td>6h</td><td>7h</td></tr><tr><td>4</td><td>8Fh</td><td>C0h</td><td>C2h</td></tr><tr><td>5</td><td>8Bh</td><td>C4h</td><td>C6h</td></tr><tr><td>6</td><td>89h</td><td>C8h</td><td>CAh</td></tr><tr><td>7</td><td>8Ah</td><td>CCh</td><td>CEh</td></tr></tbody></table><p style="font-family: arial, verdana, tahoma, sans-serif; font-size: 16px; ">DMA 4. Doesn't exist. DMA 4 is used to cascade the two 8237A chips. When first 8237A wants to DMA, it issues "HRQ" to second chip's DRQ 4. The second chip thinks DMA 4 is wanna be made so issues DRQ 4 to the first chip's HLDA. First chip makes it's own DMA 0-3, then sends to the second "OK second chip, my DMA 4 is complete" and second chip knows it's free on the bus. If this mechanism would not work, the two chips could peck each other on the BUS and the PC would screw up. :+)</p></div><div>from:</div><div><a href="http://www.osdever.net/papers/view/how-does-the-dma-work">http://www.osdever.net/papers/view/how-does-the-dma-work</a></div><img src ="http://www.cppblog.com/beautykingdom/aggbug/133602.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-11-14 19:23 <a href="http://www.cppblog.com/beautykingdom/archive/2010/11/14/133602.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>有关异步读写、通信 </title><link>http://www.cppblog.com/beautykingdom/archive/2010/09/06/126028.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Mon, 06 Sep 2010 09:33:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/09/06/126028.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/126028.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/09/06/126028.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/126028.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/126028.html</trackback:ping><description><![CDATA[<div><span class="Apple-tab-span" style="white-space:pre">	</span>简介</div><div><br></div><div>一般来说，简单的异步（Asynchronous） 调用是这样一种调用方式：发起者请求一个异步调用，通知执行者，然后处理其他工作，在某一个同步点等待执行者的完成；执行者执行调用的实际操作，完成后通 知发起者。可以看出，在异步调用中有两种角色：发起者和执行者，它们都是能主动运行的对象，我们称为主动对象，同时还有一个同步点，主动对象在同步点协调 同步。在本文中，我们讨论主要是通用计算机、多进程多线程的分时操作系统上的异步调用。在操作系统的角度上来看，主动对象包括了进程、线程和硬件上的IC等，至于中断，可以看作总是在某个进程或者线程的上下文借用一下CPU。而同步操作可以通过操作系统得各种同步机制：互斥锁，信号灯等等来完成。</div><div><br></div><div>我们可以先看看异步调用在Windows(本文中一般不加指出的话，都是特指NT/2000)读写文件中的应用。Windows中的ReadFile和WriteFile都提供了异步的接口。以ReadFile为例，</div><div><br></div><div>BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped);</div><div><br></div><div>如果最后一个参数lpOverlapped不为NULL，并且文件以FILE_FLAG_OVERLAPPED 标志打开，那么这个调用就是异步的：ReadFile会立刻返回，如果操作没有立刻完成（返回FALSE并且GetLastError()返回 ERROR_IO_PENDING），那么调用者可以在某个时刻通过WaitForSingleObject等函数来等待中的hEvent来等待操作完成 （可能已经完成）进行同步，当操作完成以后，可以调用GetOverlappedResult者获得操作的结果，比如是否成功，读取了多少字节等等。这里 的发起者就是应用程序，而执行者就是操作系统本身，至于执行者是怎么执行的，我们会在后面的篇幅讨论。而两者的同步就是通过一个Windows Event来完成。</div><div><br></div><div>把这个异步调用的过程再抽象和扩展一些，我们可以把异步调用需要解决的问题归结为两个：一个是执行的动力，另一个是主动对象的调度。简单来说，前者是各个主动对象（线程、进程或者一些代码）是如何获得CPU，后者是各个主动对象如何协同工作， 保证操作的流程是协调正确的。一般来说，进程和线程都可以由操作系统直接调度而获得CPU，而更细粒度的，比如一些代码的调度，往往就需要一个更复杂的模 型（比如在操作系统内部的实现，这时候线程的粒度太粗了）。而主动对象的调度，当参与者较少的时候，可以通过基本的同步机制来完成，在更复杂的情况下，可 能通过一个schedule机制来做会更实际一些。</div><div><br></div><div>动力和调度</div><div><br></div><div>如前所述，异步调用主要需要解决两 个问题：执行的动力和执行的调度。最普遍的情况就是，一个主导流程的调用者进程（线程），一个或多个工作者进程（线程），通过操作系统提供的同步机制来完 成异步调用。这个同步机制在扩展化的情形下，是一个或多个栅栏Barrier，对应于每个同步的执行点。所有需要在这个执行点同步的主动对象会等待相应的 Barrier，直到所有对象都完成。在一些简化的情形，比如说工作者并不关心调用者的同步，那么这个Barrier可以简化成信号灯，在只有一个工作者 的情况下，可以简化成一个Windows事件Event或者条件变量 Condition Variable。</div><div><br></div><div>现在来考虑复杂的情 形。假设我们用一些线程来协作完成一项工作，各个线程的执行之间有先后顺序上的限制，而操作系统就是这项工作的调度者，负责在适当的时候调度适当的线程来 获得CPU。显然，并发执行中的一个线程对于另外一个线程来说，本质上就是异步的，假如它们之间有调用关系，那也就是一个异步调用。而操作系统可以通过基 本的同步机制使得合适的线程才被调度，其他未完成的线程则处于等待状态。举例说，我们有4个线程A,B,C,D来完成一项工作，其中的顺序限制是 A&gt;B;C&gt;D，&#8220;&gt;&#8221;表示左边的线程完成必须先于右边的线程执行，而&#8220;;&#8221;表示两个线程可以同时进行。同时假设B的一个操作需要调用 C来完成，显而易见，这时候这个操作就是一个异步调用。我们可以在每个&#8220;&gt;&#8221;的位置设定一个同步点，然后通过一个信号灯来完成同步。线程B，C等待 第一个信号灯，而D会等待第二个信号灯。这个例子的动力和调度都是通过操作系统的基本机制（线程调度和同步机制）来完成。</div><div><br></div><div>把这个过程抽象一下，可以描述为：若干个主动对象（包括代码）协调来完成一项工作，通过一个调度器来调度，实际上，这个调度器可能只是一些调度规则。显 然，进程或者线程只要被调度就能获得CPU，所以我们主要考虑代码（比如一个函数）怎么样才能获得执行。用工作者线程来调用这个函数显然是直观和通用的一 个方案。事实上，在用户空间(user space)或者用户态(user mode)，这个方法是很常用的。而在内核态(kernel mode)，则可以通过中断来获得CPU，这个通过注册IDT入 口和触发软中断就可以完成。硬件设备上的IC是另一个动力之源。而主动对象的调度，最基本的也是前面说的各种同步机制。另一个常用的机制就是回调函数，需 要注意的是，回调函数一般会发生在跟调用者不一样的上下文，比如说同一个进程的不同线程，这个差别会带来一些限制。如果需要回调发生在调用者的进程（线 程）上下文，则需要一些类似Unix下的signal或者Windows下的APC机制，这一点我们在后面会有所阐述。那么在回调函数里面一般作些什么事情呢？最常用的， 跟同步机制结合在一起，当然就是释放一个互斥锁，信号灯或者Windows Event（Unix的条件变量）等等，从而使得等待同步的其他对象可以得到调度而重新执行，实际上，也可以看作是通知调度器（操作系统）某些主动对象 （等待同步的）可以重新被调度了，从而调度器重新调度。但是对于另外一些调度器，在这个过程中可能不需要同步对象的参与。在一些极端一些的例子里，调度甚 至不要求严格有序的。</div><div><br></div><div>在实际应用中，根据环境的限制，异步调用的动力和调度的实现方式可以有很大差别。我们会在后面的例子里加以说明。 操作系统中的异步：Windows的异步I/O。</div><div><br></div><div>Windows NT/2000是一个抢占式的分时操作系统。Windows的调度单位是线程，它的 I/O架构是完全异步的，也就是说同步的I/O实际上都基于异步I/O来完成。一个用户态的线程请求一个I/O的时候会导致一个运行状态从user mode到kernel mode的转变（操作系统把内核映射到每个进程的2G-4G的地址上，对于每个进程都是一样的）。这个过程是通过中断调用内核输出的一些System Service来完成，比如说ReadFile实际上会执行NtReadFile（ZwReadFile），需要注意的是，运行上下文仍然是当前线程。 NtReadFile的实现则基于Windows内核的异步I/O框架，在I/O Manager的协助下完成。需要指出的是，I/O Manager只是由若干API构成的一个抽象概念，并没有一个真正的I/O Manager线程在运行。</div><div><br></div><div>Windows的I/O驱动程序是层次堆积的。每个驱动程序会提供一致的接口以供初始化、清理和功能调用。驱动程序的调用基于I/O请求包（I/O Request Packet, IRP），而不是像普通的函数调用那样使用栈来传递参数。操作系统和PnP管理器根据注册表在 适当的时机初始化和清理相应的驱动程序。在一般的功能调用的时候，IRP里面会指定功能调用号码以及相应的上下文或者参数（I/O stack location）。一个驱动程序可能调用别的驱动程序，这个过程可能是同步的（线程上下文不改变)，也可能是异步的。NtReadFile的实现，大致 是向最上层的驱动程序发出一个或多个IRP，然后等待相应事件的完成（同步的情况），或者直接返回（带Overlapped的情况），这些都在发起请求的 线程执行。</div><div><br></div><div>当驱动程序处理IRP的时候，它可能立刻完成，也可能在中断里才能完成，比如说，往硬件设备发出一个请求（通常可以是写 I/O port），当设备完成操作的时候会触发一个中断，然后在中断处理函数里得到操作结果。Windows有两类中断，硬件设备的中断和软中断，分成若干个不 同的优先级（IRQL）。软中断主要有两种：DPC(Delayed Procedure Call)和APC(Asynchronous Procedure Call)，都处于较低的优先级。驱动程序可以为硬件中断注册ISR(Interrupt Service Routine)，一般就是修改IDT某个条目的入口。同样，操作系统也会为DPC和APC注册适当的中断处理例程（也是在IDT中）。</div><div><br></div><div>值得指出的是，DPC是跟处理器相关的，每个处理器会有一个DPC队列，而APC是跟线程相关的，每个线程会有它的APC队列（实际上包括一个 Kernel APC队列和User APC队列，它们的调度策略有所区别），可以想象，APC并不算严格意义上的中断，因为中断可能发生在任何一个线程的上下文中，它被称为中断，主要是因为 IRQL的提升（从PASSIVE到APC），APC的调度一般在线程切换等等情形下进行。当中断发生的时候，操作系统会调用中断处理例程，对于硬件设备 的ISR，一般处理是关设备中断，发出一个DPC请求，然后返回。不在设备的中断处理中使用太多的CPU时间，主要考虑是否则可能丢失别 的中断。由于硬件设备中断的IRQL比DPC中断的高，所以在ISR里面DPC会阻塞，直到ISR返回IRQL回到较低的水平，才会触发DPC中断，在 DPC中断里执行从硬件设备读取数据以及重新请求、开中断等操作。ISR或者DPC可能在任何被中断的线程上下文（arbitrary thread context）执行，事实上线程的上下文是不可见的，可以认为是系统借用一下时间片而已。</div><div><br></div><div>总的来说，Windows的异步I/O架 构中，主要有两种动力，一是发起请求的线程，一部分内核代码会在这个线程上下文执行，二是ISR和DPC，这部分内核代码会在中断里完成，可能使用任何一 个线程的上下文。而调度常见使用回调和事件（KEVENT），比如说在往下一层的驱动程序发出请求的时候，可以指定一个完成例程Completion Routine，当下层的驱动完成这个请求的时候会调用这个例程，而往往在这个例程里，就是简单的触发一下一个事件。 另外可以顺便提一下Linux。Linux 2.6也有类似的中断机制，它有更多的软中断优先级，即不同优先级的softirq，而类似于DPC，Linux也提供了专门的软中断，对应DPC的就是 tasklet。Linux没有一个像windows这么一致的层次驱动程序架构，所以它的异步I/O稍微粗糙一些，主要是通过以前的一些阻塞点，现在直 接返回-EIOCBRETRY，而让调用者在合适的时机继续重试。在这个方法中，可以认为整个操作由一个函数完成，每次操作有进展时，都把这个函数从头执 行一遍，当然已经完成的部分就不会再有实际的I/O。这样的最大好处是原有的文件系统和驱动程序不用完全重写。而对于同步调用，只要阻塞就可以了，这样对 系统的修改较小。这时候，要提供POSIX aio的语义，就可能需要提供一些用户线程来完成重试的过程了（回想Windows可以通过中断和DPC完成的）。而对于Solaris，也是类似的处理，如果设备支持异步I/O，那就通过中断可以完成，否则就使用内部的LWP来模拟。</div><div>应用程序：一个异步的HTTP服务器的设计</div><div><br></div><div>假设我们要设计一个HTTP服务器，它的设计目标包括：高并发性、精简 （部分支持HTTP/1.1）、支持plug-in结构。在不少场合可能都有这个需求。总体上来说，HTTP服务器可以类比成一个基于多线程的操作系 统：OS调度每个工作线程在适当的时候获得执行，而工作线程提供服务（也就是处理HTTP请求）。在这个基础上，主要的考虑就是调度粒度的大小，粒度太大 的时候并发性会降低，而粒度太小又可能因为任务切换（考虑OS的Context Switching）而导致效率降低，所以这又是一个折衷的结果。类似于Apache（以及其他的HTTP服务器），我们可以把一个HTTP处理过程分为 若干个状态，基于这些状态可以构造出一个HTTP处理的状态机。这种情况下，我们就可以把每个状态的处理作为调度的粒度。一个调度过程就是：一个工作线程 从全局的任务队列里取出一个HTTP_Context结构；根据当前的状态完成相应处理；然后根据状态机设置下一个状态；再放回到全局的任务队列里。这样 子，若干个HTTP状态就可以通过这个调度策略构成一个完整HTTP处理过程。显而易见，一个状态对于下一个状态处理的调用都可以认为是异步的。一个 HTTP状态机的设计如下图所示。</div><div><img src="http://www.cppblog.com/images/cppblog_com/beautykingdom/gr4o3x9474bo.jpg" id="" width="512" height="398" vspace="0" hspace="0" border="" align="baseline" alt="" longdesc=""><br></div><div>　　　　</div><div>图1. HTTP状态机</div><div><br></div><div>工作线程的函数其实就是两个操作：从状态队列里取出一个HTTP_Context，调用HTTP_Context的service()函数，周而复此。 在这个架构上，就很容易引入异步I/O和Plug-in的机制了。事实上我们也可以使用基于事件（例如select/poll）的I/O策略来模拟异步I /O，实现中使用一个用户线程就可以了。</div><div><br></div><div>对于异步I/O和Plug-in的调用，我们也是采用类似于Linux 2.6里面aio的重试方案，而异步完成的时候采用回调函数。在某个状态上，如果系统需要I/O操作（recv或者send），则会请求一个异步I /O（操作系统提供的异步I/O或者由用户线程模拟的异步I/O），这时候相应的HTTP_Context不会重新回到状态队列里，而在I/O完成的回调 函数里面才会重新放回到状态队列，得到重新调度的机会。HTTP_Context得到重新调度的时候会检查I/O状态（这个可以通过一些标志位来完成）， 如果已经完成，则处理然后设置下一状态，重新调度，否则可以重新请求一个新的I/O请求。Plug-in也可以使用类似的方案，比如说一个Plug-in 要跟外部的一个服务器通信，这时候就可以在通信完成的时候才把HTTP_Context重新放回到状态队列。显然，Plug-in跟HTTP状态是多对多 的关系，一个Plug-in可以在若干个关心的状态注册自身，同时还可以设置一些short-path来提高处理的效率。</div><div><br></div><div>结论</div><div><br></div><div>总的来说，异步调用的设计和应用归根结底就是对多个主动对象的管理问题：如何提供执行的动力以及如何保证执行的顺序逻辑。主要考虑的问题是主动对象的粒 度以及执行方式，同步或者回调来完成顺序的调度，或者使用近似的调度而加一些鲁棒的错误处理机制来保证语义的正确。后者可以考虑在使用基于事件的 socket的时候，readable事件的通知可以是冗余的，或者说可以比实际中发生的readable事件更多，这个时候使用非阻塞的socket, 有些read()（或者recv()）会直接返回EWOULDBLOCK，系统只要考虑处理这种情况（使用non blocking socket而不是blocking socket），当例外的情况不多的时候是可以接受的。这时候可以说事件的报告就只是近似的。</div><div>from:</div><div><a href="http://hi.baidu.com/hytjfxk/blog/item/d9262cdfcb298c14632798b3.html">http://hi.baidu.com/hytjfxk/blog/item/d9262cdfcb298c14632798b3.html</a></div><div><br></div><img src ="http://www.cppblog.com/beautykingdom/aggbug/126028.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-09-06 17:33 <a href="http://www.cppblog.com/beautykingdom/archive/2010/09/06/126028.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>semaphore and spinlock</title><link>http://www.cppblog.com/beautykingdom/archive/2010/04/01/111257.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Thu, 01 Apr 2010 03:50:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/04/01/111257.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/111257.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/04/01/111257.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/111257.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/111257.html</trackback:ping><description><![CDATA[<font color="#000000" size="4">内核同步措施<br>
<br>
&nbsp;&nbsp;&nbsp;      为了避免并发，防止竞争。内核提供了一组同步方法来提供对共享数据的保护。
我们的重点不是介绍这些方法的详细用法，而是强调为什么使用这些方法和它们之间的差别。<br>
&nbsp;&nbsp;&nbsp; Linux
使用的同步机制可以说从2.0到2.6以来不断发展完善。从最初的原子操作，到后来的信号量，从大内核锁到今天的自旋锁。这些同步机制的发展伴随
Linux从单处理器到对称多处理器的过度；伴随着从非抢占内核到抢占内核的过度。锁机制越来越有效，也越来越复杂。<br>
&nbsp;&nbsp;&nbsp;
目前来说内核中原子操作多用来做计数使用，其它情况最常用的是两种锁以及它们的变种:一个是自旋锁，另一个是信号量。我们下面就来着重介绍一下这两种锁机
制。<br>
<br>
<br>
自旋锁<br>
------------------------------------------------------<br>
<font color="#800000"><strong>&nbsp;&nbsp;&nbsp;
自旋锁是专为防止多处理器并发而引入的一种锁，它在内核中大量应用于中断处理等部分(对于单处理器来说，防止中断处理中的并发可简单采用关闭中断的方式，
不需要自旋锁)。<br>
&nbsp;&nbsp;&nbsp;
自旋锁最多只能被一个内核任务持有，如果一个内核任务试图请求一个已被争用(已经被持有)的自旋锁，那么这个任务就会一直进行忙循环——旋转——等待锁重
新可用。</strong></font>要是锁未被争用，请求它的内核任务便能立刻得到它并且继续进行。自旋锁可以在任何时刻防止多于一个的内核任务同
时进入临界区，因此这种锁可有效地避免多处理器上并发运行的内核任务竞争共享资源。<br>
&nbsp;&nbsp;&nbsp;
事实上，自旋锁的初衷就是：在短期间内进行轻量级的锁定。一个被争用的自旋锁使得请求它的线程在等待锁重新可用的期间进行自旋(特别浪费处理器时间)，所
以自旋锁不应该被持有时间过长。如果需要长时间锁定的话, 最好使用信号量。<br>
自旋锁的基本形式如下：<br>
&nbsp;&nbsp;&nbsp;      spin_lock(&amp;mr_lock);<br>
&nbsp;&nbsp;&nbsp;      //临界区<br>
&nbsp;&nbsp;&nbsp;      spin_unlock(&amp;mr_lock);<br>
<br>
&nbsp;&nbsp;&nbsp;
因为自旋锁在同一时刻只能被最多一个内核任务持有，所以一个时刻只有一个线程允许存在于临界区中。这点很好地满足了对称多处理机器需要的锁定服务。在单处
理器上，自旋锁仅仅当作一个设置内核抢占的开关。如果内核抢占也不存在，那么自旋锁会在编译时被完全剔除出内核。<br>
&nbsp;&nbsp;&nbsp;      简单的说，<font color="#800000"><strong>自旋锁在内核中主要用来防止多处理器中并发访问临界区，防止
内核抢占造成的竞争。</strong></font>另外自旋锁不允许任务睡眠(持有自旋锁的任务睡眠会造成自死锁——因为睡眠有可能造成持有锁的内核
任务被重新调度，而再次申请自己已持有的锁)，<font color="#800000"><strong>它能够在中断上下文中使用</strong></font>。<br>
&nbsp;&nbsp;&nbsp;
死锁：假设有一个或多个内核任务和一个或多个资源，每个内核都在等待其中的一个资源，但所有的资源都已经被占用了。这便会发生所有内核任务都在相互等待，
但它们永远不会释放已经占有的资源，于是任何内核任务都无法获得所需要的资源，无法继续运行，这便意味着死锁发生了。自死琐是说自己占有了某个资源，然后
自己又申请自己已占有的资源，显然不可能再获得该资源，因此就自缚手脚了。<br>
<br>
<br>
信号量<br>
------------------------------------------------------<br>
&nbsp;&nbsp;&nbsp;
Linux中的信号量是一种睡眠锁。如果有一个任务试图获得一个已被持有的信号量时，信号量会将其推入等待队列，然后让其睡眠。这时处理器获得自由去执行
其它代码。当持有信号量的进程将信号量释放后，在等待队列中的一个任务将被唤醒，从而便可以获得这个信号量。<br>
&nbsp;&nbsp;&nbsp;
信号量的睡眠特性，使得信号量适用于锁会被长时间持有的情况；只能在进程上下文中使用，因为中断上下文中是不能被调度的；另外当代码持有信号量时，不可以
再持有自旋锁。<br>
<br>
信号量基本使用形式为：<br>
static DECLARE_MUTEX(mr_sem);//声明互斥信号量<br>
if(down_interruptible(&amp;mr_sem))<br>
&nbsp;&nbsp;&nbsp;      //可被中断的睡眠，当信号来到，睡眠的任务被唤醒 <br>
&nbsp;&nbsp;&nbsp;      //临界区<br>
up(&amp;mr_sem);<br>
<br>
<br>
信号量和自旋锁区别<br>
------------------------------------------------------<br>
&nbsp;&nbsp;&nbsp;      虽然听起来两者之间的使用条件复杂，其实在实际使用中信号量和自旋锁并不易混淆。注意以下原则:<br>
&nbsp;&nbsp;&nbsp;
如果代码需要睡眠——这往往是发生在和用户空间同步时——使用信号量是唯一的选择。由于不受睡眠的限制，使用信号量通常来说更加简单一些。如果需要在自旋
锁和信号量中作选择，应该取决于锁被持有的时间长短。理想情况是所有的锁都应该尽可能短的被持有，但是如果锁的持有时间较长的话，使用信号量是更好的选
择。另外，信号量不同于自旋锁，它不会关闭内核抢占，所以持有信号量的代码可以被抢占。这意味者信号量不会对影响调度反应时间带来负面影响。<br>
<br>
<br>
自旋锁对信号量<br>
------------------------------------------------------<br>
需求 &nbsp;&nbsp;&nbsp;      &nbsp;&nbsp;&nbsp;      &nbsp;&nbsp;&nbsp;      &nbsp;&nbsp;&nbsp;      &nbsp;&nbsp;&nbsp;      建议的加锁方法<br>
<br>
低开销加锁 &nbsp;&nbsp;&nbsp;      &nbsp;&nbsp;&nbsp;      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;        优先使用自旋锁<br>
短期锁定 &nbsp;&nbsp;&nbsp;      &nbsp;&nbsp;&nbsp;      &nbsp;&nbsp;&nbsp;      &nbsp;&nbsp;&nbsp;      优先使用自旋锁<br>
长期加锁 &nbsp;&nbsp;&nbsp;      &nbsp;&nbsp;&nbsp;      &nbsp;&nbsp;&nbsp;      &nbsp;&nbsp;&nbsp;      优先使用信号量<br>
中断上下文中加锁 &nbsp;&nbsp;&nbsp;      &nbsp;&nbsp;&nbsp;&nbsp;     使用自旋锁<br>
持有锁是需要睡眠、调度&nbsp;&nbsp;&nbsp;&nbsp;   使用信号量<br><br>from:<br>http://blog.chinaunix.net/u1/38576/showart_367985.html<br><br></font><img src ="http://www.cppblog.com/beautykingdom/aggbug/111257.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-04-01 11:50 <a href="http://www.cppblog.com/beautykingdom/archive/2010/04/01/111257.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>An In-Depth Look into the Win32 Portable Executable File Format</title><link>http://www.cppblog.com/beautykingdom/archive/2010/03/25/110504.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Thu, 25 Mar 2010 07:17:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/03/25/110504.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/110504.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/03/25/110504.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/110504.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/110504.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: from:http://msdn.microsoft.com/zh-cn/magazine/cc301808%28en-us%29.aspxDownload the code for this article: PE.exe(98KB)part1:SUMMARYA good understanding of the Portable Executable (PE) fi...&nbsp;&nbsp;<a href='http://www.cppblog.com/beautykingdom/archive/2010/03/25/110504.html'>阅读全文</a><img src ="http://www.cppblog.com/beautykingdom/aggbug/110504.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-03-25 15:17 <a href="http://www.cppblog.com/beautykingdom/archive/2010/03/25/110504.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>IA-32 保护模式内存管理</title><link>http://www.cppblog.com/beautykingdom/archive/2010/03/25/110503.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Thu, 25 Mar 2010 07:03:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/03/25/110503.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/110503.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/03/25/110503.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/110503.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/110503.html</trackback:ping><description><![CDATA[<h2>  CHAPTER 3
PROTECTED-MODE MEMORY MANAGEMENT</h2>
<h3> 3.1. MEMORY MANAGEMENT OVERVIEW</h3>
<p>  The memory management facilities of the IA-32 architecture are
divided into two parts: segmentation and paging. Segmentation provides a
mechanism of isolating individual code, data, and stack modules so that
multiple programs (or tasks) can run on the same processor without
interfering with one another. Paging provides a mechanism for
implementing a conventional demand-paged, virtual-memory system where
sections of a program&#8217;s execution environment are mapped into physical
memory as needed. Paging can also be used to provide isolation
between multiple tasks. When operating in protected mode, some form of
segmentation must be used. There is no mode bit to disable
segmentation. The use of paging, however, is optional.</p>
<p class="translation">
IA-32架构的内存管理机构（facilities）可划分为两个部分：分段（segmentation）和分页（paging）。分段功能提供了分隔
代码、数据和堆栈的机制，从而使多个进程运行在同一个CPU物理地址空间内而互不影响；分页可用来实现一种&#8220;请求页式（demand-paged）&#8221;的虚
拟内存机制，从而页化程序执行环境，在程序运行时可将所需要的页映射到物理内存。分页机制也可用作隔离多进程任务。分段功能是CPU保护模式必须的，没有
设置位可以屏蔽内存分段；不过内存分页则是可选的。</p>
<p> These two mechanisms (segmentation and paging) can be configured to
support simple single-program (or single-task) systems, multitasking
systems, or multiple-processor systems that used shared memory.</p>
<p> As shown in Figure 3-1, segmentation provides a mechanism for
dividing the processor&#8217;s addressable memory space (called the linear
address space) into smaller protected address spaces called segments.
Segments can be used to hold the code, data, and stack for a program or
to hold system data structures (such as a TSS or LDT). If more than one
program (or task) is running on a processor, each program can be
assigned its own set of segments. The processor then enforces the
boundaries between these segments and insures that one program does not
interfere with the execution of another program by writing into the
other program&#8217;s segments.</p>
<p> <span class="translation">分段和分页机制被配置成支持单任务系统、多任务系统或多处理器系统。</span>
</p>
<p class="translation">
如图3-1，内存分段将CPU的可寻址空间（称为线性地址空间）划分更小的受保护的内存段，这些段存放程序的数据（代码、数据和堆栈）和系统的数据结构
（像TSS 或 LDT）。如果处理器运行着多个任务，那么每个任务都有一集自己独立的内存段。</p>
<p> The segmentation mechanism also allows typing of segments so that
the operations that may be performed on a particular type of segment can
be restricted.</p>
<p> All the segments in a system are contained in the processor&#8217;s linear
address space. To locate a byte in a particular segment, a logical
address (also called a far pointer) must be provided. A logical address
consists of a segment selector and an offset. The segment selector is a
unique identifier for a segment. Among other things it provides an
offset into a descriptor table (such as the global descriptor table,
GDT) to a data structure called a segment descriptor. Each segment has a
segment descriptor, which specifies the size of the segment, the access
rights and
privilege level for the segment, the segment type, and the location of
the first byte of the segment in the linear address space (called the
base address of the segment). The offset part of the logical address is
added to the base address for the segment to locate a byte within the
segment. The base address plus the offset thus forms a linear address in
the processor&#8217;s linear address space.</p>
<p> <span class="translation">进程的各个段都必须位于CPU的线性空间之内，进程要访问某段的一个字节，必须给出该字节
的逻辑地址（也叫远指针）。逻辑地址由段选择子（segment selector
）和偏移值组成。段选择子是段的唯一标识，指向一个叫段描述符的数据结构；段描述符位于一个叫描述表之内（如全局描述表GDT）;
每个段必须都有相应的段描述符，用以指定段大小、访问权限和段的特权级别（privilege
level）、段类型和段的首地址在线性地址空间的位置（叫段的基地址）。逻辑地址通过基地址加上段内偏移得到。</span>
</p>
<p><img  src="http://album.hi.csdn.net/app_uploads/keminlau/20081017/104727378.p.gif" alt="" align="middle">
</p>
<p>If paging is not used, the linear address space of the processor is
mapped directly into the physical address space of processor. The
physical address space is defined as the range of addresses that the
processor can generate on its address bus.</p>
<p> Because multitasking computing systems commonly define a linear
address space much larger than it is economically feasible to contain
all at once in physical memory, some method of &#8220;virtualizing&#8221; the linear
address space is needed. This virtualization of the linear address
space
is handled through the processor&#8217;s paging mechanism.</p>
<p class="translation">
如果不用分页功能，处理器的[线性地址空间]就会直接映射到[物理地址空间]。[物理地址空间]的大小就是处理器能通过地址总线产生的地址范围。为了直接
使用线性地址空间从而简化编程和实现多进程而提高内存的利用率，需要实现某种对线性地址空间进行&#8220;虚拟化（virtualizing）&#8221;，CPU的分页机
制实现了这种虚拟化。</p>
<p> Paging supports a &#8220;virtual memory&#8221; environment where a large linear
address space is simulated with a small amount of physical memory (RAM
and ROM) and some disk storage. When using paging, each segment is
divided into pages (typically 4 KBytes each in size), which are stored
either in physical memory or on the disk. The operating system or
executive maintains a page directory and a set of page tables to keep
track of the pages. When a program (or task) attempts to access an
address location in the linear address space, the processor uses the
page directory and page tables to translate the linear address into a
physical address and then performs the requested operation (read or
write) on the memory location. If the page being accessed is not
currently in physical memory, the processor interrupts execution of the
program (by generating a page-fault exception). The operating system or
executive then reads the page into physical memory from the disk and
continues executing the program. </p>
<p class="translation">
&#8220;虚拟内存&#8221;就是利用物理内存和磁盘来对CPU的线性地址进行模拟（kemin:高级语言源码指定的是符号地址，是虚的，有了虚拟内存即便是用汇编指定一
固定地址也是虚的。问题是这些虚存是怎么管理的）。当使用分页时，进程的每个段都会被分成大小固定的页，这些页可能在内存中，也可能在磁盘。操作系统用了
一张页目录（page
directory）和多张页表来管理这些页。当进程试图访问线性地址空间的某个位置，处理器会通过页目录和页表先将线性地址转换成物理地址，然后再访问
（读或写）（kemin：转换细节没有讲）。如果被访问的页当前不在内存，处理就会中断进程的运行（通过产生缺页异常中断）（kemin:怎么判断某页不
在内存？）。操作系统负责从磁盘读入该页并继续执行该进程（kemin:页读入的前前后后没有讲）。</p>
<p> When paging is implemented properly in the operating-system or
executive, the swapping of pages between physical memory and the disk is
transparent to the correct execution of a program. Even programs
written for 16-bit IA-32 processors can be paged (transparently) when
they are run in virtual-8086 mode.</p>
<p><br></p>
<p>from:</p>
<p>http://blog.csdn.net/keminlau/archive/2008/10/19/3090337.aspx<br></p><img src ="http://www.cppblog.com/beautykingdom/aggbug/110503.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-03-25 15:03 <a href="http://www.cppblog.com/beautykingdom/archive/2010/03/25/110503.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Context Switch Definition</title><link>http://www.cppblog.com/beautykingdom/archive/2010/02/25/108457.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Thu, 25 Feb 2010 15:09:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/02/25/108457.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/108457.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/02/25/108457.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/108457.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/108457.html</trackback:ping><description><![CDATA[<p><font size="3">A <em> context switch</em>  (also sometimes referred to as a <em> process  switch</em>  or a <em> task switch</em> ) is the switching of the <a href="http://blog.csdn.net/wave_1102/archive/2007/09/04/cpu.html">CPU</a> (central processing unit) from one <a href="http://blog.csdn.net/wave_1102/archive/2007/09/04/process.html"><em> process</em> </a> or <em> thread</em>  to another. </font></p>
<p><font size="3">A process (also sometimes referred to as a <em> task</em> ) is an  <em> executing</em>  (i.e., running) <a href="http://blog.csdn.net/wave_1102/archive/2007/09/04/instance.html">instance</a> of a <a href="http://blog.csdn.net/wave_1102/archive/2007/09/04/program.html">program</a>. In <a href="http://blog.csdn.net/wave_1102/archive/2007/09/04/linuxdef.html">Linux</a>, threads  are lightweight processes that can run in parallel and share an <em> address  space</em>  (i.e., a range of <a href="http://blog.csdn.net/wave_1102/archive/2007/09/04/memory.html">memory</a> locations) and  other resources with their <em> parent</em>  processes (i.e., the processes that  created them). </font></p>
<p><font size="3">A <em> context</em>  is the contents of a CPU's <a href="http://blog.csdn.net/wave_1102/archive/2007/09/04/register.html"><em> registers</em> </a> and <em> program counter</em>  at any  point in time. A register is a small amount of very fast memory inside of a CPU  (as opposed to the slower <a href="http://blog.csdn.net/wave_1102/archive/2007/09/04/ram.html">RAM</a> main memory outside of the  CPU) that is used to speed the execution of <a href="http://blog.csdn.net/wave_1102/archive/2007/09/04/computer.html">computer</a>
programs by providing quick access to commonly used values, generally
those in the midst of a calculation. A program counter is a specialized
register that indicates the position of the CPU in its instruction
sequence and which holds either the address of the instruction being
executed or the address of the next instruction to be executed,
depending on the specific system. </font></p>
<p><font size="3">Context switching can be described in slightly more detail as the <a href="http://blog.csdn.net/wave_1102/archive/2007/09/04/kernel.html"><em> kernel</em> </a><a href="http://blog.csdn.net/wave_1102/archive/2007/09/04/operating_systems_list.html">operating system</a>)
performing the following activities with regard to processes (including
threads) on the CPU: (1) suspending the progression of one process and
storing the CPU's <em> state</em>  (i.e., the context) for that process
somewhere in memory, (2) retrieving the context of the next process
from memory and restoring it in the CPU's registers and (3) returning
to the location indicated by the program counter (i.e., returning to
the line of code at which the process was interrupted) in order to
resume the process. </font> (i.e., the core of the </p>
<p><font size="3">A context switch is sometimes described as the kernel suspending <em> execution  of one process</em>  on the CPU and resuming <em> execution of some other  process</em>
that had previously been suspended. Although this wording can help
clarify the concept, it can be confusing in itself because a process <em> is</em> ,  by definition, an executing instance of a program. Thus the wording  <em> suspending progression of a process</em>  might be preferable. </font></p>
<p><font size="3"><strong> Context Switches and Mode Switches</strong> </font> </p>
<p><font size="3">Context switches can occur only in <a href="http://blog.csdn.net/wave_1102/archive/2007/09/04/kernel_mode.html"><em> kernel  mode</em> </a>.
Kernel mode is a privileged mode of the CPU in which only the kernel
runs and which provides access to all memory locations and all other
system resources. Other programs, including applications, initially
operate in <a href="http://blog.csdn.net/wave_1102/archive/2007/09/04/user_mode.html"><em> user mode</em> </a>, but they can run portions of the  kernel code via <a href="http://blog.csdn.net/wave_1102/archive/2007/09/04/system_call.html"><em> system calls</em> </a>. A system  call is a request in a <a href="http://blog.csdn.net/wave_1102/archive/2007/09/04/unix-like.html">Unix-like</a> operating system  by an <em> active process</em>  (i.e., a process currently progressing in the CPU)  for a service performed by the kernel, such as <em> input/output</em>  (I/O) or  <em> process creation</em>
(i.e., creation of a new process). I/O can be defined as any movement
of information to or from the combination of the CPU and main memory
(i.e. RAM), that is, communication between this combination and the
computer's users (e.g., via the keyboard or mouse), its <a href="http://blog.csdn.net/wave_1102/archive/2007/09/04/storage.html">storage</a> devices (e.g., disk or tape drives), or other  computers. </font></p>
<p><font size="3">The
existence of these two modes in Unix-like operating systems means that
a similar, but simpler, operation is necessary when a system call
causes the CPU to shift to kernel mode. This is referred to as a <em> mode switch</em>  rather than  a context switch, because it does not change the current process. </font></p>
<p><font size="3">Context switching is an essential feature of <a href="http://blog.csdn.net/wave_1102/archive/2007/09/04/multitasking.html"><em> multitasking</em> </a>
operating systems. A multitasking operating system is one in which
multiple processes execute on a single CPU seemingly simultaneously and
without interfering with each other. This illusion of <em> concurrency</em>
is achieved by means of context switches that are occurring in rapid
succession (tens or hundreds of times per second). These context
switches occur as a result of processes voluntarily relinquishing their
time in the CPU or as a result of the <em> scheduler</em>  making the switch  when a process has used up its CPU <em> time slice</em> . </font></p>
<p><font size="3">A context switch can also occur as a result of a <em> hardware interrupt</em> ,  which is a signal from a hardware device (such as a keyboard, mouse, modem or  system clock) to the kernel that an <em> event</em>  (e.g., a key press, mouse  movement or arrival of data from a <a href="http://blog.csdn.net/wave_1102/archive/2007/09/04/network.html">network</a>  connection) has occurred. </font></p>
<p><font size="3">Intel 80386 and higher CPUs contain hardware support for context switches.  However, most modern operating systems perform <em> software context  switching</em> , which can be used on any CPU, rather than <em> hardware context  switching</em>
in an attempt to obtain improved performance. Software context
switching was first implemented in Linux for Intel-compatible
processors with the 2.4 kernel. </font></p>
<p><font size="3">One
major advantage claimed for software context switching is that, whereas
the hardware mechanism saves almost all of the CPU state, software can
be more selective and save only that portion that actually needs to be
saved and reloaded. However, there is some question as to how important
this really is in increasing the efficiency of context switching. Its
advocates also claim that software context switching allows for the
possibility of improving the switching code, thereby further enhancing
efficiency, and that it permits better control over the validity of the
data that is being loaded. </font></p>
<p><font size="3"><strong> The Cost of Context Switching</strong> </font> </p>
<p><font size="3">Context
switching is generally computationally intensive. That is, it requires
considerable processor time, which can be on the order of nanoseconds
for each of the tens or hundreds of switches per second. Thus, context
switching represents a substantial <em> cost</em>  to the system in terms of CPU time and can,  in fact, be the most costly operation on an operating system. </font></p>
<p><font size="3">Consequently,
a major focus in the design of operating systems has been to avoid
unnecessary context switching to the extent possible. However, this has
not been easy to accomplish in practice. In fact, although the cost of
context switching has been declining when measured in terms of the
absolute amount of CPU time consumed, this appears to be due mainly to
increases in CPU clock speeds rather than to improvements in the
efficiency of context switching itself. </font></p>
<p><font size="3">One
of the many advantages claimed for Linux as compared with other
operating systems, including some other Unix-like systems, is its
extremely low cost of context switching and mode switching. </font></p>
<br>from:<br>http://blog.csdn.net/wave_1102/archive/2007/09/04/1771745.aspx
<br><br><img src ="http://www.cppblog.com/beautykingdom/aggbug/108457.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-02-25 23:09 <a href="http://www.cppblog.com/beautykingdom/archive/2010/02/25/108457.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>堆和栈的区别</title><link>http://www.cppblog.com/beautykingdom/archive/2009/12/11/103023.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Fri, 11 Dec 2009 15:53:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2009/12/11/103023.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/103023.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2009/12/11/103023.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/103023.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/103023.html</trackback:ping><description><![CDATA[<p>堆：　是大家共有的空间，分全局堆和局部堆。全局堆就是所有没有分配的空间，局部堆就是用户分配的空间。堆在操作系统对进程初始化的时候分配，运行过程中也可以向系统要额外的堆，但是记得用完了要还给操作系统，要不然就是内存泄漏。</p>
<p>栈：是个线程独有的，保存其运行状态和局部自动变量的。栈在线程开始的时候初始化，每个线程的栈互相独立，因此，栈是　thread safe的。每个Ｃ　＋＋对象的数据成员也存在在栈中，每个函数都有自己的栈，栈被用来在函数之间传递参数。操作系统在切换线程的时候会自动的切换栈，就是切换　ＳＳ／ＥＳＰ寄存器。栈空间不需要在高级语言里面显式的分配和释放。</p>
<p>堆和栈的区别</p>
<p>一、预备知识—程序的内存分配<br>一个由c/C++编译的程序占用的内存分为以下几个部分：<br>1、栈区（stack）— 由编译器自动分配释放，存放函数的参数值，局部变量的值等。其操作方式类似于数据结构中的栈。</p>
<p>2、堆区（heap） — 一般由程序员分配释放，若程序员不释放，程序结束时可能由OS回收。注意它与数据结构中的堆是两回事，分配方式倒是类似于链表。</p>
<p>3、全局区（静态区）（static）—，全局变量和静态变量的存储是放在一块的，初始化的全局变量和静态变量在一块区域，未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 - 程序结束后由系统释放。</p>
<p>4、文字常量区&nbsp;&nbsp; —常量字符串就是放在这里的。程序结束后由系统释放。</p>
<p>5、程序代码区—存放函数体的二进制代码。</p>
<p>二、例子程序<br>//main.cpp<br>int a = 0; 全局初始化区<br>char *p1; 全局未初始化区<br>main()<br>{<br>int b; 栈<br>char s[] = "abc"; 栈<br>char *p2; 栈<br>char *p3 = "123456"; 123456\0在常量区，p3在栈上。<br>static int c =0；全局（静态）初始化区<br>p1 = (char *)malloc(10);<br>p2 = (char *)malloc(20);<br>分配得来得10和20字节的区域就在堆区。<br>strcpy(p1, "123456"); 123456\0放在常量区，编译器可能会将它与p3所指向的"123456"优化成一个地方。<br>}<br>二、堆和栈的理论知识<br>2.1申请方式<br>stack:<br>由系统自动分配。例如，声明在函数中一个局部变量 int b; 系统自动在栈中为b开辟空间<br>heap:<br>需要程序员自己申请，并指明大小，在c中malloc函数<br>如p1 = (char *)malloc(10);<br>在C++中用new运算符<br>如p2 = (char *)malloc(10);<br>但是注意p1、p2本身是在栈中的。</p>
<p><br>2.2<br>申请后系统的响应<br>栈：只要栈的剩余空间大于所申请空间，系统将为程序提供内存，否则将报异常提示栈溢出。<br>堆： 首先应该知道操作系统有一个记录空闲内存地址的链表，当系统收到程序的申请时，会遍历该链表，寻找第一个空间大于所申请空间的堆结点，然后将该结点从空闲 结点链表中删除，并将该结点的空间分配给程序，另外，对于大多数系统，会在这块内存空间中的首地址处记录本次分配的大小，这样，代码中的delete语句才能正确的释放本内存空间。另外，由于找到的堆结点的大小不一定正好等于申请的大小，系统会自动的将多余的那部分重新放入空闲链表中。</p>
<p>2.3申请大小的限制<br>栈：在Windows下,栈是向低地址扩展的数据结构，是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的，在WINDOWS下，栈的大小是2M（也可能是1M，它是一个编译时就确定的常数），如果申请的空间超过栈的剩余空间时，将提示overflow。因此，能从栈获得的空间较小<br>。<br>堆：堆是向高地址扩展的数据结构，是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的，自然是不连续的，而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见，堆获得的空间比较灵活，也比较大。</p>
<p><br>2.4申请效率的比较：<br>栈由系统自动分配，速度较快。但程序员是无法控制的。<br>堆是由new分配的内存，一般速度比较慢，而且容易产生内存碎片,不过用起来最方便.<br>另外，在WINDOWS下，最好的方式是用VirtualAlloc分配内存，他不是在堆，也不是在栈是直接在进程的地址空间中保留一快内存，虽然用起来最不方便。但是速度快，也最灵活。</p>
<p>2.5堆和栈中的存储内容<br>栈：在函数调用时，第一个进栈的是主函数中后的下一条指令（函数调用语句的下一条可执行语句）的地址，然后是函数的各个参数，在大多数的C编译器中，参数是由右往左入栈的，然后是函数中的局部变量。注意静态变量是不入栈的。<br>当本次函数调用结束后，局部变量先出栈，然后是参数，最后栈顶指针指向最开始存的地址，也就是主函数中的下一条指令，程序由该点继续运行。<br>堆：一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容有程序员安排。</p>
<p>2.6存取效率的比较</p>
<p>char s1[] = "aaaaaaaaaaaaaaa";<br>char *s2 = "bbbbbbbbbbbbbbbbb";<br>aaaaaaaaaaa是在运行时刻赋值的；<br>而bbbbbbbbbbb是在编译时就确定的；<br>但是，在以后的存取中，在栈上的数组比指针所指向的字符串(例如堆)快。<br>比如：<br>void main()<br>{<br>char a = 1;<br>char c[] = "1234567890";<br>char *p ="1234567890";<br>a = c[1];<br>a = p[1];<br>return;<br>}<br>对应的汇编代码<br>10: a = c[1];<br>00401067 8A 4D F1 mov cl,byte ptr [ebp-0Fh]<br>0040106A 88 4D FC mov byte ptr [ebp-4],cl<br>11: a = p[1];<br>0040106D 8B 55 EC mov edx,dword ptr [ebp-14h]<br>00401070 8A 42 01 mov al,byte ptr [edx+1]<br>00401073 88 45 FC mov byte ptr [ebp-4],al<br>第一种在读取时直接就把字符串中的元素读到寄存器cl中，而第二种则要先把指针值读到edx中，在根据<br>edx读取字符，显然慢了。</p>
<p><br>2.7小结：<br>堆和栈的区别可以用如下的比喻来看出：<br>使用栈就象我们去饭馆里吃饭，只管点菜（发出申请）、付钱、和吃（使用），吃饱了就走，不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作，他的好处是快捷，但是自由度小。<br>使用堆就象是自己动手做喜欢吃的菜肴，比较麻烦，但是比较符合自己的口味，而且自由度大。<br></p>
<p><br></p>
<p>下面是另一篇，总结的比上面好：
</p>
<p>堆和栈的联系与区别dd</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
在bbs上，堆与栈的区分问题，似乎是一个永恒的话题，由此可见，初学者对此往往是混淆不清的，所以我决定拿他第一个开刀。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  首先，我们举一个例子：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  void f() { int* p=new int[5]; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
这条短短的一句话就包含了堆与栈，看到new，我们首先就应该想到，我们分配了一块堆内存，那么指针p呢？他分配的是一块栈内存，所以这句话的意思就是：
在栈内存中存放了一个指向一块堆内存的指针p。在程序会先确定在堆中分配内存的大小，然后调用operator
new分配内存，然后返回这块内存的首地址，放入栈中，他在VC6下的汇编代码如下：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  00401028&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  push&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  14h</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  0040102A&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  call&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  operator new
(00401060)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  0040102F&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  add&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  esp,4</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  00401032&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  dword ptr
[ebp-8],eax</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  00401035&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  eax,dword ptr
[ebp-8]</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  00401038&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  dword ptr
[ebp-4],eax</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  这里，我们为了简单并没有释放内存，那么该怎么去释放呢？是delete
p么？澳，错了，应该是delete []p，这是为了告诉编译器：我删除的是一个数组，VC6就会根据相应的Cookie信息去进行释放内存的工作。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  好了，我们回到我们的主题：堆和栈究竟有什么区别？</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  主要的区别由以下几点：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  1、管理方式不同；</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  2、空间大小不同；</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  3、能否产生碎片不同；</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  4、生长方向不同；</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  5、分配方式不同；</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  6、分配效率不同；</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
管理方式：对于栈来讲，是由编译器自动管理，无需我们手工控制；对于堆来说，释放工作由程序员控制，容易产生memory leak。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
空间大小：一般来讲在32位系统下，堆内存可以达到4G的空间，从这个角度来看堆内存几乎是没有什么限制的。但是对于栈来讲，一般都是有一定的空间大小
的，例如，在VC6下面，默认的栈空间大小是1M（好像是，记不清楚了）。当然，我们可以修改：&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
打开工程，依次操作菜单如下：Project-&gt;Setting-&gt;Link，在Category
中选中Output，然后在Reserve中设定堆栈的最大值和commit。</p>
<p>注意：reserve最小值为4Byte；commit是保留在虚拟内存的页文件里面，它设置的较大会使栈开辟较大的值，
可能增加内存的开销和启动时间。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
碎片问题：对于堆来讲，频繁的new/delete势必会造成内存空间的不连续，从而造成大量的碎片，使程序效率降低。对于栈来讲，则不会存在这个问题，
因为栈是先进后出的队列，他们是如此的一一对应，以至于永远都不可能有一个内存块从栈中间弹出，在他弹出之前，在他上面的后进的栈内容已经被弹出，详细的
可以参考数据结构，这里我们就不再一一讨论了。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
生长方向：对于堆来讲，生长方向是向上的，也就是向着内存地址增加的方向；对于栈来讲，它的生长方向是向下的，是向着内存地址减小的方向增长。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
分配方式：堆都是动态分配的，没有静态分配的堆。栈有2种分配方式：静态分配和动态分配。静态分配是编译器完成的，比如局部变量的分配。动态分配由
alloca函数进行分配，但是栈的动态分配和堆是不同的，他的动态分配是由编译器进行释放，无需我们手工实现。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
分配效率：栈是机器系统提供的数据结构，计算机会在底层对栈提供支持：分配专门的寄存器存放栈的地址，压栈出栈都有专门的指令执行，这就决定了栈的效率比
较高。堆则是C/C++函数库提供的，它的机制是很复杂的，例如为了分配一块内存，库函数会按照一定的算法（具体的算法可以参考数据结构/操作系统）在堆
内存中搜索可用的足够大小的空间，如果没有足够大小的空间（可能是由于内存碎片太多），就有可能调用系统功能去增加程序数据段的内存空间，这样就有机会分
到足够大小的内存，然后进行返回。显然，堆的效率比栈要低得多。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
从这里我们可以看到，堆和栈相比，由于大量new/delete的使用，容易造成大量的内存碎片；由于没有专门的系统支持，效率很低；由于可能引发用户态
和核心态的切换，内存的申请，代价变得更加昂贵。所以栈在程序中是应用最广泛的，就算是函数的调用也利用栈去完成，函数调用过程中的参数，返回地
址，EBP和局部变量都采用栈的方式存放。所以，我们推荐大家尽量用栈，而不是用堆。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  虽然栈有如此众多的好处，但是由于和堆相比不是那么灵活，有时候分配大量的内存空间，还是用堆好一些。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
无论是堆还是栈，都要防止越界现象的发生（除非你是故意使其越界），因为越界的结果要么是程序崩溃，要么是摧毁程序的堆、栈结构，产生以想不到的结果,就
算是在你的程序运行过程中，没有发生上面的问题，你还是要小心，说不定什么时候就崩掉，那时候debug可是相当困难的 :)&nbsp;&nbsp;&nbsp;
对了，还有一件事，如果有人把堆栈合起来说，那它的意思是栈，可不是堆，呵呵, 清楚了？</p>
<p><br>from：<br><a href="http://blog.chinaunix.net/u2/76292/showart_1327414.html">http://blog.chinaunix.net/u2/76292/showart_1327414.html</a></p>
<p><a href="http://blog.chinaunix.net/u2/76292/showart_1327414.html">http://hi.baidu.com/54wangjun/blog/item/d1b4a74424d5934f510ffedd.html<br></a></p><img src ="http://www.cppblog.com/beautykingdom/aggbug/103023.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2009-12-11 23:53 <a href="http://www.cppblog.com/beautykingdom/archive/2009/12/11/103023.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>同步、异步、阻塞和非阻塞的概念</title><link>http://www.cppblog.com/beautykingdom/archive/2009/12/05/102631.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Sat, 05 Dec 2009 15:10:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2009/12/05/102631.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/102631.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2009/12/05/102631.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/102631.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/102631.html</trackback:ping><description><![CDATA[ 在进行网络编程时，我们常常见到同步、异步、阻塞和非阻塞四种调用方式。这些方式彼此概念并不好理解。下面是我对这些术语的理解。
同步

  所谓同步，就是在发出一个功能调用时，在没有得到结果之前，该调用就不返回。按照这个定义，其实绝大多数函数都是同步调用（例如sin, isdigit等）。但是一般而言，我们在说同步、异步的时候，特指那些需要其他部件协作或者需要一定时间完成的任务。最常见的例子就是 SendMessage。该函数发送一个消息给某个窗口，在对方处理完消息之前，这个函数不返回。当对方处理完毕以后，该函数才把消息处理函数所返回的 LRESULT值返回给调用者。
异步

   异步的概念和同步相对。当一个异步过程调用发出后，调用者不能立刻得到结果。实际处理这个调用的部件在完成后，通过状态、通知和回调来通知调用者。以CAsycSocket类为例（注意，CSocket从CAsyncSocket派生，但是起功能已经由异步转化为同步），当一个客户端通过调用 Connect函数发出一个连接请求后，调用者线程立刻可以朝下运行。当连接真正建立起来以后，socket底层会发送一个消息通知该对象。
这里提到执行部件和调用者通过三种途径返回结果：状态、通知和回调。可以使用哪一种依赖于执行部件的实现，除非执行部件提供多种选择，否则不受调用者控制。如果执行部件用状态来通知，那么调用者就需要每隔一定时间检查一次，效率就很低（有些初学多线程编程的人，总喜欢用一个循环去检查某个变量的值，这其实是一种很严重的错误）。如果是使用通知的方式，效率则很高，因为执行部件几乎不需要做额外的操作。至于回调函数，其实和通知没太多区别。
阻塞

   阻塞调用是指调用结果返回之前，当前线程会被挂起。函数只有在得到结果之后才会返回。
有人也许会把阻塞调用和同步调用等同起来，实际上他是不同的。对于同步调用来说，很多时候当前线程还是激活的，只是从逻辑上当前函数没有返回而已。例如，我们在CSocket中调用Receive函数，如果缓冲区中没有数据，这个函数就会一直等待，直到有数据才返回。而此时，当前线程还会继续处理各种各样的消息。如果主窗口和调用函数在同一个线程中，除非你在特殊的界面操作函数中调用，其实主界面还是应该可以刷新。
socket接收数据的另外一个函数recv则是一个阻塞调用的例子。当socket工作在阻塞模式的时候，如果没有数据的情况下调用该函数，则当前线程就会被挂起，直到有数据为止。
非阻塞

   非阻塞和阻塞的概念相对应，指在不能立刻得到结果之前，该函数不会阻塞当前线程，而会立刻返回。
对象的阻塞模式和阻塞函数调用

   对象是否处于阻塞模式和函数是不是阻塞调用有很强的相关性，但是并不是一一对应的。阻塞对象上可以有非阻塞的调用方式，我们可以通过一定的API去轮询状态，在适当的时候调用阻塞函数，就可以避免阻塞。而对于非阻塞对象，调用特殊的函数也可以进入阻塞调用。函数select就是这样的一个例子。<img src ="http://www.cppblog.com/beautykingdom/aggbug/102631.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2009-12-05 23:10 <a href="http://www.cppblog.com/beautykingdom/archive/2009/12/05/102631.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>中断、DMA、通道</title><link>http://www.cppblog.com/beautykingdom/archive/2009/11/10/100672.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Tue, 10 Nov 2009 15:34:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2009/11/10/100672.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/100672.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2009/11/10/100672.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/100672.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/100672.html</trackback:ping><description><![CDATA[<p><font size=3><strong>一、轮询方式</strong><br>对I/O设备的程序轮询的方式，是早期的计算机系统对I/O设备的一种管理方式。它定时对各种设备轮流询问一遍有无处理要求。轮流询问之后，有要求的，则加以处理。在处理I/O设备的要求之后，处理机返回继续工作。<br>尽管轮询需要时间，但轮询不比I/O设备的速度要快得多，所以一般不会发生不能及时处理的问题。 <br>当然，再快的处理机，能处理的输入输出设备的数量也是有一定限度的。而且，程序轮询毕竟占据了CPU相当一部分处理时间，因此程序轮询是一种效率较低的方式，在现代计算机系统中已很少应用。</font></p>
<p><font size=3><strong>二、中断方式 </strong><br>处理器的高速和输入输出设备的低速是一对矛盾，是设备管理要解决的一个重要问题。为了提高整体效率，减少在程序直接控制方式中CPU之间的数据传送，是很必要的。 <br>在I/O设备中断方式下，中央处理器与I/O设备之间数据的传输步骤如下： <br>⑴在某个进程需要数据时，发出指令启动输入输出设备准备数据 <br>⑵在进程发出指令启动设备之后，该进程放弃处理器，等待相关I/O操作完成。此时，进程调度程序会调度其他就绪进程使用处理器。 <br>⑶当I/O操作完成时，输入输出设备控制器通过中断请求线向处理器发出中断信号，处理器收到中断信号之后，转向预先设计好的中断处理程序，对数据传送工作进行相应的处理。 <br>⑷得到了数据的进程，转入就绪状态。在随后的某个时刻，进程调度程序会选中该进程继续工作。 <br><strong>中断方式的优缺点 </strong><br>I/O设备中断方式使处理器的利用率提高，且能支持多道程序和I/O设备的并行操作。 <br>不过，中断方式仍然存在一些问题。首先，现代计算机系统通常配置有各种各样的输入输出设备。如果这些I/O设备都同过中断处理方式进行并行操作，那么中断次数的急剧增加会造成CPU无法响应中断和出现数据丢失现象。 <br>其次，如果I/O控制器的数据缓冲区比较小，在缓冲区装满数据之后将会发生中断。那么，在数据传送过程中，发生中断的机会较多，这将耗去大量的CPU处理时间。</font> </p>
<p><font size=3><strong>三、直接内存存取（DMA）方式 </strong><br>直接内存存取技术是指，数据在内存与I/O设备间直接进行成块传输。 <br><strong>DMA技术特征 </strong><br>DMA有两个技术特征，首先是直接传送，其次是块传送。 <br>所谓直接传送，即在内存与IO设备间传送一个数据块的过程中，不需要CPU的任何中间干涉，只需要CPU在过程开始时向设备发出&#8220;传送块数据&#8221;的命令，然后通过中断来得知过程是否结束和下次操作是否准备就绪。 <br><strong>DMA工作过程 </strong><br>⑴当进程要求设备输入数据时，CPU把准备存放输入数据的内存起始地址以及要传送的字节数分别送入DMA控制器中的内存地址寄存器和传送字节计数器。<br>⑵发出数据传输要求的进行进入等待状态。此时正在执行的CPU指令被暂时挂起。进程调度程序调度其他进程占据CPU。<br>⑶输入设备不断地窃取CPU工作周期，将数据缓冲寄存器中的数据源源不断地写入内存，直到所要求的字节全部传送完毕。<br>⑷DMA控制器在传送完所有字节时，通过中断请求线发出中断信号。CPU在接收到中断信号后，转入中断处理程序进行后续处理。<br>⑸中断处理结束后，CPU返回到被中断的进程中，或切换到新的进程上下文环境中，继续执行。<strong><br></strong>　　<strong>DMA与中断的区别</strong><br>⑴中断方式是在数据缓冲寄存器满之后发出中断，要求CPU进行中断处理，而DMA方式则是在所要求传送的数据块全部传送结束时要求CPU 进行中断处理。这就大大减少了CPU进行中断处理的次数。<br>⑵中断方式的数据传送是在中断处理时由CPU控制完成的，而DMA方式则是在DMA控制器的控制下，不经过CPU控制完成的。这就排除了CPU因并行设备过多而来不及处理以及因速度不匹配而造成数据丢失等现象。<strong><br></strong>　　<strong>DMA方式的优缺点</strong><br>在DMA方式中，由于I/O设备直接同内存发生成块的数据交换，因此I/O效率比较高。由于DMA技术可以提高I/O效率，因此在现代计算机系统中， 得到了广泛的应用。许多输入输出设备的控制器，特别是块设备的控制器，都支持DMA方式。<br>通过上述分析可以看出，DMA控制器功能的强弱，是决定DMA效率的关键因素。DMA控制器需要为每次数据传送做大量的工作，数据传送单位的增大意味着传送次数的减少。另外，DMA方式窃取了始终周期，CPU处理效率降低了，要想尽量少地窃取始终周期，就要设法提高DMA控制器的性能，这样可以较少地影响CPU出理效率。</font> </p>
<font size=3><strong>四、通道方式</strong><br>输入/输出通道是一个独立于CPU的，专门管理I/O的处理机，它控制设备与内存直接进行数据交换。它有自己的通道指令，这些通道指令由CPU启动，并在操作结束时向CPU发出中断信号，见图6-3。<br>输入/输出通道控制是一种以内存为中心，实现设备和内参内直接交换数据的控制方式。在通道方式中，数据的传送方向、存放数据的内存起始地址以及传送的数据块长度等都由通道来进行控制。<br>另外，通道控制方式可以做到一个通道控制多台设备与内存进行数据交换。因而，通道方式进一步减轻了CPU的工作负担，增加了计算机系统的并行工作程度。<strong><br></strong>　　<strong>输入/输出通道分类</strong><br>按照信息交换方式和所连接的设备种类不同，通道可以分为以下三种类型：<br>⑴字节多路通道<br>它适用于连接打印机、终端等低速或中速的I/O设备。这种通道以字节为单位交叉工作：当为一台设备传送一个字节后，立即转去为另一它设备传送一个字节。<br>⑵选择通道<br>它适用于连接磁盘、磁带等高速设备。这种通道以&#8220;组方式&#8221;工作，每次传送一批数据，传送速率很高，但在一段时间只能为一台设备服务。每当一个I/O请求处理完之后，就选择另一台设备并为其服务。<br>⑶成组多路通道<br>这种通道综合了字节多路通道分时工作和选择通道传输速率高的特点，其实质是：对通道程序采用多道程序设计技术，使得与通道连接的设备可以并行工作。<strong><br></strong>　　<strong>通道工作原理</strong><br>在通道控制方式中，I/O设备控制器（常简称为I/O控制器）中没有传送字节计数器和内存地址寄存器，但多了通道设备控制器和指令执行部件。CPU只需发出启动指令，指出通道相应的操作和I/O设备，该指令就可启动通道并使该通道从内存中调出相应的通道指令执行。<br>一旦CPU发出启动通道的指令，通道就开始工作。I/O通道控制I/O控制器工作，I/O控制器又控制I/O设备。这样，一个通道可以连接多个I/O控制器，而一个I/O控制器又可以连接若干台同类型的外部设备。<strong><br></strong>　　<strong>通道的连接</strong><br>由于通道和控制器的数量一般比设备数量要少，因此，如果连接不当，往往会导致出现&#8220;瓶颈&#8221;。故一般设备的连接采用交叉连接，这样做的好处是：<br>①&nbsp;&nbsp;提高系统的可靠性：当某条通路因控制器或通道故障而断开时，可使用其他通路。<br>②&nbsp;&nbsp; 提高设备的并行性：对于同一个设备，当与它相连的某一条通路中的控制器或通道被占用时，可以选择另一条空闲通路，减少了设备因等待通路所需要花费的时间。<strong><br></strong>　　<strong>通道处理机</strong><br>通道相当于一个功能单纯的处理机，它具有自己的指令系统，包括读、写、控制、转移、结束以及空操作等指令，并可以执行由这些指令编写的通道程序。<br>通道的运算控制部件包括：<br>① 通道地址字（CAW）：记录下一条通道指令存放的地址，其功能类似于中央处理机的指令寄存器。<br>② 通道命令字（CCW）：记录正在执行的通道指令，其作用相当于中央处理机的指令寄存器。<br>③&nbsp;&nbsp;通道状态字（CSW）：记录通道、控制器、设备的状态，包括I/O传输完成信息、出错信息、重复执行次数等。<strong><br></strong>　　<strong>通道对主机的访问</strong><br>通道一般需要与主机共享同一个内存，以保存通道程序和交换数据。通道访问内存采用&#8220;周期窃用&#8221;方式。<br>采用通道方式后，输入/输出的执行过程如下：<br>CPU在执行用户程序时遇到I/O请求，根据用户的I/O请求生成通道程序（也可以是事先编好的）。放到内存中，并把该通道程序首地址放入CAW中。<br>然后，CPU执行&#8220;启动I/O&#8221;指令，启动通道工作。通道接收&#8220;启动I/O&#8221;指令信号，从CAW中取出通道程序首地址，并根据此地址取出通道程序的第一条指令，放入CCW中；同时向CU发回答信号，通知&#8220;启动I/O&#8221;指令完成完毕，CPU可继续执行。<br>通道开始执行通道程序，进行物理I/O操作。当执行完一条指令后，如果还有下一条指令则继续执行；否则表示传输完成，同时自行停止，通知CPU转去处理通道结束事件，并从CCW中得到有关通道状态。<br>总之，在通道中，I/O运用专用的辅助处理器处理I/O操作，从而剪径了主处理器处理I/O的负担。主处理器只要发出一个I/O操作命令，剩下的工作完全由通道负责。I/O操作结束后，I/O通道会发出一个中断请求，表示相应操作已完成。<strong><br></strong>　　<strong>通道的发展</strong><br>通道的思想是从早期的大型计算机系统中发展起来的。在早期的大型计算机系统中，一般配有大量的I/O设备。为了把对I/O设备的管理从计算机主机中分离出来，形成了I/O通道的概念，并专门设计出I/O通道处理机。<br>I/O通道在计算机系统中是一个非常重要的部件，它对系统整体性能的提高起了相当重要的作用。不过，随着技术不断的发展，处理机和I/O设备性能的不断提高，专用的、独立I/O通道处理机已不容易见到。但是通道的思想又融入了许多新的技术，所以仍在广泛地应用着。由于光纤通道技术具有数据传输速率高、数据传输距离远以及可简化大型存储系统设计的优点，新的通用光纤通道技术正在快速发展。这种通用光纤通道可以在一个通道上容纳多达127个的大容量硬盘驱动器。显然，在大容量高速存储应用领域，通用光纤通道有着广泛的应用前景。<br><br>转自：<br><a href="http://blog.chinaunix.net/u2/67780/showart_2063742.html">http://blog.chinaunix.net/u2/67780/showart_2063742.html</a></font>
<img src ="http://www.cppblog.com/beautykingdom/aggbug/100672.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2009-11-10 23:34 <a href="http://www.cppblog.com/beautykingdom/archive/2009/11/10/100672.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>callback function from wikipedia</title><link>http://www.cppblog.com/beautykingdom/archive/2009/05/12/82747.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Tue, 12 May 2009 15:28:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2009/05/12/82747.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/82747.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2009/05/12/82747.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/82747.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/82747.html</trackback:ping><description><![CDATA[<h1 class=firstHeading id=firstHeading>Callback (computer science)</h1>
<div id=bodyContent>
<h3 id=siteSub>From Wikipedia, the free encyclopedia</h3>
<div id=contentSub></div>
<div id=jump-to-nav>Jump to: <a href="http://en.wikipedia.org/wiki/Callback_%28computer_science%29#column-one"><u><font color=#0000ff>navigation</font></u></a>, <a href="http://en.wikipedia.org/wiki/Callback_%28computer_science%29#searchInput"><u><font color=#0000ff>search</font></u></a></div>
<!-- start content -->
<div class=dablink>For a discussion of callback with computer <a title=Modem href="http://en.wikipedia.org/wiki/Modem"><u><font color=#0000ff>modems</font></u></a>, see <a title="Callback (telecommunications)" href="http://en.wikipedia.org/wiki/Callback_%28telecommunications%29"><u><font color=#0000ff>callback (telecommunications)</font></u></a>.</div>
<p>In <a title="Computer programming" href="http://en.wikipedia.org/wiki/Computer_programming"><u><font color=#0000ff>computer programming</font></u></a>, a <strong>callback</strong> is <a class=mw-redirect title="Executable code" href="http://en.wikipedia.org/wiki/Executable_code"><u><font color=#0000ff>executable code</font></u></a> that is passed as an <a class=mw-redirect title="Argument (computer science)" href="http://en.wikipedia.org/wiki/Argument_%28computer_science%29"><u><font color=#0000ff>argument</font></u></a> to other code. It allows a lower-level <a title="Abstraction layer" href="http://en.wikipedia.org/wiki/Abstraction_layer"><u><font color=#0000ff>software layer</font></u></a> to call a <a title=Subroutine href="http://en.wikipedia.org/wiki/Subroutine"><u><font color=#0000ff>subroutine</font></u></a> (or function) defined in a higher-level layer.</p>
<div class="thumb tright">
<div class=thumbinner style="WIDTH: 372px"><a class=image title="A callback is often back on the level of the original caller." href="http://en.wikipedia.org/wiki/File:Callback-notitle.svg"><img class=thumbimage height=138 alt="" src="http://upload.wikimedia.org/wikipedia/commons/thumb/d/d4/Callback-notitle.svg/370px-Callback-notitle.svg.png" width=370 border=0></a>
<div class=thumbcaption>
<div class=magnify><a class=internal title=Enlarge href="http://en.wikipedia.org/wiki/File:Callback-notitle.svg"><img height=11 alt="" src="http://en.wikipedia.org/skins-1.5/common/images/magnify-clip.png" width=15></a></div>
A callback is often back on the level of the original caller.</div>
</div>
</div>
<p>However, while technically accurate, this might not be the most illustrative explanation. Think of it as an "In case of fire, break glass" subroutine. Many computer programs tend to be written such that they expect a certain set of possibilities at any given moment. If "Thing That Was Expected", then "Do something", otherwise, "Do something else." is a common theme. However, there are many situations in which events (such as fire) could happen at any time. Rather than checking for them at each possible step ("Thing that was expected OR Things are on fire"), it is easier to have a system which detects a number of events, and will call the appropriate function upon said event (this also keeps us from having to write programs like "Thing that was expected OR Things are on fire OR Nuclear meltdown OR alien invasion OR the dead rising from the grave OR...etc., etc.) Instead, a callback routine is a sort of insurance policy. If zombies attack, call this function. If the user moves their mouse over an icon, call HighlightIcon, and so forth.</p>
<p>Usually, there is a <a title="Software framework" href="http://en.wikipedia.org/wiki/Software_framework"><u><font color=#0000ff>framework</font></u></a> in which a series of events (some condition is met) in which the running framework (be it a generic <a title="Library (computing)" href="http://en.wikipedia.org/wiki/Library_%28computing%29"><u><font color=#0000ff>library</font></u></a> or unique to the program) will call a registered chunk of code based on some pre-registered function (typically, a handle or a function pointer) The events may be anything from user <a title=Input/output href="http://en.wikipedia.org/wiki/Input/output"><u><font color=#0000ff>input</font></u></a> (such as <a title="Mouse (computing)" href="http://en.wikipedia.org/wiki/Mouse_%28computing%29"><u><font color=#0000ff>mouse</font></u></a> or <a title="Keyboard (computing)" href="http://en.wikipedia.org/wiki/Keyboard_%28computing%29"><u><font color=#0000ff>keyboard</font></u></a> input), <a title="Computer network" href="http://en.wikipedia.org/wiki/Computer_network"><u><font color=#0000ff>network</font></u></a> activity (callbacks are frequently used as message handlers for new network sessions) or an internal <a title="Operating system" href="http://en.wikipedia.org/wiki/Operating_system"><u><font color=#0000ff>operating system</font></u></a> event (such as a POSIX-style signal) The concept is to develop a piece of code that can be registered within some framework (be it a <a title="Graphical user interface" href="http://en.wikipedia.org/wiki/Graphical_user_interface"><u><font color=#0000ff>GUI</font></u></a> toolkit, network library, etc.) that will serve as the handler upon the condition stated at registration. How the flow of control is passed between the underlying framework and the registered callback function is specific to the framework itself.</p>
<div class="thumb tright">
<div class=thumbinner style="WIDTH: 252px"><a class=image title="In another common scenario, the callback is first registered and later called asynchronously." href="http://en.wikipedia.org/wiki/File:Callback-async-notitle.svg"><img class=thumbimage height=278 alt="" src="http://upload.wikimedia.org/wikipedia/commons/thumb/2/25/Callback-async-notitle.svg/250px-Callback-async-notitle.svg.png" width=250 border=0></a>
<div class=thumbcaption>
<div class=magnify><a class=internal title=Enlarge href="http://en.wikipedia.org/wiki/File:Callback-async-notitle.svg"><img height=11 alt="" src="http://en.wikipedia.org/skins-1.5/common/images/magnify-clip.png" width=15></a></div>
In another common scenario, the callback is first registered and later called asynchronously.</div>
</div>
</div>
<table class=toc id=toc summary=Contents>
    <tbody>
        <tr>
            <td>
            <div id=toctitle>
            <h2>Contents</h2>
            <span class=toctoggle>[<a class=internal id=togglelink href="javascript:toggleToc()"><u><font color=#0000ff>hide</font></u></a>]</span></div>
            <ul>
                <li class=toclevel-1><a href="http://en.wikipedia.org/wiki/Callback_%28computer_science%29#Motivation"><font color=#0000ff><u><span class=tocnumber>1</span> <span class=toctext>Motivation</span></u></font></a></li>
                <li class=toclevel-1><a href="http://en.wikipedia.org/wiki/Callback_%28computer_science%29#Example"><font color=#0000ff><u><span class=tocnumber>2</span> <span class=toctext>Example</span></u></font></a></li>
                <li class=toclevel-1><a href="http://en.wikipedia.org/wiki/Callback_%28computer_science%29#Implementation"><font color=#0000ff><u><span class=tocnumber>3</span> <span class=toctext>Implementation</span></u></font></a></li>
                <li class=toclevel-1><a href="http://en.wikipedia.org/wiki/Callback_%28computer_science%29#Special_cases"><font color=#0000ff><u><span class=tocnumber>4</span> <span class=toctext>Special cases</span></u></font></a></li>
                <li class=toclevel-1><a href="http://en.wikipedia.org/wiki/Callback_%28computer_science%29#See_also"><font color=#0000ff><u><span class=tocnumber>5</span> <span class=toctext>See also</span></u></font></a></li>
                <li class=toclevel-1><a href="http://en.wikipedia.org/wiki/Callback_%28computer_science%29#External_links"><font color=#0000ff><u><span class=tocnumber>6</span> <span class=toctext>External links</span></u></font></a></li>
                <li class=toclevel-1><a href="http://en.wikipedia.org/wiki/Callback_%28computer_science%29#References"><u><font color=#0000ff><span class=tocnumber>7</span> <span class=toctext>References</span></font></u></a></li>
            </ul>
            </td>
        </tr>
    </tbody>
</table>
<script type=text/javascript>
//<![cdata[
if (window.showTocToggle) { var tocShowText = "show"; var tocHideText = "hide"; showTocToggle(); }
//]]&gt;
</script>
<p><a id=Motivation name=Motivation><u><font color=#0000ff></font></u></a></p>
<h2><span class=editsection>[<a title="Edit section: Motivation" href="http://en.wikipedia.org/w/index.php?title=Callback_%28computer_science%29&amp;action=edit&amp;section=1"><u><font color=#0000ff>edit</font></u></a>]</span> <span class=mw-headline>Motivation</span></h2>
<p>To understand the motivation for using callbacks, consider the problem of a network server. At any given point in time, it may have an internal state machine that is currently at a point in which it is dealing with one very specific communication session, not necessarily expecting new participants. As a host, it could be dealing with all the name exchange and handshakes and pleasantries, but no real way of dealing with the next dinner party guest that walks through the door. One way to deal with this is for this server to live by a state machine in which it rejects new connections until the current one is dealt with...not very robust (What if the other end goes away unexpectedly?) and not very scalable (Would you really want to make other clients wait (or more likely, keep retrying to connect) until it's their turn?) Instead, it's easier to have some sort of management process that spins off a new thread (or process) to deal with the new connection. Rather than writing programs that keep dealing with all of the possible resource contention problems that could come of this, or all of the details involved in socket code (your desired platform may be more straight-forward than others, but one of your design goals may be cross-platform compatibility), many have opted to use more generic frameworks that will handle such details in exchange for providing a reference such that the underlying framework can call it if the registered event occurs.</p>
<p><a id=Example name=Example></a></p>
<h2><span class=editsection>[<a title="Edit section: Example" href="http://en.wikipedia.org/w/index.php?title=Callback_%28computer_science%29&amp;action=edit&amp;section=2"><u><font color=#0000ff>edit</font></u></a>]</span> <span class=mw-headline>Example</span></h2>
<p>The following code in <a title="C (programming language)" href="http://en.wikipedia.org/wiki/C_%28programming_language%29"><u><font color=#0000ff>C</font></u></a> demonstrates the use of callbacks for the specific case of dealing with a POSIX-style signal (in this case SIGUSR1).</p>
<div dir=ltr style="TEXT-ALIGN: left">
<pre class=source-c><span class=co2>#include &lt;stdio.h&gt;</span>
<span class=co2>#include &lt;signal.h&gt;</span>
<span class=kw4>void</span> * sig<span class=br0>(</span><span class=kw4>int</span> signum<span class=br0>)</span>
<span class=br0>{</span>
<span class=kw3>printf</span><span class=br0>(</span><span class=st0>"Received signal number %d!<span class=es0>\n</span>"</span>, signum<span class=br0>)</span>;
<span class=br0>}</span>
<span class=kw4>int</span> main<span class=br0>(</span><span class=kw4>int</span> argc, <span class=kw4>char</span> *argv<span class=br0>[</span><span class=br0>]</span><span class=br0>)</span>
<span class=br0>{</span>
signal<span class=br0>(</span>SIGUSR1,&amp;sig<span class=br0>)</span>;
<span class=kw1>while</span><span class=br0>(</span><span class=nu0>1</span><span class=br0>)</span><span class=br0>{</span><span class=br0>}</span>;
<span class=kw1>return</span> <span class=nu0>0</span>;
<span class=br0>}</span>
</pre>
</div>
<p>The while loop will keep this example from doing anything interesting, but it will give you plenty of time to send a signal to this process. (If you're on a unix-like system, try a "kill -USR1 &lt;pid&gt;" to the process ID associated with this sample program. No matter how or when you send it, the callback should respond.)</p>
<p><a id=Implementation name=Implementation></a></p>
<h2><span class=editsection>[<a title="Edit section: Implementation" href="http://en.wikipedia.org/w/index.php?title=Callback_%28computer_science%29&amp;action=edit&amp;section=3"><u><font color=#0000ff>edit</font></u></a>]</span> <span class=mw-headline>Implementation</span></h2>
<p>The form of a callback varies among <a title="Programming language" href="http://en.wikipedia.org/wiki/Programming_language"><u><font color=#0000ff>programming languages</font></u></a>.</p>
<ul>
    <li><a title="C (programming language)" href="http://en.wikipedia.org/wiki/C_%28programming_language%29"><u><font color=#0000ff>C</font></u></a> and <a title=C++ href="http://en.wikipedia.org/wiki/C%2B%2B"><u><font color=#0000ff>C++</font></u></a> allow <a title="Function pointer" href="http://en.wikipedia.org/wiki/Function_pointer"><u><font color=#0000ff>function pointers</font></u></a> as arguments to other functions.</li>
    <li>Several programming languages (though especially <a title="Functional programming" href="http://en.wikipedia.org/wiki/Functional_programming"><u><font color=#0000ff>functional programming</font></u></a> languages such as <a title="Scheme (programming language)" href="http://en.wikipedia.org/wiki/Scheme_%28programming_language%29"><u><font color=#0000ff>Scheme</font></u></a> or <a title="ML (programming language)" href="http://en.wikipedia.org/wiki/ML_%28programming_language%29"><u><font color=#0000ff>ML</font></u></a>) allow <a title="Closure (computer science)" href="http://en.wikipedia.org/wiki/Closure_%28computer_science%29"><u><font color=#0000ff>closures</font></u></a>, a generalization of function pointers, as arguments to other functions.</li>
    <li>Several programming languages, especially <a title="Interpreted language" href="http://en.wikipedia.org/wiki/Interpreted_language"><u><font color=#0000ff>interpreted languages</font></u></a>, allow one to pass the <em>name</em> of a function A as a parameter to a function B and have B call A by means of <a title=Eval href="http://en.wikipedia.org/wiki/Eval"><u><font color=#0000ff>eval</font></u></a>.</li>
    <li>In <a title="Object-oriented programming" href="http://en.wikipedia.org/wiki/Object-oriented_programming"><u><font color=#0000ff>object-oriented programming</font></u></a> languages, a call can accept an object that implements some abstract interface, without specifying in detail how the object should do so. The programmer who implements that object may use the interface's methods exclusively for application-specific code. Such objects are effectively a bundle of callbacks, plus the data they need to manipulate. They are useful in implementing various <a class=mw-redirect title="Design patterns (computer science)" href="http://en.wikipedia.org/wiki/Design_patterns_%28computer_science%29"><u><font color=#0000ff>design patterns</font></u></a> like <a title="Visitor pattern" href="http://en.wikipedia.org/wiki/Visitor_pattern"><u><font color=#0000ff>Visitor</font></u></a>, <a title="Observer pattern" href="http://en.wikipedia.org/wiki/Observer_pattern"><u><font color=#0000ff>Observer</font></u></a>, and <a title="Strategy pattern" href="http://en.wikipedia.org/wiki/Strategy_pattern"><u><font color=#0000ff>Strategy</font></u></a>.</li>
    <li>C++ allows objects to provide their own implementation of the function call operation. The <a title="Standard Template Library" href="http://en.wikipedia.org/wiki/Standard_Template_Library"><u><font color=#0000ff>Standard Template Library</font></u></a> accepts these objects (called <em><a title="Function object" href="http://en.wikipedia.org/wiki/Function_object"><u><font color=#0000ff>functors</font></u></a></em>), as well as function pointers, as parameters to various polymorphic algorithms</li>
    <li>C# .NET Framework provides a <a title="Type safety" href="http://en.wikipedia.org/wiki/Type_safety"><u><font color=#0000ff>type-safe</font></u></a> encapsulating reference, a '<a title="Delegate (.NET)" href="http://en.wikipedia.org/wiki/Delegate_%28.NET%29"><u><font color=#0000ff>delegate</font></u></a>', to manage <a title="Function pointer" href="http://en.wikipedia.org/wiki/Function_pointer"><u><font color=#0000ff>function pointers</font></u></a>. These can be used for callback operations.</li>
    <li><a title=Perl href="http://en.wikipedia.org/wiki/Perl"><u><font color=#0000ff>Perl</font></u></a> supports subroutine references.<sup class=reference id=cite_ref-0><a title="" href="http://en.wikipedia.org/wiki/Callback_%28computer_science%29#cite_note-0"><u><font color=#0000ff><span>[</span>1<span>]</span></font></u></a></sup><sup class=reference id=cite_ref-1><a title="" href="http://en.wikipedia.org/wiki/Callback_%28computer_science%29#cite_note-1"><u><font color=#0000ff><span>[</span>2<span>]</span></font></u></a></sup></li>
    <li>Some systems have built-in programming languages to support extension and adaptation. These languages provide callbacks without the need for separate software development tools.</li>
</ul>
<p><a id=Special_cases name=Special_cases></a></p>
<h2><span class=editsection>[<a title="Edit section: Special cases" href="http://en.wikipedia.org/w/index.php?title=Callback_%28computer_science%29&amp;action=edit&amp;section=4"><u><font color=#0000ff>edit</font></u></a>]</span> <span class=mw-headline>Special cases</span></h2>
<p>Callback functions are also frequently used as a means to handle exceptions arising within the low level function, as a way to enable <a class=mw-redirect title="Side-effect (computer science)" href="http://en.wikipedia.org/wiki/Side-effect_%28computer_science%29"><u><font color=#0000ff>side-effects</font></u></a> in response to some condition, or as a way to gather operational statistics in the course of a larger computation. <a title="Interrupt handler" href="http://en.wikipedia.org/wiki/Interrupt_handler"><u><font color=#0000ff>Interrupt handlers</font></u></a> in an <a title="Operating system" href="http://en.wikipedia.org/wiki/Operating_system"><u><font color=#0000ff>operating system</font></u></a> respond to hardware conditions, <a class=mw-redirect title="Signal handler" href="http://en.wikipedia.org/wiki/Signal_handler"><u><font color=#0000ff>signal handlers</font></u></a> of a process are triggered by the operating system, and <a title="Event handler" href="http://en.wikipedia.org/wiki/Event_handler"><u><font color=#0000ff>event handlers</font></u></a> process the asynchronous input a program receives.</p>
<p>A <strong>pure callback function</strong> is one which is <a title="Purely functional" href="http://en.wikipedia.org/wiki/Purely_functional"><u><font color=#0000ff>purely functional</font></u></a> (always returns the same value given the same inputs) and free of observable side-effects. Some uses of callbacks require pure callback functions to operate correctly.</p>
<p>A special case of a callback is called a <strong>predicate callback</strong>, or just predicate for short. This is a pure callback function which accepts a single input value and returns a <a title=Boolean href="http://en.wikipedia.org/wiki/Boolean"><u><font color=#0000ff>Boolean</font></u></a> value. These types of callbacks are useful for filtering collections of values by some condition.</p>
<p><a id=See_also name=See_also></a></p>
<h2><span class=editsection>[<a title="Edit section: See also" href="http://en.wikipedia.org/w/index.php?title=Callback_%28computer_science%29&amp;action=edit&amp;section=5"><u><font color=#0000ff>edit</font></u></a>]</span> <span class=mw-headline>See also</span></h2>
<ul>
    <li><a title="Signals and slots" href="http://en.wikipedia.org/wiki/Signals_and_slots"><font color=#0000ff><u>Signals and slots</u></font></a></li>
    <li><a title=Libsigc++ href="http://en.wikipedia.org/wiki/Libsigc%2B%2B"><u><font color=#0000ff>libsigc++</font></u></a>, a callback library for C++</li>
    <li><a title="Implicit invocation" href="http://en.wikipedia.org/wiki/Implicit_invocation"><font color=#0000ff><u>Implicit invocation</u></font></a></li>
    <li><a title="User exit" href="http://en.wikipedia.org/wiki/User_exit"><font color=#0000ff><u>User exit</u></font></a></li>
    <li><a title="Inversion of control" href="http://en.wikipedia.org/wiki/Inversion_of_control"><u><font color=#0000ff>Inversion of control</font></u></a></li>
</ul>
<p><a id=External_links name=External_links><u><font color=#0000ff></font></u></a></p>
<h2><span class=editsection>[<a title="Edit section: External links" href="http://en.wikipedia.org/w/index.php?title=Callback_%28computer_science%29&amp;action=edit&amp;section=6"><u><font color=#0000ff>edit</font></u></a>]</span> <span class=mw-headline>External links</span></h2>
<ul>
    <li><a class="external text" title=http://gotw.ca/gotw/083.htm href="http://gotw.ca/gotw/083.htm" rel=nofollow><font color=#0000ff><u>Style Case Study #2: Generic Callbacks</u></font></a></li>
    <li><a class="external text" title=http://partow.net/programming/templatecallback/index.html href="http://partow.net/programming/templatecallback/index.html" rel=nofollow><font color=#0000ff><u>C++ Callback Solution</u></font></a></li>
    <li><a class="external text" title=http://msdn.microsoft.com/msdnmag/issues/02/12/basicinstincts href="http://msdn.microsoft.com/msdnmag/issues/02/12/basicinstincts" rel=nofollow><font color=#0000ff><u>Basic Instincts: Implementing Callback Notifications Using Delegates</u></font></a></li>
    <li><a class="external text" title=http://www.codeproject.com/aspnet/ScriptCallbackFramework.asp href="http://www.codeproject.com/aspnet/ScriptCallbackFramework.asp" rel=nofollow><font color=#0000ff><u>Implement Script Callback Framework in ASP.NET</u></font></a></li>
    <li><a class="external text" title=http://www.javaworld.com/javaworld/javatips/jw-javatip10.html href="http://www.javaworld.com/javaworld/javatips/jw-javatip10.html" rel=nofollow><u><font color=#0000ff>Implement callback routines in Java</font></u></a></li>
</ul>
<p><a id=References name=References><u><font color=#0000ff></font></u></a></p>
<h2><span class=editsection>[<a title="Edit section: References" href="http://en.wikipedia.org/w/index.php?title=Callback_%28computer_science%29&amp;action=edit&amp;section=7"><u><font color=#0000ff>edit</font></u></a>]</span> <span class=mw-headline>References</span></h2>
<div class="references-small references-column-count references-column-count-2" style="-moz-column-count: 2">
<ol class=references>
    <li id=cite_note-0><strong><a title="" href="http://en.wikipedia.org/wiki/Callback_%28computer_science%29#cite_ref-0"><u><font color=#0000ff>^</font></u></a></strong> <cite class=web style="FONT-STYLE: normal"><a class="external text" title=http://www.unix.org.ua/orelly/perl/cookbook/ch11_05.htm href="http://www.unix.org.ua/orelly/perl/cookbook/ch11_05.htm" rel=nofollow><u><font color=#0000ff>"Perl Cookbook - 11.4. Taking References to Functions"</font></u></a><span class=printonly>. <a class="external free" title=http://www.unix.org.ua/orelly/perl/cookbook/ch11_05.htm href="http://www.unix.org.ua/orelly/perl/cookbook/ch11_05.htm" rel=nofollow><u><font color=#0000ff>http://www.unix.org.ua/orelly/perl/cookbook/ch11_05.htm</font></u></a></span><span class=reference-accessdate>. Retrieved on 2008-03-03</span>.</cite><span class=Z3988 title=ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&amp;rft.genre=bookitem&amp;rft.btitle=Perl+Cookbook+-+11.4.+Taking+References+to+Functions&amp;rft.atitle=&amp;rft_id=http%3A%2F%2Fwww.unix.org.ua%2Forelly%2Fperl%2Fcookbook%2Fch11_05.htm&amp;rfr_id=info:sid/en.wikipedia.org:Callback_(computer_science)><span style="DISPLAY: none">&nbsp;</span></span></li>
    <li id=cite_note-1><strong><a title="" href="http://en.wikipedia.org/wiki/Callback_%28computer_science%29#cite_ref-1"><u><font color=#0000ff>^</font></u></a></strong> <cite class=web style="FONT-STYLE: normal"><a class="external text" title=http://www.unix.org.ua/orelly/perl/advprog/ch04_02.htm href="http://www.unix.org.ua/orelly/perl/advprog/ch04_02.htm" rel=nofollow><u><font color=#0000ff>"Advanced Perl Programming - 4.2 Using Subroutine References"</font></u></a><span class=printonly>. <a class="external free" title=http://www.unix.org.ua/orelly/perl/advprog/ch04_02.htm href="http://www.unix.org.ua/orelly/perl/advprog/ch04_02.htm" rel=nofollow><u><font color=#0000ff>http://www.unix.org.ua/orelly/perl/advprog/ch04_02.htm</font></u></a></span><span class=reference-accessdate>. Retrieved on 2008-03-03</span>.</cite><span class=Z3988 title=ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&amp;rft.genre=bookitem&amp;rft.btitle=Advanced+Perl+Programming+-+4.2+Using+Subroutine+References&amp;rft.atitle=&amp;rft_id=http%3A%2F%2Fwww.unix.org.ua%2Forelly%2Fperl%2Fadvprog%2Fch04_02.htm&amp;rfr_id=info:sid/en.wikipedia.org:Callback_(computer_science)><span style="DISPLAY: none">&nbsp;</span></span></li>
</ol>
</div>
<!--
NewPP limit report
Preprocessor node count: 784/1000000
Post-expand include size: 6586/2048000 bytes
Template argument size: 2419/2048000 bytes
Expensive parser function count: 0/500
--><!-- Saved in parser cache with key enwiki:pcache:idhash:645246-0!1!0!default!!en!2 and timestamp 20090509205449 -->
<div class=printfooter>Retrieved from "<a href="http://en.wikipedia.org/wiki/Callback_%28computer_science%29"><u><font color=#0000ff>http://en.wikipedia.org/wiki/Callback_(computer_science)</font></u></a>"</div>
<div class=catlinks id=catlinks>
<div id=mw-normal-catlinks><a title=Special:Categories href="http://en.wikipedia.org/wiki/Special:Categories"><u><font color=#0000ff>Categories</font></u></a>: <span dir=ltr><a title="Category:Articles with example C code" href="http://en.wikipedia.org/wiki/Category:Articles_with_example_C_code"><u><font color=#0000ff>Articles with example C code</font></u></a></span> | <span dir=ltr><a title="Category:Control flow" href="http://en.wikipedia.org/wiki/Category:Control_flow"><u><font color=#0000ff>Control flow</font></u></a></span></div>
</div>
</div>
<img src ="http://www.cppblog.com/beautykingdom/aggbug/82747.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2009-05-12 23:28 <a href="http://www.cppblog.com/beautykingdom/archive/2009/05/12/82747.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Critical Section&lt;from wikipedia&gt;</title><link>http://www.cppblog.com/beautykingdom/archive/2009/05/11/82547.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Mon, 11 May 2009 03:48:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2009/05/11/82547.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/82547.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2009/05/11/82547.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/82547.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/82547.html</trackback:ping><description><![CDATA[<h1 id="firstHeading" class="firstHeading">Critical section</h1>
<h3 id="siteSub">From Wikipedia, the free encyclopedia</h3>
<div id="jump-to-nav">Jump to: <a  href="http://en.wikipedia.org/wiki/Critical_section#column-one">navigation</a>, <a  href="http://en.wikipedia.org/wiki/Critical_section#searchInput">search</a></div>
<!-- start content -->
<p>In <a  href="http://en.wikipedia.org/wiki/Concurrent_programming" title="Concurrent programming" class="mw-redirect">concurrent programming</a> a <strong>critical section</strong> is a piece of <a  href="http://en.wikipedia.org/wiki/Code" title="Code">code</a>
that accesses a shared resource (data structure or device) that must
not be concurrently accessed by more than one thread of execution. A
critical section will usually terminate in fixed time, and a thread,
task or process will only have to wait a fixed time to enter it (i.e.
bounded waiting). Some <a  href="http://en.wikipedia.org/wiki/Synchronization_%28computer_science%29" title="Synchronization (computer science)">synchronization</a> mechanism is required at the entry and exit of the critical section to ensure exclusive use, for example a <a  href="http://en.wikipedia.org/wiki/Semaphore_%28programming%29" title="Semaphore (programming)">semaphore</a>.</p>
<p>By carefully controlling which variables are modified inside and
outside the critical section (usually, by accessing important state
only from within), concurrent access to that state is prevented. A
critical section is typically used when a <a  href="http://en.wikipedia.org/wiki/Multithreaded" title="Multithreaded" class="mw-redirect">multithreaded</a>
program must update multiple related variables without a separate
thread making conflicting changes to that data. In a related situation,
a critical section may be used to ensure a shared resource, for example
a printer, can only be accessed by one process at a time.</p>
<p>How critical sections are implemented varies among operating systems.</p>
<p>The simplest method is to prevent any change of processor control
inside the critical section. On uni-processor systems, this can be done
by disabling interrupts on entry into the critical section, avoiding
system calls that can cause a <a  href="http://en.wikipedia.org/wiki/Context_switch" title="Context switch">context switch</a>
while inside the section and restoring interrupts to their previous
state on exit. Any thread of execution entering any critical section
anywhere in the system will, with this implementation, prevent any
other thread, including an interrupt, from getting the CPU and
therefore from entering any other critical section or, indeed, any code
whatsoever, until the original thread leaves its critical section.</p>
<p>This brute-force approach can be improved upon by using <a  href="http://en.wikipedia.org/wiki/Semaphore_%28programming%29" title="Semaphore (programming)">semaphores</a>. To enter a critical section, a thread must obtain a <a  href="http://en.wikipedia.org/wiki/Semaphore_%28programming%29" title="Semaphore (programming)">semaphore</a>,
which it releases on leaving the section. Other threads are prevented
from entering the critical section at the same time as the original
thread, but are free to gain control of the CPU and execute other code,
including other critical sections that are protected by different <a  href="http://en.wikipedia.org/wiki/Semaphore_%28programming%29" title="Semaphore (programming)">semaphores</a>.</p>
<p>Some confusion exists in the literature about the relationship between different critical sections in the same program.<sup class="noprint template-fact" title="This claim needs references to reliable sources&nbsp;since november 2008" style="white-space: nowrap;">[<em><a  href="http://en.wikipedia.org/wiki/Wikipedia:Citation_needed" title="Wikipedia:Citation needed">citation needed</a></em>]</sup>
In general, a resource that must be protected from concurrent access
may be accessed by several pieces of code. Each piece must be guarded
by a common <a  href="http://en.wikipedia.org/wiki/Semaphore_%28programming%29" title="Semaphore (programming)">semaphore</a>. Is each piece now a critical section or are all the pieces guarded by the same <a  href="http://en.wikipedia.org/wiki/Semaphore_%28programming%29" title="Semaphore (programming)">semaphore</a> in aggregate a single critical section? This confusion is evident in definitions of a critical section such as "... a piece of <a  href="http://en.wikipedia.org/wiki/Code" title="Code">code</a> that can only be <a  href="http://en.wikipedia.org/wiki/Execution_%28computers%29" title="Execution (computers)" class="mw-redirect">executed</a> by one <a  href="http://en.wikipedia.org/wiki/Computer_process" title="Computer process" class="mw-redirect">process</a> or <a  href="http://en.wikipedia.org/wiki/Thread_%28computer_science%29" title="Thread (computer science)">thread</a>
at a time". This only works if all access to a protected resource is
contained in one "piece of code", which requires either the definition
of a piece of code or the code itself to be somewhat contrived.</p>
<table id="toc" class="toc" summary="Contents">
    <tbody>
        <tr>
            <td>
            <div id="toctitle">
            <h2>Contents</h2>
            <span class="toctoggle">[<a  href="javascript:toggleToc()" class="internal" id="togglelink">hide</a>]</span></div>
            <ul>
                <li class="toclevel-1"><a  href="http://en.wikipedia.org/wiki/Critical_section#Application_Level_Critical_Sections"><span class="tocnumber">1</span> <span class="toctext">Application Level Critical Sections</span></a></li>
                <li class="toclevel-1"><a  href="http://en.wikipedia.org/wiki/Critical_section#Kernel_Level_Critical_Sections"><span class="tocnumber">2</span> <span class="toctext">Kernel Level Critical Sections</span></a></li>
                <li class="toclevel-1"><a  href="http://en.wikipedia.org/wiki/Critical_section#See_also"><span class="tocnumber">3</span> <span class="toctext">See also</span></a></li>
                <li class="toclevel-1"><a  href="http://en.wikipedia.org/wiki/Critical_section#External_links"><span class="tocnumber">4</span> <span class="toctext">External links</span></a></li>
            </ul>
            </td>
        </tr>
    </tbody>
</table>
<script type="text/javascript">
//<![cdata[
if (window.showtoctoggle) { var tocshowtext =" "show";" var tochidetext =" "hide";" showTocToggle(); }
//]]&gt;
</script>
<p><a name="Application_Level_Critical_Sections" id="Application_Level_Critical_Sections"></a></p>
<h2><span class="editsection">[<a  href="http://en.wikipedia.org/w/index.php?title=Critical_section&amp;action=edit&amp;section=1" title="Edit section: Application Level Critical Sections">edit</a>]</span> <span class="mw-headline">Application Level Critical Sections</span></h2>
<p><a  href="http://en.wikipedia.org/wiki/Application_software" title="Application software">Application</a>-level critical sections reside in the <a  href="http://en.wikipedia.org/wiki/Random_access_memory" title="Random access memory" class="mw-redirect">memory</a> range of the process and are usually modifiable by the process itself. This is called a <a  href="http://en.wikipedia.org/wiki/User_space" title="User space">user-space</a> object because the program run by the user (as opposed to the <a  href="http://en.wikipedia.org/wiki/Kernel_%28computer_science%29" title="Kernel (computer science)" class="mw-redirect">kernel</a>) can modify and interact with the object. However the functions called may jump to <a  href="http://en.wikipedia.org/wiki/Kernel_space" title="Kernel space" class="mw-redirect">kernel-space</a> code to register the user-space object with the kernel.</p>
<p><strong>Example Code For Critical Sections with POSIX pthread library</strong></p>
<div dir="ltr" style="text-align: left;">
<pre class="source-c"><span class="coMULTI">/* Sample C/C++, Unix/Linux */</span><br><span class="co2">#include &lt;pthread.h&gt;</span><br> <br><span class="coMULTI">/* This is the critical section object (statically allocated). */</span><br><span class="kw4">static</span> pthread_mutex_t cs_mutex = PTHREAD_MUTEX_INITIALIZER;<br> <br><span class="kw4">void</span> f<span class="br0">(</span><span class="br0">)</span><br><span class="br0">{</span><br>    <span class="coMULTI">/* Enter the critical section -- other threads are locked out */</span><br>    pthread_mutex_lock<span class="br0">(</span> &amp;cs_mutex <span class="br0">)</span>;<br> <br>    <span class="coMULTI">/* Do some thread-safe processing! */</span><br> <br>    <span class="coMULTI">/*Leave the critical section -- other threads can now pthread_mutex_lock()  */</span><br>    pthread_mutex_unlock<span class="br0">(</span> &amp;cs_mutex <span class="br0">)</span>;<br><span class="br0">}</span><br></pre>
</div>
<p><strong>Example Code For Critical Sections with Win32 API</strong></p>
<div dir="ltr" style="text-align: left;">
<pre class="source-c"><span class="coMULTI">/* Sample C/C++, Windows, link to kernel32.dll */</span><br><span class="co2">#include &lt;windows.h&gt;</span><br> <br><span class="kw4">static</span> CRITICAL_SECTION cs; <span class="coMULTI">/* This is the critical section object -- once initialized,<br>                               it cannot be moved in memory */</span><br>                            <span class="coMULTI">/* If you program in OOP, declare this in your class */</span><br> <br><span class="coMULTI">/* Initialize the critical section before entering multi-threaded context. */</span><br>InitializeCriticalSection<span class="br0">(</span>&amp;cs<span class="br0">)</span>;<br> <br><span class="kw4">void</span> f<span class="br0">(</span><span class="br0">)</span><br><span class="br0">{</span><br>    <span class="coMULTI">/* Enter the critical section -- other threads are locked out */</span><br>    EnterCriticalSection<span class="br0">(</span>&amp;cs<span class="br0">)</span>;<br> <br>    <span class="coMULTI">/* Do some thread-safe processing! */</span><br> <br>    <span class="coMULTI">/* Leave the critical section -- other threads can now EnterCriticalSection() */</span><br>    LeaveCriticalSection<span class="br0">(</span>&amp;cs<span class="br0">)</span>;<br><span class="br0">}</span><br> <br><span class="coMULTI">/* Release system object when all finished -- usually at the end of the cleanup code */</span><br>DeleteCriticalSection<span class="br0">(</span>&amp;cs<span class="br0">)</span>;<br></pre>
</div>
<p>Note that on <a  href="http://en.wikipedia.org/wiki/Windows_NT" title="Windows NT">Windows NT</a> (not 9x/ME), the function <strong>TryEnterCriticalSection()</strong>
can be used to attempt to enter the critical section. This function
returns immediately so that the thread can do other things if it fails
to enter the critical section (usually due to another thread having
locked it). With the pthreads library, the equivalent function is <strong>pthread_mutex_trylock()</strong>. Note that the use of a CriticalSection is not the same as a Win32 <a  href="http://en.wikipedia.org/wiki/Mutual_exclusion" title="Mutual exclusion">Mutex</a>, which is an <a  href="http://en.wikipedia.org/wiki/Object_%28computer_science%29" title="Object (computer science)">object</a> used for <em>inter-process</em> synchronization. A Win32 CriticalSection is for <em>intra-process</em> synchronization (and is much faster as far as lock times), however it cannot be shared across processes.</p>
<p><a name="Kernel_Level_Critical_Sections" id="Kernel_Level_Critical_Sections"></a></p>
<h2><span class="editsection">[<a  href="http://en.wikipedia.org/w/index.php?title=Critical_section&amp;action=edit&amp;section=2" title="Edit section: Kernel Level Critical Sections">edit</a>]</span> <span class="mw-headline">Kernel Level Critical Sections</span></h2>
<table class="metadata plainlinks ambox ambox-content">
    <tbody>
        <tr>
            <td class="mbox-image">
            <div style="width: 52px;"><a  href="http://en.wikipedia.org/wiki/File:Question_book-new.svg" class="image" title="Question book-new.svg"><img  src="http://upload.wikimedia.org/wikipedia/en/thumb/9/99/Question_book-new.svg/50px-Question_book-new.svg.png" alt="" width="50" border="0" height="39"></a></div>
            </td>
            <td class="mbox-text">This section <strong>does not <a  href="http://en.wikipedia.org/wiki/Wikipedia:Citing_sources" title="Wikipedia:Citing sources">cite</a> any <a  href="http://en.wikipedia.org/wiki/Wikipedia:Verifiability" title="Wikipedia:Verifiability">references or sources</a></strong>. Please help <a  href="http://en.wikipedia.org/w/index.php?title=Critical_section&amp;action=edit" class="external text" title="http://en.wikipedia.org/w/index.php?title=Critical_section&amp;action=edit" rel="nofollow">improve this article</a> by adding citations to <a  href="http://en.wikipedia.org/wiki/Wikipedia:Reliable_sources" title="Wikipedia:Reliable sources">reliable sources</a>. <a  href="http://en.wikipedia.org/wiki/Wikipedia:Verifiability" title="Wikipedia:Verifiability">Unverifiable</a> material may be challenged and removed. <small><em>(July 2007)</em></small></td>
        </tr>
    </tbody>
</table>
<p>Typically, critical sections prevent process and thread migration between processors and the <a  href="http://en.wikipedia.org/wiki/Preemption_%28computing%29" title="Preemption (computing)">preemption</a> of processes and threads by interrupts and other processes and threads.</p>
<p>Critical sections often allow nesting. Nesting allows multiple critical sections to be entered and exited at little cost.</p>
<p>If the <a  href="http://en.wikipedia.org/wiki/Scheduling_%28computing%29" title="Scheduling (computing)">scheduler</a>
interrupts the current process or thread in a critical section, the
scheduler will either allow the process or thread to run to completion
of the critical section, or it will schedule the process or thread for
another complete quantum. The scheduler will not migrate the process or
thread to another processor, and it will not schedule another process
or thread to run while the current process or thread is in a critical
section.</p>
<p>Similarly, if an <a  href="http://en.wikipedia.org/wiki/Interrupt" title="Interrupt">interrupt</a>
occurs in a critical section, the interrupt's information is recorded
for future processing, and execution is returned to the process or
thread in the critical section. Once the critical section is exited,
and in some cases the scheduled quantum completes, the pending
interrupt will be executed.</p>
<p>Since critical sections may <a  href="http://en.wikipedia.org/wiki/Execution_%28computers%29" title="Execution (computers)" class="mw-redirect">execute</a>
only on the processor on which they are entered, synchronization is
only required within the executing processor. This allows critical
sections to be entered and exited at almost zero cost. No
interprocessor synchronization is required, only instruction stream
synchronization. Most processors provide the required amount of
synchronization by the simple act of interrupting the current execution
state. This allows critical sections in most cases to be nothing more
than a per processor count of critical sections entered.</p>
<p>Performance enhancements include executing pending interrupts at the
exit of all critical sections and allowing the scheduler to run at the
exit of all critical sections. Furthermore, pending interrupts may be
transferred to other processors for execution.</p>
<p>Critical sections should not be used as a long-lived locking
primitive. They should be short enough that the critical section will
be entered, executed, and exited without any interrupts occurring, from
neither <a  href="http://en.wikipedia.org/wiki/Computer_hardware" title="Computer hardware" class="mw-redirect">hardware</a> much less the scheduler.</p>
<p>Kernel Level Critical Sections are the base of the <a  href="http://en.wikipedia.org/wiki/Software_lockout" title="Software lockout">software lockout</a> issue.</p>
<p><a name="See_also" id="See_also"></a></p>
<h2><span class="editsection">[<a  href="http://en.wikipedia.org/w/index.php?title=Critical_section&amp;action=edit&amp;section=3" title="Edit section: See also">edit</a>]</span> <span class="mw-headline">See also</span></h2>
<ul>
    <li><a  href="http://en.wikipedia.org/wiki/Lock_%28computer_science%29" title="Lock (computer science)">Lock (computer science)</a></li>
</ul>
<p><a name="External_links" id="External_links"></a></p>
<h2><span class="editsection">[<a  href="http://en.wikipedia.org/w/index.php?title=Critical_section&amp;action=edit&amp;section=4" title="Edit section: External links">edit</a>]</span> <span class="mw-headline">External links</span></h2>
<p>Critical Section documentation on the <a  href="http://en.wikipedia.org/wiki/MSDN_Library" title="MSDN Library">MSDN Library</a> homepage: <a  href="http://msdn2.microsoft.com/en-us/library/ms682530.aspx" class="external free" title="http://msdn2.microsoft.com/en-us/library/ms682530.aspx" rel="nofollow">http://msdn2.microsoft.com/en-us/library/ms682530.aspx</a></p><img src ="http://www.cppblog.com/beautykingdom/aggbug/82547.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2009-05-11 11:48 <a href="http://www.cppblog.com/beautykingdom/archive/2009/05/11/82547.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>进程和线程编程&lt;转&gt;</title><link>http://www.cppblog.com/beautykingdom/archive/2009/03/26/77949.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Thu, 26 Mar 2009 07:56:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2009/03/26/77949.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/77949.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2009/03/26/77949.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/77949.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/77949.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: http://man.lupaworld.com/content/develop/joyfire/system/11.html#I255&nbsp;&nbsp;                        进程和线程编程            &nbsp;目 录    进程和线程编程            原始管道       ...&nbsp;&nbsp;<a href='http://www.cppblog.com/beautykingdom/archive/2009/03/26/77949.html'>阅读全文</a><img src ="http://www.cppblog.com/beautykingdom/aggbug/77949.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2009-03-26 15:56 <a href="http://www.cppblog.com/beautykingdom/archive/2009/03/26/77949.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OS FAQ</title><link>http://www.cppblog.com/beautykingdom/archive/2009/03/15/76637.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Sun, 15 Mar 2009 05:20:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2009/03/15/76637.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/76637.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2009/03/15/76637.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/76637.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/76637.html</trackback:ping><description><![CDATA[<p>V6:::::::::</p>
<p>1.3 What is the main advantage of multiprogramming?<br>Answer: Multiprogramming makes efficient use of the CPU by overlapping the demands for the CPU and its I/O devices from various users. It attempts to increase CPU utilization by always having something for the CPU to execute.<br><br>1.5 In a multiprogramming and time-sharing environment, several users share the system simultaneously. This situation can result in various security problems.<br>a. What are two such problems?<br>b. Can we ensure the same degree of security in a time-shared machine as we have in a<br>dedicated machine? Explain your answer.<br>Answer:<br>a. Stealing or copying one&#8217;s programs or data; using system resources (CPU, memory, disk space, peripherals) without proper accounting.<br>b. Probably not, since any protection scheme devised by humans can inevitably be broken by a human, and the more complex the scheme, the more difficult it is to feel<br>confident of its correct implementation.<br><br>1.9 Describe the differences between symmetric and asymmetric multiprocessing. What are three advantages and one disadvantage of multiprocessor systems?<br>Answer: Symmetric multiprocessing treats all processors as equals, and I/O can be processed on any CPU. Asymmetric multiprocessing has one master CPU and the remainder CPUs are slaves. The master distributes tasks among the slaves, and I/O is usually done by themaster only. Multiprocessors can savemoney by not duplicating power supplies, housings, and peripherals. They can execute programs more quickly and can have increased reliability. They are also more complex in both hardware and software than uniprocessor systems.<br><br>1.10 What is the main difficulty that a programmer must overcome in writing an operating system for a real-time environment?<br>Answer: The main difficulty is keeping the operating system within the fixed time constraints of a real-time system. If the system does not complete a task in a certain time<br>frame, it may cause a breakdown of the entire system it is running. Therefore when writing an operating system for a real-time system, the writer must be sure that his scheduling schemes don&#8217;t allow response time to exceed the time constraint.<br>&nbsp;<br>2.1 Prefetching is a method of overlapping the I/O of a job with that job&#8217;s own computation.<br>The idea is simple. After a read operation completes and the job is about to start operating on the data, the input device is instructed to begin the next read immediately. The CPU and input device are then both busy. With luck, by the time the job is ready for the next data item, the input device will have finished reading that data item. The CPU can then begin processing the newly read data, while the input device starts to read the following data.<br>A similar idea can be used for output. In this case, the job creates data that are put into a buffer until an output device can accept them. Compare the prefetching scheme with the spooling scheme, where the CPU overlaps the input of one job with the computation and output of other jobs. <br>Answer: Prefetching is a user-based activity, while spooling is a system-based activity.<br>Spooling is a much more effective way of overlapping I/O and CPU operations.<br><br>2.3 What are the differences between a trap and an interrupt? What is the use of each function?<br>&nbsp;&nbsp;&nbsp;An interrupt is a hardware-generated change-of-flow within the system. An interrupt handler is summoned to deal with the cause of the interrupt; control is then re-turned to the interrupted context and instruction.&nbsp;<br>&nbsp;&nbsp;&nbsp;A trap is a software-generated interrupt.<br>&nbsp;&nbsp;&nbsp;An interrupt can be used to signal the completion of an I/O to obviate the need for device polling.&nbsp;<br>&nbsp;&nbsp;&nbsp;A trap can be used to call operating system routines or to catch arithmetic errors.<br><br>V7::::::::</p>
<font style="BACKGROUND-COLOR: #ffffff">19.3 The Linux 2.6 kernel can be built with no virtual memory system. Explain how this feature may appeal to designers of real-time systems.<br>Answer: By disabling the virtual memory system, processes are guaranteed&nbsp;to have portions of its address space resident in physical memory.<br>This results in a system that does not suffer from page faults and therefore does not have to deal with unanticipated costs corresponding to paging the address space.<br>&nbsp;The resulting system is appealing to designers of real-time systems who prefer to avoid variability in performance.<br><br><br><br><br></font>
<img src ="http://www.cppblog.com/beautykingdom/aggbug/76637.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2009-03-15 13:20 <a href="http://www.cppblog.com/beautykingdom/archive/2009/03/15/76637.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>创建线程函数的使用</title><link>http://www.cppblog.com/beautykingdom/archive/2008/09/26/62790.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Fri, 26 Sep 2008 01:07:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2008/09/26/62790.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/62790.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2008/09/26/62790.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/62790.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/62790.html</trackback:ping><description><![CDATA[<p>应用场景：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 做了一个client，去和Message Middleware通信，实时获取消息中间件以topic方式(不是Queue，对Message Middleware来说，Queue是发送一个destination，topic可以发多个)。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 从实时获取的角度来说，需要启一个线程，接收Message Middleware消息，然后做场景需要的处理。创建线程的函数如下所示：<br>&nbsp;// for compilers which have it, we should use C RTL function for thread<br>// creation instead of Win32 API one because otherwise we will have memory<br>// leaks if the thread uses C RTL (and most threads do)<br>#if defined(__VISUALC__) || \<br>&nbsp;&nbsp;&nbsp; (defined(__BORLANDC__) &amp;&amp; (__BORLANDC__ &gt;= 0x500)) || \<br>&nbsp;&nbsp;&nbsp; (defined(__GNUG__) &amp;&amp; defined(__MSVCRT__))<br>&nbsp;&nbsp;&nbsp; typedef unsigned (__stdcall *RtlThreadStart)(void *);</p>
<p>&nbsp;&nbsp;&nbsp; m_hThread = (HANDLE)_beginthreadex(NULL, 0,<br>&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (RtlThreadStart)<br>&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wxThreadInternal::WinThreadStart,<br>&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; thread, CREATE_SUSPENDED,<br>&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (unsigned int *)&amp;m_tid);<br>#else // compiler doesn't have _beginthreadex<br>&nbsp;&nbsp;&nbsp; m_hThread = ::CreateThread<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (<br>&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // default security<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0,&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // default stack size<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (LPTHREAD_START_ROUTINE)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // thread entry point<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wxThreadInternal::WinThreadStart,&nbsp;&nbsp; // the function that runs under thread<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (LPVOID)thread,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // parameter<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CREATE_SUSPENDED,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // flags<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;m_tid&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;&nbsp;&nbsp; // [out] thread id<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; );<br>#endif // _beginthreadex/CreateThread<br>note: there should be a function definition&nbsp;before&nbsp;these lines.eg:<br>&nbsp;DWORD wxThreadInternal::WinThreadStart(wxThread *thread)</p>
<img src ="http://www.cppblog.com/beautykingdom/aggbug/62790.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2008-09-26 09:07 <a href="http://www.cppblog.com/beautykingdom/archive/2008/09/26/62790.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>