﻿<?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++博客-嵌入式-随笔分类-技术交流</title><link>http://www.cppblog.com/cxf20090520biancheng/category/18904.html</link><description>编程与应用</description><language>zh-cn</language><lastBuildDate>Sat, 19 May 2012 11:12:11 GMT</lastBuildDate><pubDate>Sat, 19 May 2012 11:12:11 GMT</pubDate><ttl>60</ttl><item><title>打印函数调用堆栈</title><link>http://www.cppblog.com/cxf20090520biancheng/archive/2012/05/18/175338.html</link><dc:creator>陈显锋</dc:creator><author>陈显锋</author><pubDate>Fri, 18 May 2012 14:39:00 GMT</pubDate><guid>http://www.cppblog.com/cxf20090520biancheng/archive/2012/05/18/175338.html</guid><wfw:comment>http://www.cppblog.com/cxf20090520biancheng/comments/175338.html</wfw:comment><comments>http://www.cppblog.com/cxf20090520biancheng/archive/2012/05/18/175338.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cxf20090520biancheng/comments/commentRss/175338.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cxf20090520biancheng/services/trackbacks/175338.html</trackback:ping><description><![CDATA[<font face="Tahoma">在编写Java程序时，Exception类的printStacktrace()可以打印异常堆栈，这个小工具极大的提高了调试效率；虽然不是一个好习惯，却很实用。习惯了Java编程，很希望 C/C++里也有这样的小工具可以帮助调试程序.</font> 
<div><span style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; border-collapse: separate; font: 14px Tahoma; white-space: normal; orphans: 2; color: #000000; word-spacing: 0px">经过几天查找，发现其实每个系统都提供了打印调用堆栈的函数；这些函数是系统相关，这里仅以Linux下的函数作说明.</span></div>
<div><span style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; border-collapse: separate; font: 14px Tahoma; white-space: normal; orphans: 2; color: #000000; word-spacing: 0px">Linux中共提供了三个函数用于打印调用堆栈：
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080">&nbsp;1</span><img id="Codehighlighter1_0_111_Open_Image" onclick="this.style.display='none'; Codehighlighter1_0_111_Open_Text.style.display='none'; Codehighlighter1_0_111_Closed_Image.style.display='inline'; Codehighlighter1_0_111_Closed_Text.style.display='inline';" align="top" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif"><img style="display: none" id="Codehighlighter1_0_111_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_0_111_Closed_Text.style.display='none'; Codehighlighter1_0_111_Open_Image.style.display='inline'; Codehighlighter1_0_111_Open_Text.style.display='inline';" align="top" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif"><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_0_111_Closed_Text">/**/</span><span id="Codehighlighter1_0_111_Open_Text"><span style="color: #008000">/*</span><span style="color: #008000">&nbsp;<br /></span><span style="color: #008080">&nbsp;2</span><span style="color: #008000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />*&nbsp;函数说明：&nbsp;取得当前函数的调用堆栈&nbsp;<br /></span><span style="color: #008080">&nbsp;3</span><span style="color: #008000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />*&nbsp;参数：&nbsp;<br /></span><span style="color: #008080">&nbsp;4</span><span style="color: #008000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buffer：用于存储函数地址的数组&nbsp;<br /></span><span style="color: #008080">&nbsp;5</span><span style="color: #008000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;size：buffer数组的长度&nbsp;<br /></span><span style="color: #008080">&nbsp;6</span><span style="color: #008000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />*&nbsp;返回值：&nbsp;<br /></span><span style="color: #008080">&nbsp;7</span><span style="color: #008000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;存储到数组中的函数个数&nbsp;<br /></span><span style="color: #008080">&nbsp;8</span><span style="color: #008000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif"  alt="" /></span><span style="color: #008000">*/</span></span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;9</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;backtrace(</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">**</span><span style="color: #000000">buffer,&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;size);&nbsp;<br /></span><span style="color: #008080">10</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;<br /></span><span style="color: #008080">11</span><span style="color: #000000"><img id="Codehighlighter1_157_287_Open_Image" onclick="this.style.display='none'; Codehighlighter1_157_287_Open_Text.style.display='none'; Codehighlighter1_157_287_Closed_Image.style.display='inline'; Codehighlighter1_157_287_Closed_Text.style.display='inline';" align="top" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif"><img style="display: none" id="Codehighlighter1_157_287_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_157_287_Closed_Text.style.display='none'; Codehighlighter1_157_287_Open_Image.style.display='inline'; Codehighlighter1_157_287_Open_Text.style.display='inline';" align="top" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif"></span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_157_287_Closed_Text">/**/</span><span id="Codehighlighter1_157_287_Open_Text"><span style="color: #008000">/*</span><span style="color: #008000">&nbsp;<br /></span><span style="color: #008080">12</span><span style="color: #008000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />*&nbsp;<br /></span><span style="color: #008080">13</span><span style="color: #008000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />*&nbsp;函数说明：将一组函数地址转换为字符串&nbsp;<br /></span><span style="color: #008080">14</span><span style="color: #008000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />*&nbsp;参数:&nbsp;&nbsp;<br /></span><span style="color: #008080">15</span><span style="color: #008000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buffer:&nbsp;经由backtrace得到的函数地址&nbsp;<br /></span><span style="color: #008080">16</span><span style="color: #008000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;size:&nbsp;buffer数组的长度&nbsp;<br /></span><span style="color: #008080">17</span><span style="color: #008000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />*&nbsp;返回值:&nbsp;&nbsp;<br /></span><span style="color: #008080">18</span><span style="color: #008000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;函数在系统中对应用字符串&nbsp;<br /></span><span style="color: #008080">19</span><span style="color: #008000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif"  alt="" /></span><span style="color: #008000">*/</span></span><span style="color: #000000"><br /></span><span style="color: #008080">20</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #0000ff">char</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">**</span><span style="color: #000000">backtrace_symbols(</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">*</span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">buffer,&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;size);&nbsp;<br /></span><span style="color: #008080">21</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;<br /></span><span style="color: #008080">22</span><span style="color: #000000"><img id="Codehighlighter1_350_468_Open_Image" onclick="this.style.display='none'; Codehighlighter1_350_468_Open_Text.style.display='none'; Codehighlighter1_350_468_Closed_Image.style.display='inline'; Codehighlighter1_350_468_Closed_Text.style.display='inline';" align="top" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif"><img style="display: none" id="Codehighlighter1_350_468_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_350_468_Closed_Text.style.display='none'; Codehighlighter1_350_468_Open_Image.style.display='inline'; Codehighlighter1_350_468_Open_Text.style.display='inline';" align="top" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif"></span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_350_468_Closed_Text">/**/</span><span id="Codehighlighter1_350_468_Open_Text"><span style="color: #008000">/*</span><span style="color: #008000">&nbsp;<br /></span><span style="color: #008080">23</span><span style="color: #008000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />*&nbsp;函数说明：将一组函数地址转换为字符串&nbsp;<br /></span><span style="color: #008080">24</span><span style="color: #008000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />*&nbsp;参数:&nbsp;&nbsp;<br /></span><span style="color: #008080">25</span><span style="color: #008000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buffer:&nbsp;经由backtrace得到的函数地址&nbsp;<br /></span><span style="color: #008080">26</span><span style="color: #008000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;size:&nbsp;buffer数组的长度&nbsp;<br /></span><span style="color: #008080">27</span><span style="color: #008000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd:&nbsp;输出结果文件描述符&nbsp;<br /></span><span style="color: #008080">28</span><span style="color: #008000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif"  alt="" /></span><span style="color: #008000">*/</span></span><span style="color: #000000"><br /></span><span style="color: #008080">29</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;backtrace_symbols_fd(</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">*</span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">buffer,&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;size,&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;fd);&nbsp;<br /></span><span style="color: #008080">30</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /><br /></span><span style="color: #008080">31</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /><br /></span><span style="color: #008080">32</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" />&nbsp;示例程序：<br /></span><span style="color: #008080">33</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /><br /></span><span style="color: #008080">34</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">?</span><span style="color: #000000">1</span><span style="color: #000000"><br /></span><span style="color: #008080">35</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">2</span><span style="color: #000000"><br /></span><span style="color: #008080">36</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">3</span><span style="color: #000000"><br /></span><span style="color: #008080">37</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">4</span><span style="color: #000000"><br /></span><span style="color: #008080">38</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">5</span><span style="color: #000000"><br /></span><span style="color: #008080">39</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">6</span><span style="color: #000000"><br /></span><span style="color: #008080">40</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">7</span><span style="color: #000000"><br /></span><span style="color: #008080">41</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">8</span><span style="color: #000000"><br /></span><span style="color: #008080">42</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">9</span><span style="color: #000000"><br /></span><span style="color: #008080">43</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">10</span><span style="color: #000000"><br /></span><span style="color: #008080">44</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">11</span><span style="color: #000000"><br /></span><span style="color: #008080">45</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">12</span><span style="color: #000000"><br /></span><span style="color: #008080">46</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">13</span><span style="color: #000000"><br /></span><span style="color: #008080">47</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">14</span><span style="color: #000000"><br /></span><span style="color: #008080">48</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">15</span><span style="color: #000000"><br /></span><span style="color: #008080">49</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">16</span><span style="color: #000000"><br /></span><span style="color: #008080">50</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">17</span><span style="color: #000000"><br /></span><span style="color: #008080">51</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">18</span><span style="color: #000000"><br /></span><span style="color: #008080">52</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">19</span><span style="color: #000000"><br /></span><span style="color: #008080">53</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">20</span><span style="color: #000000"><br /></span><span style="color: #008080">54</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">21</span><span style="color: #000000"><br /></span><span style="color: #008080">55</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">22</span><span style="color: #000000"><br /></span><span style="color: #008080">56</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">23</span><span style="color: #000000"><br /></span><span style="color: #008080">57</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">24</span><span style="color: #000000"><br /></span><span style="color: #008080">58</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">25</span><span style="color: #000000"><br /></span><span style="color: #008080">59</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">26</span><span style="color: #000000"><br /></span><span style="color: #008080">60</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">27</span><span style="color: #000000"><br /></span><span style="color: #008080">61</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">28</span><span style="color: #000000">&nbsp;#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">execinfo.h</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;<br /></span><span style="color: #008080">62</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" />#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">stdio.h</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;<br /></span><span style="color: #008080">63</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" />#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">stdlib.h</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;<br /></span><span style="color: #008080">64</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" />#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">unistd.h</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;<br /></span><span style="color: #008080">65</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;<br /></span><span style="color: #008080">66</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;myfunc3(</span><span style="color: #0000ff">void</span><span style="color: #000000">)&nbsp;<br /></span><span style="color: #008080">67</span><span style="color: #000000"><img id="Codehighlighter1_731_981_Open_Image" onclick="this.style.display='none'; Codehighlighter1_731_981_Open_Text.style.display='none'; Codehighlighter1_731_981_Closed_Image.style.display='inline'; Codehighlighter1_731_981_Closed_Text.style.display='inline';" align="top" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif"><img style="display: none" id="Codehighlighter1_731_981_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_731_981_Closed_Text.style.display='none'; Codehighlighter1_731_981_Open_Image.style.display='inline'; Codehighlighter1_731_981_Open_Text.style.display='inline';" align="top" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif"></span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_731_981_Closed_Text"><img src="http://www.cppblog.com/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_731_981_Open_Text"><span style="color: #000000">{&nbsp;<br /></span><span style="color: #008080">68</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;j,&nbsp;nptrs;&nbsp;<br /></span><span style="color: #008080">69</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">#define</span><span style="color: #000000">&nbsp;SIZE&nbsp;100&nbsp;</span><span style="color: #000000"><br /></span><span style="color: #008080">70</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">buffer[</span><span style="color: #000000">100</span><span style="color: #000000">];&nbsp;<br /></span><span style="color: #008080">71</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">char</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">**</span><span style="color: #000000">strings;&nbsp;<br /></span><span style="color: #008080">72</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />&nbsp;&nbsp;<br /></span><span style="color: #008080">73</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;nptrs&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;backtrace(buffer,&nbsp;SIZE);&nbsp;<br /></span><span style="color: #008080">74</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="color: #000000">"</span><span style="color: #000000">backtrace()&nbsp;returned&nbsp;%d&nbsp;addresses\n</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;nptrs);&nbsp;<br /></span><span style="color: #008080">75</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />&nbsp;&nbsp;<br /></span><span style="color: #008080">76</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;backtrace_symbols_fd(buffer,&nbsp;nptrs,&nbsp;STDOUT_FILENO);&nbsp;<br /></span><span style="color: #008080">77</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif"  alt="" />}</span></span><span style="color: #000000">&nbsp;<br /></span><span style="color: #008080">78</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;<br /></span><span style="color: #008080">79</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;myfunc(</span><span style="color: #0000ff">void</span><span style="color: #000000">)&nbsp;<br /></span><span style="color: #008080">80</span><span style="color: #000000"><img id="Codehighlighter1_1006_1025_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1006_1025_Open_Text.style.display='none'; Codehighlighter1_1006_1025_Closed_Image.style.display='inline'; Codehighlighter1_1006_1025_Closed_Text.style.display='inline';" align="top" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif"><img style="display: none" id="Codehighlighter1_1006_1025_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_1006_1025_Closed_Text.style.display='none'; Codehighlighter1_1006_1025_Open_Image.style.display='inline'; Codehighlighter1_1006_1025_Open_Text.style.display='inline';" align="top" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif"></span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_1006_1025_Closed_Text"><img src="http://www.cppblog.com/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_1006_1025_Open_Text"><span style="color: #000000">{&nbsp;<br /></span><span style="color: #008080">81</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;myfunc3();&nbsp;<br /></span><span style="color: #008080">82</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif"  alt="" />}</span></span><span style="color: #000000">&nbsp;<br /></span><span style="color: #008080">83</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;<br /></span><span style="color: #008080">84</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;main(</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;argc,&nbsp;</span><span style="color: #0000ff">char</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">argv[])&nbsp;<br /></span><span style="color: #008080">85</span><span style="color: #000000"><img id="Codehighlighter1_1065_1098_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1065_1098_Open_Text.style.display='none'; Codehighlighter1_1065_1098_Closed_Image.style.display='inline'; Codehighlighter1_1065_1098_Closed_Text.style.display='inline';" align="top" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif"><img style="display: none" id="Codehighlighter1_1065_1098_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_1065_1098_Closed_Text.style.display='none'; Codehighlighter1_1065_1098_Open_Image.style.display='inline'; Codehighlighter1_1065_1098_Open_Text.style.display='inline';" align="top" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif"></span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_1065_1098_Closed_Text"><img src="http://www.cppblog.com/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_1065_1098_Open_Text"><span style="color: #000000">{&nbsp;<br /></span><span style="color: #008080">86</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;myfunc();&nbsp;<br /></span><span style="color: #008080">87</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;&nbsp;<br /></span><span style="color: #008080">88</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif"  alt="" />}</span></span><span style="color: #000000">&nbsp;<br /></span><span style="color: #008080">89</span><span style="color: #000000"><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span></div></span></div><span style="font-size: 14px"><strong>程序运行结果：</strong></span> 
<div><span style="font-size: 14px">[dma@bp860-10 ~]$ g++ -rdynamic t.cpp -o t #这里的参数 -rdynamic 是必须</span></div>
<div><span style="font-size: 14px">[dma@bp860-10 ~]$ ./t</span><br /><span style="font-size: 14px">backtrace() returned 5 addresses</span><br /><span style="font-size: 14px">./t(_Z7myfunc3v+0x1c)[0x4008c4]</span><br /><span style="font-size: 14px">./t(_Z6myfuncv+0x9)[0x4008f9]</span><br /><span style="font-size: 14px">./t(main+0x14)[0x400910]</span><br /><span style="font-size: 14px">/lib64/tls/libc.so.6(__libc_start_main+0xdb)[0x3f37c1c40b]</span><br /><span style="font-size: 14px">./t(__gxx_personality_v0+0x3a)[0x40081a]</span><br /><span style="font-size: 14px">[dma@bp860-10 ~]$</span></div>
<div></div>
<div><span style="font-size: 14px">虽然现在的程序可以输出函数调用的堆栈，但是函数多了一些前缀，比如：./t(_Z7myfunc3v+0x1c)；这个问题可以通过c++fileter这个工具来解决：</span></div>
<div><span style="font-size: 14px">[dma@bp860-10 ~]$ ./t | c++filt</span><br /><span style="font-size: 14px">./t(myfunc3()+0x1c)[0x4008c4]</span><br /><span style="font-size: 14px">./t(myfunc()+0x9)[0x4008f9]</span><br /><span style="font-size: 14px">./t(main+0x14)[0x400910]</span><br /><span style="font-size: 14px">/lib64/tls/libc.so.6(__libc_start_main+0xdb)[0x3f37c1c40b]</span><br /><span style="font-size: 14px">./t(__gxx_personality_v0+0x3a)[0x40081a]</span><br /><span style="font-size: 14px">backtrace() returned 5 addresses</span></div><br /><img src ="http://www.cppblog.com/cxf20090520biancheng/aggbug/175338.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cxf20090520biancheng/" target="_blank">陈显锋</a> 2012-05-18 22:39 <a href="http://www.cppblog.com/cxf20090520biancheng/archive/2012/05/18/175338.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>打印函数调用堆栈并具体位置</title><link>http://www.cppblog.com/cxf20090520biancheng/archive/2012/04/23/172464.html</link><dc:creator>陈显锋</dc:creator><author>陈显锋</author><pubDate>Mon, 23 Apr 2012 08:34:00 GMT</pubDate><guid>http://www.cppblog.com/cxf20090520biancheng/archive/2012/04/23/172464.html</guid><wfw:comment>http://www.cppblog.com/cxf20090520biancheng/comments/172464.html</wfw:comment><comments>http://www.cppblog.com/cxf20090520biancheng/archive/2012/04/23/172464.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cxf20090520biancheng/comments/commentRss/172464.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cxf20090520biancheng/services/trackbacks/172464.html</trackback:ping><description><![CDATA[<div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080;">&nbsp;1</span>&nbsp;<span style="color: #000000;">#include&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">stdio.h</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br /></span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;">#include&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">execinfo.h</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br /></span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #000000;"><br /></span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #000000;"></span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;print_trace(</span><span style="color: #0000ff;">void</span><span style="color: #000000;">);<br /></span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #000000;"></span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;funcC()<br /></span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;打印调用堆栈，看看谁调用了本函数&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br /></span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;print_trace();<br /></span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;">}<br /></span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;"></span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;funcB()<br /></span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;">&nbsp;{<br /></span><span style="color: #008080;">11</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;funcC();<br /></span><span style="color: #008080;">12</span>&nbsp;<span style="color: #000000;">&nbsp;}<br /></span><span style="color: #008080;">13</span>&nbsp;<span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;funcA()<br /></span><span style="color: #008080;">14</span>&nbsp;<span style="color: #000000;">&nbsp;{<br /></span><span style="color: #008080;">15</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;funcB();<br /></span><span style="color: #008080;">16</span>&nbsp;<span style="color: #000000;">&nbsp;}<br /></span><span style="color: #008080;">17</span>&nbsp;<span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;main&nbsp;(</span><span style="color: #0000ff;">void</span><span style="color: #000000;">)<br /></span><span style="color: #008080;">18</span>&nbsp;<span style="color: #000000;">&nbsp;{<br /></span><span style="color: #008080;">19</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;funcA();<br /></span><span style="color: #008080;">20</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br /></span><span style="color: #008080;">21</span>&nbsp;<span style="color: #000000;">&nbsp;}<br /></span><span style="color: #008080;">22</span>&nbsp;<span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;print_trace(</span><span style="color: #0000ff;">void</span><span style="color: #000000;">)<br /></span><span style="color: #008080;">23</span>&nbsp;<span style="color: #000000;">&nbsp;{<br /></span><span style="color: #008080;">24</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;i;<br /></span><span style="color: #008080;">25</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;MAX_CALLSTACK_DEPTH&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">32</span><span style="color: #000000;">;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;需要打印堆栈的最大深度&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br /></span><span style="color: #008080;">26</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">traceback[MAX_CALLSTACK_DEPTH];&nbsp;&nbsp;</span><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;用来存储调用堆栈中的地址&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br /></span><span style="color: #008080;">27</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;利用&nbsp;addr2line&nbsp;命令可以打印出一个函数地址所在的源代码位置<br /></span><span style="color: #008080;">28</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;调用格式为：&nbsp;addr2line&nbsp;-f&nbsp;-e&nbsp;/tmp/a.out&nbsp;0x400618<br /></span><span style="color: #008080;">29</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;使用前，源代码编译时要加上&nbsp;-rdynamic&nbsp;-g&nbsp;选项<br /></span><span style="color: #008080;">30</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br /></span><span style="color: #008080;">31</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;cmd[</span><span style="color: #000000;">512</span><span style="color: #000000;">]&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">addr2line&nbsp;-f&nbsp;-e&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br /></span><span style="color: #008080;">32</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">prog&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;cmd&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;strlen(cmd);<br /></span><span style="color: #008080;">33</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;得到当前可执行程序的路径和文件名&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br /></span><span style="color: #008080;">34</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;r&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;readlink(</span><span style="color: #000000;">"</span><span style="color: #000000;">/proc/self/exe</span><span style="color: #000000;">"</span><span style="color: #000000;">,prog,</span><span style="color: #0000ff;">sizeof</span><span style="color: #000000;">(cmd)</span><span style="color: #000000;">-</span><span style="color: #000000;">(prog</span><span style="color: #000000;">-</span><span style="color: #000000;">cmd)</span><span style="color: #000000;">-</span><span style="color: #000000;">1</span><span style="color: #000000;">);<br /></span><span style="color: #008080;">35</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;popen会fork出一个子进程来调用/bin/sh,&nbsp;并执行cmd字符串中的命令，<br /></span><span style="color: #008080;">36</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;同时，会创建一个管道，由于参数是'w',&nbsp;管道将与标准输入相连接，<br /></span><span style="color: #008080;">37</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;并返回一个FILE的指针fp指向所创建的管道，以后只要用fp往管理里写任何内容，<br /></span><span style="color: #008080;">38</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;内容都会被送往到标准输入，<br /></span><span style="color: #008080;">39</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;在下面的代码中，会将调用堆栈中的函数地址写入管道中，<br /></span><span style="color: #008080;">40</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;addr2line程序会从标准输入中得到该函数地址，然后根据地址打印出源代码位置和函数名。<br /></span><span style="color: #008080;">41</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br /></span><span style="color: #008080;">42</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;FILE&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">fp&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;popen(cmd,&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">w</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br /></span><span style="color: #008080;">43</span>&nbsp;<span style="color: #000000;">&nbsp;</span><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;得到当前调用堆栈中的所有函数地址，放到traceback数组中&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br /></span><span style="color: #008080;">44</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;depth&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;backtrace(traceback,&nbsp;MAX_CALLSTACK_DEPTH);<br /></span><span style="color: #008080;">45</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">&nbsp;(i&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;&nbsp;i&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;depth;&nbsp;i</span><span style="color: #000000;">++</span><span style="color: #000000;">)<br /></span><span style="color: #008080;">46</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;{<br /></span><span style="color: #008080;">47</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;得到调用堆栈中的函数的地址，然后将地址发送给&nbsp;addr2line&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br /></span><span style="color: #008080;">48</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf(fp,&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">%p/n</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;traceback[i]);<br /></span><span style="color: #008080;">49</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;addr2line&nbsp;命令在收到地址后，会将函数地址所在的源代码位置打印到标准输出&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br /></span><span style="color: #008080;">50</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080;">51</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;fclose(fp);<br /></span><span style="color: #008080;">52</span>&nbsp;<span style="color: #000000;">}</span></div><img src ="http://www.cppblog.com/cxf20090520biancheng/aggbug/172464.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cxf20090520biancheng/" target="_blank">陈显锋</a> 2012-04-23 16:34 <a href="http://www.cppblog.com/cxf20090520biancheng/archive/2012/04/23/172464.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MTD</title><link>http://www.cppblog.com/cxf20090520biancheng/archive/2012/03/25/168894.html</link><dc:creator>陈显锋</dc:creator><author>陈显锋</author><pubDate>Sun, 25 Mar 2012 07:11:00 GMT</pubDate><guid>http://www.cppblog.com/cxf20090520biancheng/archive/2012/03/25/168894.html</guid><wfw:comment>http://www.cppblog.com/cxf20090520biancheng/comments/168894.html</wfw:comment><comments>http://www.cppblog.com/cxf20090520biancheng/archive/2012/03/25/168894.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cxf20090520biancheng/comments/commentRss/168894.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cxf20090520biancheng/services/trackbacks/168894.html</trackback:ping><description><![CDATA[<div class="card-summary-content">
<p>MTD(memory technology device内存技术设备)是用于访问memory设备（ROM、flash）的Linux的子系统。MTD的主要目的是为了使新的memory设备的驱动更加简单，为此它在硬件和上层之间提供了一个抽象的接口。MTD的所有<a href="http://baike.baidu.com/view/60376.htm" target="_blank">源代码</a>在/drivers/mtd子目录下。CFI接口的MTD设备分为四层（从设备节点直到底层硬件驱动），这四层从上到下依次是：设备节点、MTD设备层、MTD原始设备层和硬件驱动层。</p></div>
<div class="clear"></div>
<div id="lemmaContent-0" class="lemma-main-content">　　<strong>MTD原始设备描述</strong> 
<div class="spctrl"></div>　　所有组成<a href="http://baike.baidu.com/view/1741385.htm" target="_blank">MTD</a>原始设备的<a href="http://baike.baidu.com/view/7641.htm" target="_blank">Flash</a>芯片必须是同类型（无论是interleave还是地址相连），在描述MTD原始设备<a href="http://baike.baidu.com/view/9900.htm" target="_blank">数据结构</a>中采用同一结构描述组成Flash芯片。每个MTD原始设备有一个mtd_info结构，其中的priv指针指向一个map_info结构，map_info结构中的fldrv_priv指向一个cfi_private结构，cfi_private结构的cfiq指针指向一个cfi_ident结构，<a href="http://baike.baidu.com/view/382859.htm" target="_blank">chips</a>指针指向一个flchip结构的<a href="http://baike.baidu.com/view/209670.htm" target="_blank">数组</a>。其中mtd_info、map_info和cfi_private结构用于描述MTD原始设备，因为组成MTD原始设备的<a href="http://baike.baidu.com/view/64532.htm" target="_blank">NOR</a>型Flash相同，cfi_ident结构用于描述Flash芯片信息；而flchip结构用于描述每个Flash芯片专有信息。 
<div class="spctrl"></div>　　根文件系统 
<div class="spctrl"></div>　　文件系统 
<div class="spctrl"></div>　　字符设备节点 
<div class="spctrl"></div>　　MTD字符设备 
<div class="spctrl"></div>　　MTD块设备 
<div class="spctrl"></div>　　MTD原始设备 
<div class="spctrl"></div>　　FLASH硬件驱动 
<div class="spctrl"></div>　　块设备节点 
<div class="spctrl"></div>　　一、Flash硬件驱动层：硬件驱动层负责在init时驱动Flash硬件，Linux MTD设备的NOR　Flash芯片驱动遵循CFI接口标准，其驱动程序位于drivers/mtd/chips子目录下。NAND型Flash的驱动程序则位于/drivers/mtd/nand子目录下 
<div class="spctrl"></div>　　二、MTD原始设备：原始设备层有两部分组成，一部分是MTD原始设备的通用代码，另一部分是各个特定的Flash的数据，例如分区。 
<div class="spctrl"></div>　　用于描述MTD原始设备的数据结构是mtd_info，这其中定义了大量的关于MTD的数据和操作函数。mtd_table（mtdcore.c）则是所有MTD原始设备的列表，mtd_part（mtd_part.c）是用于表示MTD原始设备分区的结构，其中包含了mtd_info，因为每一个分区都是被看成一个MTD原始设备加在mtd_table中的，mtd_part.mtd_info中的大部分数据都从该分区的主分区mtd_part-&gt;master中获得。 
<div class="spctrl"></div>　　在drivers/mtd/maps/子目录下存放的是特定的flash的数据，每一个文件都描述了一块板子上的flash。其中调用add_mtd_device()、del_mtd_device()建立/删除 mtd_info结构并将其加入/删除mtd_table（或者调用add_mtd_partition()、del_mtd_partition() （mtdpart.c）建立/删除mtd_part结构并将mtd_part.mtd_info加入/删除mtd_table 中）。 
<div class="spctrl"></div>　　三、MTD设备层：基于MTD原始设备，<a href="http://baike.baidu.com/view/96045.htm" target="_blank">linux系统</a>可以定义出MTD的块设备（主设备号31）和字符设备（设备号90）。MTD字符设备的定义在mtdchar.c中实现，通过注册一系列file operation函数（lseek、open、close、read、write）。MTD块设备则是定义了一个描述MTD块设备的结构 mtdblk_dev，并声明了一个名为mtdblks的<a href="http://baike.baidu.com/view/2072881.htm" target="_blank">指针数组</a>，这数组中的每一个mtdblk_dev和mtd_table中的每一个 mtd_info一一对应。 
<div class="spctrl"></div>　　四、设备节点：通过mknod在/dev子目录下建立MTD字符设备节点（主设备号为90）和MTD块设备节点（主设备号为31），通过访问此设备节点即可访问MTD字符设备和块设备。 
<div class="spctrl"></div>　　五、根文件系统：在Bootloader中将JFFS（或JFFS2）的文件系统映像jffs.image（或jffs2.img）烧到flash的某一个分区中，在/arch/arm/mach-your/arch.c文件的 your_fixup函数中将该分区作为根文件系统挂载。 
<div class="spctrl"></div>　　六、文件系统：内核启动后，通过mount 命令可以将flash中的其余分区作为文件系统挂载到mountpoint上。 
<div class="spctrl"></div>　　设备层和原始设备层的函数调用关系（红色部分需要我们实现）： 
<div class="spctrl"></div>　　一个MTD原始设备可以通过mtd_part分割成数个MTD原始设备注册进 mtd_table，mtd_table中的每个MTD原始设备都可以被注册成一个MTD设备，其中字符设备的主设备号为90，次设备号为0、2、4、 6&#8230;（奇数次设备号为只读设备），块设备的主设备号为31，次设备号为0、1、2、3&#8230; 
<div class="spctrl"></div>　　mtd_notifier mtd_notifier 
<div class="spctrl"></div>　　字符设备 mtd_fops 块设备 mtd_fops 
<div class="spctrl"></div>　　（mtdchar.c） （mtdblock.c） mtdblks 
<div class="spctrl"></div>　　设备层 
<div class="spctrl"></div>　　register_mtd_user() 
<div class="spctrl"></div>　　get_mtd_device() 
<div class="spctrl"></div>　　unregister_mtd_user() 
<div class="spctrl"></div>　　put_mtd_device() 
<div class="spctrl"></div>　　erase_info 
<div class="spctrl"></div>　　mtd_notifiers 
<div class="spctrl"></div>　　mtd_table 
<div class="spctrl"></div>　　mtd_info 
<div class="spctrl"></div>　　mtd_part 
<div class="spctrl"></div>　　（mtdcore.c） 
<div class="spctrl"></div>　　（mtdpart.c） 
<div class="spctrl"></div>　　Your Flash 
<div class="spctrl"></div>　　（your-flash.c） 
<div class="spctrl"></div>　　add_mtd_partitions() 
<div class="spctrl"></div>　　del_mtd_partitions() 
<div class="spctrl"></div>　　原始设备层 add_mtd_device() 
<div class="spctrl"></div>　　del_mtd_device() 
<div class="spctrl"></div>　　mtd_partition 
<div class="spctrl"></div>　　NOR型Flash芯片驱动与MTD原始设备 
<div class="spctrl"></div>　　所有的NOR型Flash的驱动（探测probe）程序都放在 drivers/mtd/chips下，一个MTD原始设备可以由一块或者数块相同的Flash芯片组成。假设由4块devicetype为x8的 Flash，每块大小为8M，interleave为2，起始地址为0x01000000，地址相连，则构成一个MTD原始设备（0x01000000-0x03000000），其中两块interleave成一个chip，其地址从0x01000000到0x02000000，另两块interleave成一个chip，其地址从0x02000000到0x03000000。 
<div class="spctrl"></div>　　请注意，所有组成一个MTD原始设备的Flash芯片必须是同类型的（无论是interleave还是地址相连），在描述MTD原始设备的数据结构中也只是采用了同一个结构来描述组成它的Flash芯片。 
<div class="spctrl"></div>　　0x03000000 
<div class="spctrl"></div>　　0x02000000 
<div class="spctrl"></div>　　0x01000000 
<div class="spctrl"></div>　　每个MTD原始设备都有一个mtd_info 结构，其中的priv指针指向一个map_info结构，map_info结构中的fldrv_priv指向一个cfi_private结构，cfi_private结构的cfiq指针指向一个cfi_ident结构，chips指针指向一个flchip结构的数组。其中mtd_info、 map_info和cfi_private结构用于描述MTD原始设备；因为组成MTD原始设备的NOR型Flash相同，cfi_ident结构用于描述Flash芯片的信息；而flchip结构用于描述每个Flash芯片的专有信息（比如说起始地址） </div><img src ="http://www.cppblog.com/cxf20090520biancheng/aggbug/168894.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cxf20090520biancheng/" target="_blank">陈显锋</a> 2012-03-25 15:11 <a href="http://www.cppblog.com/cxf20090520biancheng/archive/2012/03/25/168894.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>重叠I/O模型</title><link>http://www.cppblog.com/cxf20090520biancheng/archive/2012/03/25/168661.html</link><dc:creator>陈显锋</dc:creator><author>陈显锋</author><pubDate>Sun, 25 Mar 2012 06:29:00 GMT</pubDate><guid>http://www.cppblog.com/cxf20090520biancheng/archive/2012/03/25/168661.html</guid><description><![CDATA[<p style="text-align: left; line-height: 15pt; text-indent: -20.25pt; margin: 0cm 0cm 0pt 20.25pt;background: white" align="left"><strong><span style="font-family: 宋体; color: purple; font-size: 10pt">一． </span></strong><strong><span style="font-family: 宋体; color: purple; font-size: 10pt">重叠I/O的概念及使用</span></strong></p>
<p style="text-align: left; line-height: 15pt; text-indent: 21pt;background: white" align="left"><span style="font-family: 宋体; font-size: 10pt">当调用</span><span style="font-family: 宋体; font-size: 10pt">ReadFile</span><span style="font-family: 宋体; font-size: 10pt">和</span><span style="font-family: 宋体; font-size: 10pt">WriteFile</span><span style="font-family: 宋体; font-size: 10pt">时，如果最后一个参数</span><span style="font-family: 宋体; font-size: 10pt">lpOverlapped</span><span style="font-family: 宋体; font-size: 10pt">设置为</span><span style="font-size: 10pt">NULL</span><span style="font-family: 宋体; font-size: 10pt">，那么线程就阻塞在这里，直到读写完指定的数据后，它们才返回。这样在读写大文件的时候，<strong>很多时间都浪费在等待</strong></span><strong><span style="font-family: 宋体; font-size: 10pt">ReadFile</span></strong><strong><span style="font-family: 宋体; font-size: 10pt">和</span></strong><strong><span style="font-family: 宋体; font-size: 10pt">WriteFile</span></strong><strong><span style="font-family: 宋体; font-size: 10pt">的返回上面</span></strong><span style="font-family: 宋体; font-size: 10pt">。如果</span><span style="font-family: 宋体; font-size: 10pt">ReadFile</span><span style="font-family: 宋体; font-size: 10pt">和</span><span style="font-family: 宋体; font-size: 10pt">WriteFile</span><span style="font-family: 宋体; font-size: 10pt">是往管道里读写数据，那么有可能阻塞得更久，导致程序性能下降。</span></p>
<p style="text-align: left; line-height: 15pt; text-indent: 21pt;background: white" align="left"><span style="font-family: 宋体; font-size: 10pt">为了解决这个问题，</span><span style="font-size: 10pt">windows</span><span style="font-family: 宋体; font-size: 10pt">引进了</span><span style="font-family: 宋体; font-size: 10pt">重叠I/O</span><span style="font-family: 宋体; font-size: 10pt">的概念，它能够同时以多个线程处理多个</span><span style="font-size: 10pt">I/O</span><span style="font-family: 宋体; font-size: 10pt">。其实你自己开多个线程也可以处理多个</span><span style="font-size: 10pt">I/O</span><span style="font-family: 宋体; font-size: 10pt">，但是系统内部对</span><span style="font-size: 10pt">I/O</span><span style="font-family: 宋体; font-size: 10pt">的处理在性能上有很大的优化。它是</span><span style="font-family: 宋体; font-size: 10pt">Windows</span><span style="font-family: 宋体; font-size: 10pt">下实现异步I/O最常用的方式。因此重叠I/O即是系统会开启另外的线程来完成I/O的处理，而使自己的线程不被阻塞，继续运行。</span></p>
<p style="text-align: left; line-height: 15pt; text-indent: 21pt;background: white" align="left"><span style="font-family: 宋体; font-size: 10pt">Windows</span><span style="font-family: 宋体; font-size: 10pt">为几乎全部类型的文件提供这个工具：磁盘文件、通信端口、命名管道和套接字。通常，使用ReadFile和WriteFile就可以很好地执行重叠I/O。</span></p>
<p style="text-align: left; line-height: 15pt; text-indent: 20pt;background: white" align="left"><span style="font-family: 宋体; font-size: 10pt">重叠模型的核心是一个<strong>重叠数据结构</strong>。若想以重叠方式使用文件，必须用 FILE_FLAG_OVERLAPPED 标志打开它，例如：</span></p>
<p style="text-align: left; line-height: 15pt; text-indent: 20pt;background: white" align="left"><span style="font-family: 宋体; color: blue; font-size: 10pt">HANDLE</span><span style="font-family: 宋体; color: gray; font-size: 10pt"> hFile</span><span style="font-family: 宋体; color: black; font-size: 10pt"> = </span><span style="font-family: 宋体; color: rgb(160,0,160); font-size: 10pt">CreateFile</span><span style="font-family: 宋体; color: black; font-size: 10pt">(lpFileName, </span><span style="font-family: 宋体; color: rgb(160,0,160); font-size: 10pt">GENERIC_READ</span><span style="font-family: 宋体; color: black; font-size: 10pt"> | </span><span style="font-family: 宋体; color: rgb(160,0,160); font-size: 10pt">GENERIC_WRITE</span><span style="font-family: 宋体; color: black; font-size: 10pt">, </span><span style="font-family: 宋体; color: rgb(160,0,160); font-size: 10pt">FILE_SHARE_READ</span><span style="font-family: 宋体; color: black; font-size: 10pt"> | </span><span style="font-family: 宋体; color: rgb(160,0,160); font-size: 10pt">FILE_SHARE_WRITE</span><span style="font-family: 宋体; color: black; font-size: 10pt">, </span><span style="font-family: 宋体; color: rgb(160,0,160); font-size: 10pt">NULL</span><span style="font-family: 宋体; color: black; font-size: 10pt">, </span><span style="font-family: 宋体; color: rgb(160,0,160); font-size: 10pt">OPEN_EXISTING</span><span style="font-family: 宋体; color: black; font-size: 10pt">, </span><em><span style="font-family: 宋体; color: rgb(160,0,160); font-size: 10pt">FILE_FLAG_OVERLAPPED</span></em><span style="font-family: 宋体; color: black; font-size: 10pt">, </span><span style="font-family: 宋体; color: rgb(160,0,160); font-size: 10pt">NULL</span><span style="font-family: 宋体; color: black; font-size: 10pt">); </span></p>
<p style="text-align: left; line-height: 15pt; text-indent: 20pt;background: white" align="left"><span style="font-family: 宋体; font-size: 10pt">如果没有规定该标志，则针对这个文件（句柄）,重叠I/O是不可用的。如果设置了该标志，当调用ReadFile和WriteFile操作这个文件（句柄）时，必须为最后一个参数提供OVERLAPPED结构：</span></p>
<p style="text-align: left; line-height: 15pt; text-indent: 20pt;background: white" align="left"><span style="font-family: 宋体; color: rgb(0,153,0); font-size: 10pt">// WINBASE.H</span></p>
<p style="text-align: left; line-height: 15pt; text-indent: 20pt;background: white" align="left"><span style="font-family: 宋体; color: black; font-size: 10pt">typedef struct </span><span style="font-family: 宋体; color: blue; font-size: 10pt">_OVERLAPPED</span><span style="font-family: 宋体; color: black; font-size: 10pt">{</span></p>
<p style="text-align: left; line-height: 15pt;background: white" align="left"><span style="font-family: 宋体; color: black; font-size: 10pt"></span><span style="font-family: 宋体; color: blue; font-size: 10pt">DWORD</span><span style="font-family: 宋体; color: black; font-size: 10pt"> </span><span style="font-family: 宋体; color: gray; font-size: 10pt">Internal</span><span style="font-family: 宋体; color: black; font-size: 10pt">;</span></p>
<p style="text-align: left; line-height: 15pt;background: white" align="left"><span style="font-family: 宋体; color: black; font-size: 10pt"></span><span style="font-family: 宋体; color: blue; font-size: 10pt">DWORD</span><span style="font-family: 宋体; color: black; font-size: 10pt"> </span><span style="font-family: 宋体; color: gray; font-size: 10pt">InternalHigh</span><span style="font-family: 宋体; color: black; font-size: 10pt">;</span></p>
<p style="text-align: left; line-height: 15pt;background: white" align="left"><span style="font-family: 宋体; color: black; font-size: 10pt"></span><span style="font-family: 宋体; color: blue; font-size: 10pt">DWORD</span><span style="font-family: 宋体; color: black; font-size: 10pt"> </span><span style="font-family: 宋体; color: gray; font-size: 10pt">Offset</span><span style="font-family: 宋体; color: black; font-size: 10pt">;</span></p>
<p style="text-align: left; line-height: 15pt;background: white" align="left"><span style="font-family: 宋体; color: black; font-size: 10pt"></span><span style="font-family: 宋体; color: blue; font-size: 10pt">DWORD</span><span style="font-family: 宋体; color: black; font-size: 10pt"> </span><span style="font-family: 宋体; color: gray; font-size: 10pt">OffsetHigh</span><span style="font-family: 宋体; color: black; font-size: 10pt">;</span></p>
<p style="text-align: left; line-height: 15pt;background: white" align="left"><span style="font-family: 宋体; color: black; font-size: 10pt"></span><span style="font-family: 宋体; color: blue; font-size: 10pt">HANDLE</span><span style="font-family: 宋体; color: black; font-size: 10pt"> </span><span style="font-family: 宋体; color: gray; font-size: 10pt">hEvent</span><span style="font-family: 宋体; color: black; font-size: 10pt">; </span><span style="font-family: 宋体; color: rgb(0,153,0); font-size: 10pt">//</span><span style="font-family: 宋体; color: rgb(0,153,0); font-size: 10pt">关键的一个参数</span></p>
<p style="text-align: left; line-height: 15pt; text-indent: 20pt;background: white" align="left"><span style="font-family: 宋体; color: black; font-size: 10pt">}</span><span style="font-family: 宋体; color: blue; font-size: 10pt">OVERLAPPED</span><span style="font-family: 宋体; color: black; font-size: 10pt">, *</span><span style="font-family: 宋体; color: blue; font-size: 10pt">LPOVERLAPPED</span><span style="font-family: 宋体; color: black; font-size: 10pt">;</span></p>
<p style="text-align: left; line-height: 15pt; text-indent: 20pt;background: white" align="left"><span style="font-family: 宋体; font-size: 10pt">头两个32位的结构字<span style="color: gray">Internal</span>和<span style="color: gray">InternalHigh</span>由系统内部使用；其次两个32位结构字<span style="color: gray">Offset</span>和<span style="color: gray">OffsetHigh</span>使得可以设置 64位的偏移量，该偏移量是要文件中读或写的地方。</span></p>
<p style="text-align: left; line-height: 15pt; text-indent: 20pt;background: white" align="left"><span style="font-family: 宋体; font-size: 10pt">因为I/O异步发生，就不能确定操作是否按顺序完成。因此，这里没有当前位置的概念。对于文件的操作，总是规定该偏移量。</span><span style="font-family: 宋体; color: #800000; font-size: 10pt"><strong>在数据流下（如COM端口或socket），</strong></span><span style="font-family: 宋体; font-size: 10pt">没有寻找精确偏移量的方法，所以在这些情况中，</span><span style="font-family: 宋体; color: #800000; font-size: 10pt"><strong>系统忽略偏移量</strong></span><span style="font-family: 宋体; font-size: 10pt">。</span><span style="font-family: 宋体; color: #800000; font-size: 10pt"><strong>这四个字段不应由应用程序直接进行处理或使用</strong></span><span style="font-family: 宋体; font-size: 10pt">，OVERLAPPED结构的最后一个参数是可选的事件句柄。稍后会提到怎样使用这个参数来设定事件通知完成I/O,现在，假定该句柄是NULL。</span></p>
<p style="text-align: left; line-height: 15pt; text-indent: 20pt;background: white" align="left"><span style="font-family: 宋体; font-size: 10pt">设置了OVERLAPPED参数后，ReadFile/WriteFile的调用会立即返回，这时候你可以去做其他的事（所谓<strong>异步</strong>），系统会自动替你完成ReadFile/WriteFile相关的I/O操作。你也可以同时发出几个ReadFile/WriteFile的调用（所谓<strong>重叠</strong>）。当系统完成I/O操作时，会将OVERLAPPED.hEvent置信，<strong>我们可以通过调用</strong></span><span style="font-family: 宋体; color: #800000; font-size: 10pt"><strong>WaitForSingleObject/WaitForMultipleObjects</strong></span><span style="font-family: 宋体; color: ; font-size: 10pt">由此可以看出，</span><span style="font-family: 宋体; font-size: 10pt">来等待这个I/O完成通知，在得到通知信号后，就可以调用</span><span style="font-family: 宋体; color: #800000; font-size: 10pt"><strong>GetOverlappedResult</strong></span><span style="font-family: 宋体; font-size: 10pt">来查询I/O操作的结果，并进行相关处理。</span><strong><span style="font-family: 宋体; font-size: 10pt">OVERLAPPED</span></strong><strong><span style="font-family: 宋体; font-size: 10pt">结构在一个重叠I/O请求的初始化及其后续的完成之间，提供了一种沟通或通信机制</span></strong><span style="font-family: 宋体; font-size: 10pt">。</span></p>
<p style="text-align: left; line-height: 15pt; text-indent: 19.7pt;background: white" align="left"><span style="font-family: 宋体; font-size: 10pt">以Win32重叠I/O机制为基础，自Winsock 2发布开始，重叠I/O便已集成到新的Winsock函数中，比如WSARecv/WSASend。这样一来，重叠I/O模型便能适用于安装了Winsock 2的所有Windows平台。可以一次投递一个或多个Winsock I/O请求。针对那些提交的请求，在它们完成之后，应用程序可为它们提供服务（对I/O的数据进行处理）。</span></p>
<p style="text-align: left; line-height: 15pt; text-indent: 20pt;background: white" align="left"><span style="font-family: 宋体; font-size: 10pt">相应的，要想在一个套接字上使用重叠I/O模型来处理网络数据通信，首先必须使用 WSA_FLAG_OVERLAPPED这个标志来创建一个套接字。如下所示：</span></p>
<p style="text-align: left; line-height: 15pt; margin: 0cm 0cm 0pt 25.1pt;background: white" align="left"><span style="font-family: 宋体; color: blue; font-size: 10pt">SOCKET</span><span style="font-family: 宋体; color: black; font-size: 10pt"> s = </span><span style="font-family: 宋体; color: rgb(136,0,0); font-size: 10pt">WSASocket</span><span style="font-family: 宋体; color: black; font-size: 10pt">(</span><span style="font-family: 宋体; color: rgb(160,0,160); font-size: 10pt">AF_INET</span><span style="font-family: 宋体; color: black; font-size: 10pt">, </span><span style="font-family: 宋体; color: rgb(160,0,160); font-size: 10pt">SOCK_STEAM</span><span style="font-family: 宋体; color: black; font-size: 10pt">, 0, </span><span style="font-family: 宋体; color: blue; font-size: 10pt">NULL</span><span style="font-family: 宋体; color: black; font-size: 10pt">, 0, </span><em><span style="font-family: 宋体; color: rgb(160,0,160); font-size: 10pt">WSA_FLAG_OVERLAPPED</span></em><span style="font-family: 宋体; color: black; font-size: 10pt">);</span></p>
<p style="text-align: left; line-height: 15pt; text-indent: 20pt;background: white" align="left"><span style="font-family: 宋体; font-size: 10pt">创建套接字的时候，假如使用的是socket函数，而非WSASocket函数，那么会默认设置WSA_FLAG_OVERLAPPED标志。成功创建好了一个套接字，将其与一个本地接口绑定到一起后，便可开始进行这个套接字上的重叠I/O操作，方法是调用下述的Winsock 2函数，同时为它们指定一个WSAOVERLAPPED结构参数（<span style="color: blue">#define WSAOVERLAPPED</span><span style="color: black"> OVERLAPPED</span><span style="color: rgb(0,153,0)">// WINSOCK2.H</span>）：</span></p>
<p style="text-align: left; line-height: 15pt; text-indent: -21pt; margin: 0cm 0cm 0pt 53.25pt;background: white" align="left"><span style="font-family: Wingdings; color: rgb(160,0,160); font-size: 10pt">n</span> <span style="font-family: 宋体; color: rgb(160,0,160); font-size: 10pt">WSASend</span></p>
<p style="text-align: left; line-height: 15pt; text-indent: -21pt; margin: 0cm 0cm 0pt 53.25pt;background: white" align="left"><span style="font-family: Wingdings; color: rgb(160,0,160); font-size: 10pt">n</span> <span style="font-family: 宋体; color: rgb(160,0,160); font-size: 10pt">WSASendTo</span></p>
<p style="text-align: left; line-height: 15pt; text-indent: -21pt; margin: 0cm 0cm 0pt 53.25pt;background: white" align="left"><span style="font-family: Wingdings; color: rgb(160,0,160); font-size: 10pt">n</span> <span style="font-family: 宋体; color: rgb(160,0,160); font-size: 10pt">WSARecv</span></p>
<p style="text-align: left; line-height: 15pt; text-indent: -21pt; margin: 0cm 0cm 0pt 53.25pt;background: white" align="left"><span style="font-family: Wingdings; color: rgb(160,0,160); font-size: 10pt">n</span> <span style="font-family: 宋体; color: rgb(160,0,160); font-size: 10pt">WSARecvFrom</span></p>
<p style="text-align: left; line-height: 15pt; text-indent: -21pt; margin: 0cm 0cm 0pt 53.25pt;background: white" align="left"><span style="font-family: Wingdings; color: rgb(160,0,160); font-size: 10pt">n</span> <span style="font-family: 宋体; color: rgb(160,0,160); font-size: 10pt">WSAIoctl</span></p>
<p style="text-align: left; line-height: 15pt; text-indent: -21pt; margin: 0cm 0cm 0pt 53.25pt;background: white" align="left"><span style="font-family: Wingdings; color: rgb(160,0,160); font-size: 10pt">n</span> <span style="font-family: 宋体; color: rgb(160,0,160); font-size: 10pt">AcceptEx</span></p>
<p style="text-align: left; line-height: 15pt; text-indent: -21pt; margin: 0cm 0cm 0pt 53.25pt;background: white" align="left"><span style="font-family: Wingdings; color: rgb(160,0,160); font-size: 10pt">n</span> <span style="font-family: 宋体; color: rgb(160,0,160); font-size: 10pt">TransmitFile</span></p>
<p style="text-align: left; line-height: 15pt; text-indent: 20.1pt;background: white" align="left"><strong><span style="font-family: 宋体; font-size: 10pt">若随一个WSAOVERLAPPED结构一起调用这些函数，函数会立即返回</span></strong><span style="font-family: 宋体; font-size: 10pt">，无论套接字是否设为锁定模式。它们<strong>依赖于WSAOVERLAPPED结构来返回一个I/O请求操作的结果</strong>。</span></p>
<p style="text-align: left; line-height: 15pt; text-indent: 20pt;background: white" align="left"><span style="font-family: 宋体; font-size: 10pt">比起阻塞、select、WSAAsyncSelect以及WSAEventSelect等模型，Winsock的重叠I/O(Overlapped I/O)模型使应用程序能达到更佳的系统性能。因为它和这4种模型不同的是，使用重叠模型的<strong>应用程序通知缓冲区收发系统直接使用数据</strong>。也就是说，如果应用程序投递了一个10KB大小的缓冲区来接收数据，且数据已经到达套接字，则该数据将直接被拷贝到投递的缓冲区。而这4种模型中，数据到达并拷贝到单套接字接收缓冲区中，此时应用程序会被系统通知可以读入的字节数。当应用程序调用接收函数之后，数据才从单套接字缓冲区拷贝到应用程序的缓冲区。这样就减少了一次从I/O缓冲区到应用程序缓冲区的拷贝，差别就在于此。此处难以理解，可以简单的认为重叠操作使系统来完成数据的接受和发送，使用一个缓冲区。而其它使用两个缓冲区，且必须有应用程序来完成数据的拷贝工作。</span></p>
<p style="text-indent: 20pt;background: white"><span style="font-family: 宋体; font-size: 10pt">在Windows NT和Windows 2000中，重叠I/O模型也允许应用程序<strong>以一种重叠方式实现对套接字连接的处理</strong>。具体的做法是在监听套接字上调用AcceptEx函数。AcceptEx是一个特殊的Winsock 1.1扩展函数，位于Mswsock.h头文件以及Mswsock.lib库文件内。该函数最初的设计宗旨是在Windows NT与Windows 2000操作系统上使用Win 32的重叠I/O机制。但事实上，它也适用于Winsock 2中的重叠I/O。AcceptEx的定义如下：</span></p>
<p style="text-indent: 20pt;background: white"><span style="font-family: 宋体; color: rgb(0,153,0); font-size: 10pt">// MSWSOCK.H</span></p>
<p style="text-align: left; text-indent: 20pt;background: white" align="left"><span style="font-family: 宋体; color: rgb(136,0,0); font-size: 10pt">AcceptEx</span><span style="font-family: 宋体; color: black; font-size: 10pt">(</span></p>
<p style="text-align: left;background: white" align="left"><span style="font-family: 宋体; color: black; font-size: 10pt"></span><span style="font-family: 宋体; color: rgb(160,0,160); font-size: 10pt">IN</span> <span style="font-family: 宋体; color: blue; font-size: 10pt">SOCKET</span> <span style="font-family: 宋体; color: gray; font-size: 10pt">sListenSocket</span><span style="font-family: 宋体; color: black; font-size: 10pt">,</span></p>
<p style="text-align: left;background: white" align="left"><span style="font-family: 宋体; color: black; font-size: 10pt"></span><span style="font-family: 宋体; color: rgb(160,0,160); font-size: 10pt">IN</span> <span style="font-family: 宋体; color: blue; font-size: 10pt">SOCKET</span> <span style="font-family: 宋体; color: gray; font-size: 10pt">sAcceptSocket</span><span style="font-family: 宋体; color: black; font-size: 10pt">,</span></p>
<p style="text-align: left;background: white" align="left"><span style="font-family: 宋体; color: black; font-size: 10pt"></span><span style="font-family: 宋体; co  <img src ="http://www.cppblog.com/cxf20090520biancheng/aggbug/168661.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cxf20090520biancheng/" target="_blank">陈显锋</a> 2012-03-25 14:29 <a href="http://www.cppblog.com/cxf20090520biancheng/archive/2012/03/25/168661.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>