﻿<?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/singohgod/</link><description>每天晚上入睡，都将迎来崭新的明天，这就是梦想！-大宝天天见</description><language>zh-cn</language><lastBuildDate>Sat, 04 Apr 2026 09:10:38 GMT</lastBuildDate><pubDate>Sat, 04 Apr 2026 09:10:38 GMT</pubDate><ttl>60</ttl><item><title>[转载]winnt.h(236) : error C2146: 语法错误 : 缺少“;”(在标识符“PVOID64”的前面)</title><link>http://www.cppblog.com/singohgod/archive/2011/12/07/161660.html</link><dc:creator>大宝天天见</dc:creator><author>大宝天天见</author><pubDate>Wed, 07 Dec 2011 05:03:00 GMT</pubDate><guid>http://www.cppblog.com/singohgod/archive/2011/12/07/161660.html</guid><wfw:comment>http://www.cppblog.com/singohgod/comments/161660.html</wfw:comment><comments>http://www.cppblog.com/singohgod/archive/2011/12/07/161660.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/singohgod/comments/commentRss/161660.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/singohgod/services/trackbacks/161660.html</trackback:ping><description><![CDATA[今天发现解决这个问题的最好办法:<br />结论是由于include路径的顺序引起的.把DX9的路径移到最后,果然就好了 @import url(http://www.cppblog.com/CuteSoft_Client/CuteEditor/Load.ashx?type=style&amp;file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css); <img src ="http://www.cppblog.com/singohgod/aggbug/161660.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/singohgod/" target="_blank">大宝天天见</a> 2011-12-07 13:03 <a href="http://www.cppblog.com/singohgod/archive/2011/12/07/161660.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转载]Linux静态库和动态库</title><link>http://www.cppblog.com/singohgod/archive/2011/10/17/158546.html</link><dc:creator>大宝天天见</dc:creator><author>大宝天天见</author><pubDate>Mon, 17 Oct 2011 07:51:00 GMT</pubDate><guid>http://www.cppblog.com/singohgod/archive/2011/10/17/158546.html</guid><wfw:comment>http://www.cppblog.com/singohgod/comments/158546.html</wfw:comment><comments>http://www.cppblog.com/singohgod/archive/2011/10/17/158546.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/singohgod/comments/commentRss/158546.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/singohgod/services/trackbacks/158546.html</trackback:ping><description><![CDATA[<p>库从本质上来说是一种可执行代码的二进制格式，可以被载入内存中执行。库分静态库和动态库两种。&nbsp;</p>
<h1>静态库和动态库的区别</h1>
<p>1. 静态函数库</p>
<p>&nbsp;&nbsp;&nbsp; 这类库的名字一般是libxxx.a；利用静态函数库编译成的文件比较大，因为整个 函数库的所有数据都会被整合进目标代码中，他的优点就显而易见了，即编译后的执行程序不需要外部的函数库支持，因为所有使用的函数都已经被编译进去了。当然这也会成为他的缺点，因为如果静态函数库改变了，那么你的程序必须重新编译。</p>
<p>2. 动态函数库</p>
<p>&nbsp;&nbsp;&nbsp; 这类库的名字一般是libxxx.so;相对于静态函数库，动态函数库在编译的时候 并没有被编译进目标代码中，你的程序执行到相关函数时才调用该函数库里的相应函数，因此动态函数库所产生的可执行文件比较小。由于函数库没有被整合进你的程序，而是程序运行时动态的申请并调用，所以程序的运行环境中必须提供相应的库。动态函数库的改变并不影响你的程序，所以动态函数库的升级比较方便。&nbsp;<br />
linux系统有几个重要的目录存放相应的函数库，如/lib /usr/lib。</p>
<h1>静态库的使用</h1>
<p>静态库的操作工具：gcc和ar 命令。&nbsp;</p>
<p><strong>编写及使用静态库</strong>&nbsp;</p>
<p><strong>(1)设计库源码 pr1.c 和 pr2.c</strong>&nbsp;</p>
<p>[root@billstone make_lib]# cat pr1.c&nbsp;</p>
<p>void print1()&nbsp;</p>
<p>{&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("This is the first lib src!\n");&nbsp;</p>
<p>}&nbsp;</p>
<p>[root@billstone make_lib]# cat pr2.c&nbsp;</p>
<p>void print2()&nbsp;</p>
<p>{&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("This is the second src lib!\n");&nbsp;</p>
<p>}&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>(2)&nbsp; 编译.c 文件</strong>&nbsp;</p>
<p>[bill@billstone make_lib]$ cc -O -c pr1.c pr2.c&nbsp;</p>
<p>[bill@billstone make_lib]$ ls -l pr*.o&nbsp;</p>
<p>-rw-rw-r--&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1 bill&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bill&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 804&nbsp;&nbsp;&nbsp; 4 月&nbsp; 15 11:11 pr1.o&nbsp;</p>
<p>-rw-rw-r--&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1 bill&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bill&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 804&nbsp;&nbsp;&nbsp; 4 月&nbsp; 15 11:11 pr2.o&nbsp;</p>
<p><strong>(3)&nbsp; 链接静态库</strong>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp; 为了在编译程序中正确找到库文件,静态库必须按照 lib[name].a 的规则命名,如下例中[name]=pr.&nbsp;</p>
<p>[bill@billstone make_lib]$ ar -rsv libpr.a pr1.o pr2.o&nbsp;</p>
<p>a - pr1.o&nbsp;</p>
<p>a - pr2.o&nbsp;</p>
<p>[bill@billstone make_lib]$ ls -l *.a&nbsp;</p>
<p>-rw-rw-r--&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1 bill&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bill&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1822&nbsp;&nbsp;&nbsp; 4 月&nbsp; 15 11:12 libpr.a&nbsp;</p>
<p>[bill@billstone make_lib]$ ar -t libpr.a&nbsp;</p>
<p>pr1.o&nbsp;</p>
<p>pr2.o&nbsp;</p>
<p><strong>(4)&nbsp; 调用库函数代码 main.c</strong>&nbsp;</p>
<p>[bill@billstone make_lib]$ cat main.c&nbsp;</p>
<p>int main()&nbsp;</p>
<p>{&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print1();&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print2();&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;&nbsp;</p>
<p>}&nbsp;</p>
<p><strong>(5)&nbsp; 编译链接选项</strong>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp; -L 及-l 参数放在后面.其中,-L 加载库文件路径,-l 指明库文件名字.&nbsp;</p>
<p>[bill@billstone make_lib]$ gcc -o main main.c -L./ -lpr&nbsp;</p>
<p>[bill@billstone make_lib]$ ls -l main*&nbsp;</p>
<p>-rwxrwxr-x&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1 bill&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bill&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 11805&nbsp;&nbsp;&nbsp; 4 月&nbsp; 15 11:17 main&nbsp;</p>
<p>-rw-rw-r--&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1 bill&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bill&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 50&nbsp;&nbsp;&nbsp; 4 月&nbsp; 15 11:15 main.c&nbsp;</p>
<p><strong>(6)执行目标程序</strong>&nbsp;</p>
<p>[bill@billstone make_lib]$ ./main&nbsp;</p>
<p>This is the first lib src!&nbsp;</p>
<p>This is the second src lib!&nbsp;</p>
<p>[bill@billstone make_lib]$&nbsp;</p>
<h1>动态库的使用</h1>
<p>编写动态库&nbsp;</p>
<p>(1)<strong>设计库代码</strong>&nbsp;</p>
<p>[bill@billstone make_lib]$ cat pr1.c&nbsp;</p>
<p>int p = 2;&nbsp;</p>
<p>void print(){&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("This is the first dll src!\n");&nbsp;</p>
<p>}&nbsp;</p>
<p>[bill@billstone make_lib]$&nbsp;&nbsp;&nbsp;</p>
<p>(2)<strong>生成动态库</strong>&nbsp;</p>
<p>[bill@billstone make_lib]$ gcc -O -fpic -shared -o dl.so pr1.c&nbsp;</p>
<p>[bill@billstone make_lib]$ ls -l *.so&nbsp;</p>
<p>-rwxrwxr-x&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1 bill&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bill&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6592&nbsp;&nbsp;&nbsp; 4 月&nbsp; 15 15:19 dl.so&nbsp;</p>
<p>[bill@billstone make_lib]$&nbsp;</p>
<p><strong>动态库的隐式调用</strong>&nbsp;</p>
<p>&nbsp; 在编译调用库函数代码时指明动态库的位置及名字,&nbsp; 看下面实例&nbsp;</p>
<p>[bill@billstone make_lib]$ cat main.c&nbsp;</p>
<p>int main()&nbsp;</p>
<p>{&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print();&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;&nbsp;</p>
<p>}&nbsp;</p>
<p>[bill@billstone make_lib]$ gcc -o tdl main.c ./dl.so&nbsp;</p>
<p>[bill@billstone make_lib]$ ./tdl&nbsp;</p>
<p>This is the first dll src!&nbsp;</p>
<p>[bill@billstone make_lib]$&nbsp;</p>
<p>当动态库的位置活名字发生改变时,&nbsp; 程序将无法正常运行;&nbsp; 而动态库取代静态库的好处之一则是通过更新动态库而随时升级库的内容.&nbsp;</p>
<p><strong>动态库的显式调用</strong>&nbsp;</p>
<p>&nbsp; 显式调用动态库需要四个函数的支持,&nbsp;&nbsp;<strong>函数 dlopen 打开动态库,&nbsp; 函数 dlsym 获取动态库中对象基址,&nbsp; 函</strong><strong>数 dlerror 获取显式动态库操作中的错误信息,&nbsp; 函数 doclose 关闭动态库.</strong></p>
<p>[bill@billstone make_lib]$ cat main.c&nbsp;</p>
<p>#include &lt;dlfcn.h&gt;&nbsp;</p>
<p>int main()&nbsp;</p>
<p>{&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void *pHandle;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void (*pFunc)();&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp; 指向函数的指针&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int *p;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pHandle = dlopen("./d1.so", RTLD_NOW);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp; 打开动态库&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(!pHandle){&nbsp;</p>
<p>&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; printf("Can't find d1.so \n");&nbsp;</p>
<p>&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; exit(1);&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pFunc = (void (*)())dlsym(pHandle, "print");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp; 获取库函数 print 的地址&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(pFunc)&nbsp;</p>
<p>&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; pFunc();&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else&nbsp;</p>
<p>&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; printf("Can't find function print\n");&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p = (int *)dlsym(pHandle, "p");&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; 获取库变量 p 的地址&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(p)&nbsp;</p>
<p>&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; printf("p = %d\n", *p);&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else&nbsp;</p>
<p>&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; printf("Can't find int p\n");&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dlclose(pHandle);&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;&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;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;&nbsp;</p>
<p>}&nbsp;</p>
<p>[bill@billstone make_lib]$&nbsp;<strong>gcc -o tds main.c &#8211;ld1 &#8211;L.</strong></p>
<p>此时还不能立即./tds，因为在动态函数库使用时，会查找/usr/lib、/lib目录下的动态函数库，而此时我们生成的库不在里边。 这个时候有好几种方法可以让他成功运行： 最直接最简单的方法就是把libstr_out.so拉到/usr/lib或/lib中去。 还有一种方法 export LD_LIBRARY_PATH=$(pwd) 另外还可以在/etc/ld.so.conf文件里加入我们生成的库的目录，然后/sbin/ldconfig。 /etc/ld.so.conf是非常重要的一个目录，里面存放的是链接器和加载器搜索共享库时要检查的目录，默认是从/usr/lib /lib中读取的，所以想要顺利运行，我们也可以把我们库的目录加入到这个文件中并执行/sbin/ldconfig 。另外还有个文件需要了解/etc/ld.so.cache,里面保存了常用的动态函数库，且会先把他们加载到内存中，因为内存的访问速度远远大于硬盘的访问速度，这样可以提高软件加载动态函数库的速度了。</p>
<h1>库依赖的查看</h1>
<p>使用ldd命令来查看执行文件依赖于哪些库。</p>
<p>该命令用于判断某个可执行的 binary 档案含有什么动态函式库。<br />
[root@test root]# ldd [-vdr] [filename]<br />
参数说明：<br />
--version　　打印ldd的版本号<br />
-v --verbose　　打印所有信息，例如包括符号的版本信息<br />
-d --data-relocs　　执行符号重部署，并报告缺少的目标对象（只对ELF格式适用）<br />
-r --function-relocs　　对目标对象和函数执行重新部署，并报告缺少的目标对象和函数（只对ELF格式适用）<br />
--help 用法信息。</p>
<p>如果命令行中给定的库名字包含'/'，这个程序的libc5版本将使用它作为库名字；否则它将在标准位置搜索库。运行一个当前目录下的共享库，加前缀"./"。</p>
@import url(http://www.cppblog.com/CuteSoft_Client/CuteEditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css);<img src ="http://www.cppblog.com/singohgod/aggbug/158546.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/singohgod/" target="_blank">大宝天天见</a> 2011-10-17 15:51 <a href="http://www.cppblog.com/singohgod/archive/2011/10/17/158546.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[摘录]Windows7中关机、睡眠和休眠的区别</title><link>http://www.cppblog.com/singohgod/archive/2011/08/24/154217.html</link><dc:creator>大宝天天见</dc:creator><author>大宝天天见</author><pubDate>Wed, 24 Aug 2011 08:13:00 GMT</pubDate><guid>http://www.cppblog.com/singohgod/archive/2011/08/24/154217.html</guid><wfw:comment>http://www.cppblog.com/singohgod/comments/154217.html</wfw:comment><comments>http://www.cppblog.com/singohgod/archive/2011/08/24/154217.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/singohgod/comments/commentRss/154217.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/singohgod/services/trackbacks/154217.html</trackback:ping><description><![CDATA[@import url(http://www.cppblog.com/CuteSoft_Client/CuteEditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css);
@import url(http://www.cppblog.com/CuteSoft_Client/CuteEditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css);
<span style="line-height: normal; ">
<div><font size="3">
<p>假设经过一段时间的使用，电脑里运行了很多程序，这些程序有些保留在内存中，有些&#8220;暂存&#8221;在硬盘中。如果这时候我们不打算使用电脑，那么&#8220;关机&#8221;、&#8220;休眠&#8221;，和&#8220;睡眠&#8221;的不同点就可以体现出来了。</p>
<ul>
    <li>如果&#8220;关机&#8221;，这时候Windows会保存所有运行中的程序的状态（例如在Word里写了一半的文档），把所有程序都关闭（可以想像成直接把书合上），并保存到硬盘中，然后彻底切断电脑的电源。</li>
    <li>如果&#8220;休眠&#8221;，这时候Windows也会把运行中的所有程序重新保存到硬盘。但和关机的不同在于，关机时候，Windows会把书&#8220;合上&#8221;，然后放回书柜；但休眠时候，Windows不把书合上，直接放回书柜，并把书桌上的所有东西都清空，然后彻底切断电脑的电源。</li>
    <li>如果睡眠，这时候Windows一样会把书放回书柜，但是书依然保持打开状态，到这一步和休眠时完全相同的。但是在睡眠时，书桌上的内容并不会被清空，Windows会切断除了内存之外其他所有设备的供电，但对内存的供电依然持续，因此内存中的数据不会丢失。</li>
</ul>
<p>这 也就是说，如果要让电脑关机，Windows首先要关闭所有运行中的程序，然后关闭系统后台的服务，接着向主板和电源发出特殊的信号，让电源切断对所有设 备的供电，电脑彻底关闭。下次开机后，电脑完成自检工作，然后将Windows系统载入内存，接着继续加载其他后台服务，并显示登录界面。登录后，才可以 运行自己的程序，开始使用电脑。整个过程因为要彻底关闭并重头开始启动系统和程序，因此所需的时间最常。<br />
<br />
对于待机模式，如果要将电脑放入 待机模式，Windows会自动向电源发出另一种特殊信号，随后电源会切断除了内存外其他设备的供电，内存中依然保存了系统运行中的所有数据，这个过程一 两秒钟就可以完成。当从待机状态进入正常状态时，只要通电，然后Windows就会继续从内存中保存的上一次的&#8220;状态数据&#8221;下运行，这个过程也只需要几秒 钟。<br />
<br />
可见，对于待机状态，完全可以不用关闭自己的程序，如果需要，随时可以待机。而要恢复时也只需要按下电源按钮，几秒钟即可恢复。但这 种模式虽然方便，但有一个致命的缺陷：不能停止对内存的供电。因为内存是一种易失性存储设备，必须在保证供电的情况下才能维持其中的数据。因此一旦电脑在 待机状态下断电，哪怕不到一秒钟，内存中的数据将丢失，下次开机的时候，Windows会像从关机状态下启动那样重新开始。<br />
<br />
休眠模式和待 机模式类似，只不过在休眠状态下，Windows会将内存中的数据保存到硬盘上系统盘根目录下的一个文件中（可以将这个文件理解为内存状态的&#8220;镜像&#8221;）。 而下次开机后则从内存上的休眠文件内读取数据，并载入物理内存。休眠模式可以实现和待机模式类似的功能，只不过恢复速度稍慢，而且需要在硬盘上占据一块和 物理内存一样大的空间来保存休眠文件。物理内存越多，占用的空间就越多，而进入状态和从状态恢复所需的时间也就越长（毕竟需要把文件从硬盘读入内存，而硬 盘的速度一直都是最慢的）。但这种模式的优点也有很多，不怕断电！毕竟断电后硬盘上的数据并不会丢失。<br />
<br />
Windows Vista中开始新增了的一种睡眠模式则结合了待机和休眠模式的所有优点。在进入睡眠模式后，Windows会首先将内存中的数据保存到硬盘上（这一点类 似休眠），同时切断除了内存外其他设备的供电（这一点类似待机）。在恢复时，如果没有断过电，那么系统会从内存中直接恢复，只需要几秒钟；而就算断电，因 为硬盘中还保存有内存的状态镜像，因此还可以从硬盘上恢复，虽然速度要稍微慢一些，但至少不用担心数据丢失。</p>
<div>
<div>收起该表格展开该表格</div>
<table cellspacing="1">
    <tbody>
        <tr>
            <th>&nbsp;</th><th><span style="background-color: yellow; ">进入速度</span></th><th><span style="background-color: yellow; ">恢复速度</span></th><th><span style="background-color: yellow; ">是否耗电</span></th><th><span style="background-color: yellow; ">断电后结果</span></th>
        </tr>
        <tr>
            <td><span style="background-color: yellow; ">睡眠</span></td>
            <td><span style="background-color: yellow; ">几秒钟</span></td>
            <td><span style="background-color: yellow; ">不断电的情况下几秒钟</span></td>
            <td><span style="background-color: yellow; ">需要对内存进行少量供电</span></td>
            <td><span style="background-color: yellow; ">断电后，未保存数据不受损，但恢复速度需要略微延长些</span></td>
        </tr>
        <tr>
            <td><span style="background-color: yellow; ">休眠</span></td>
            <td><span style="background-color: yellow; ">两分钟左右</span></td>
            <td><span style="background-color: yellow; ">两分钟左右</span></td>
            <td><span style="background-color: yellow; ">完全不耗电</span></td>
            <td><span style="background-color: yellow; ">未保存数据不会丢失</span></td>
        </tr>
        <tr>
            <td><span style="background-color: yellow; ">待机</span></td>
            <td><span style="background-color: yellow; ">几秒钟</span></td>
            <td><span style="background-color: yellow; ">几秒钟</span></td>
            <td><span style="background-color: yellow; ">需要对内存进行少量供电</span></td>
            <td><span style="background-color: yellow; ">断电后所有未保存数据都会丢失</span></td>
        </tr>
    </tbody>
</table>
</div>
<p><br />
综上所述，这几种模式各有利弊，但只要Windows和所用硬件支持，则<span style="background-color: yellow; ">强烈建议使用睡眠功能代替以往习惯的关机操作</span>。毕竟睡眠功能的优势显而易见，不仅可以避免漫长的启动过程，而且完全可以把电脑当作电视一样的一般电器，随开随关，完全不用担心丢失数据。</p>
</font></div>
</span>
@import url(http://www.cppblog.com/CuteSoft_Client/CuteEditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css);<img src ="http://www.cppblog.com/singohgod/aggbug/154217.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/singohgod/" target="_blank">大宝天天见</a> 2011-08-24 16:13 <a href="http://www.cppblog.com/singohgod/archive/2011/08/24/154217.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转载]Windows完成端口与Linux epoll技术简介</title><link>http://www.cppblog.com/singohgod/archive/2011/08/03/152376.html</link><dc:creator>大宝天天见</dc:creator><author>大宝天天见</author><pubDate>Wed, 03 Aug 2011 09:43:00 GMT</pubDate><guid>http://www.cppblog.com/singohgod/archive/2011/08/03/152376.html</guid><wfw:comment>http://www.cppblog.com/singohgod/comments/152376.html</wfw:comment><comments>http://www.cppblog.com/singohgod/archive/2011/08/03/152376.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/singohgod/comments/commentRss/152376.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/singohgod/services/trackbacks/152376.html</trackback:ping><description><![CDATA[<p><strong>WINDOWS<strong>完成端口</strong>编程<br />
</strong>1、基本概念<br />
2、WINDOWS<strong>完成端口</strong>的特点<br />
3、<strong>完成端口</strong>（Completion Ports ）相关数据结构和创建<br />
4、<strong>完成端口</strong>线程的工作原理<br />
5、Windows<strong>完成端口</strong>的实例代码<br />
<strong>Linux的<strong>EPoll</strong>模型<br />
</strong>1、为什么select落后<br />
2、内核中提高I/O性能的新方法<strong>epoll</strong><br />
3、<strong>epoll</strong>的优点<br />
4、<strong>epoll</strong>的工作模式&nbsp;<br />
5、<strong>epoll</strong>的使用方法<br />
6、Linux下<strong>EPOll</strong>编程实例<br />
<strong>总结</strong></p>
<p><strong>WINDOWS<strong>完成端口</strong>编程<br />
</strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 摘要：开发网络程序从来都不是一件容易的事情，尽管只需要遵守很少的一些规则;创建socket,发起连接，接受连接，发送和接受数据。真正的困难在于：让你的程序可以适应从单单一个连接到几千个连接乃至于上万个连接。利用Windows平台<strong>完成端口</strong>进行重叠I/O的技术和Linux在2.6版本的内核中引入的<strong>EPOll</strong>技术，可以很方便在在在Windows和Linux平台上开发出支持大量连接的网络服务程序。本文介绍在Windows和Linux平台上使用的<strong>完成端口</strong>和<strong>EPoll</strong>模型开发的基本原理，同时给出实际的例子。本文主要关注C/S结构的服务器端程序，因为一般来说，开发一个大容量，具可扩展性的winsock程序一般就是指服务程序。<br />
<strong><br />
1、基本概念<br />
</strong>&nbsp;&nbsp;&nbsp; 设备---windows操作系统上允许通信的任何东西，比如文件、目录、串行口、并行口、邮件槽、命名管道、无名管道、套接字、控制台、逻辑磁盘、物理磁盘等。绝大多数与设备打交道的函数都是CreateFile/ReadFile/WriteFile等。所以我们不能看到**File函数就只想到文件设备。与设备通信有两种方式，同步方式和异步方式。同步方式下，当调用ReadFile函数时，函数会等待系统执行完所要求的工作，然后才返回；异步方式下，ReadFile这类函数会直接返回，系统自己去完成对设备的操作，然后以某种方式通知完成操作。<br />
重叠I/O----顾名思义，当你调用了某个函数（比如ReadFile）就立刻返回做自己的其他动作的时候，同时系统也在对I/0设备进行你要求的操作，在这段时间内你的程序和系统的内部动作是重叠的，因此有更好的性能。所以，重叠I/O是用于异步方式下使用I/O设备的。 重叠I/O需要使用的一个非常重要的数据结构OVERLAPPED。<br />
<strong><br />
2、WINDOWS<strong>完成端口</strong>的特点<br />
</strong>&nbsp;&nbsp; Win32重叠I/O(Overlapped I/O)机制允许发起一个操作，然后在操作完成之后接受到信息。对于那种需要很长时间才能完成的操作来说，重叠IO机制尤其有用，因为发起重叠操作的线程在重叠请求发出后就可以自由的做别的事情了。在WinNT和Win2000上，提供的真正的可扩展的I/O模型就是使用<strong>完成端口</strong>（Completion Port）的重叠I/O.<strong>完成端口</strong>---是一种WINDOWS内核对象。<strong>完成端口</strong>用于异步方式的重叠I/0情况下，当然重叠I/O不一定非使用<strong>完成端口</strong>不可，还有设备内核对象、事件对象、告警I/0等。但是<strong>完成端口</strong>内部提供了线程池的管理，可以避免反复创建线程的开销，同时可以根据CPU的个数灵活的决定线程个数，而且可以让减少线程调度的次数从而提高性能其实类似于WSAAsyncSelect和select函数的机制更容易兼容Unix，但是难以实现我们想要的&#8220;扩展性&#8221;。而且windows的<strong>完成端口</strong>机制在操作系统内部已经作了优化，提供了更高的效率。所以，我们选择<strong>完成端口</strong>开始我们的服务器程序的开发。<br />
1、发起操作不一定完成，系统会在完成的时候通知你，通过用户在<strong>完成端口</strong>上的等待，处理操作的结果。所以要有检查<strong>完成端口</strong>，取操作结果的线程。在<strong>完成端口</strong>上守候的线程系统有优化，除非在执行的线程阻塞，不会有新的线程被激活，以此来减少线程切换造成的性能代价。所以如果程序中没有太多的阻塞操作，没有必要启动太多的线程，CPU数量的两倍，一般这样来启动线程。<br />
2、操作与相关数据的绑定方式：在提交数据的时候用户对数据打相应的标记，记录操作的类型，在用户处理操作结果的时候，通过检查自己打的标记和系统的操作结果进行相应的处理。&nbsp;<br />
3、操作返回的方式:一般操作完成后要通知程序进行后续处理。但写操作可以不通知用户，此时如果用户写操作不能马上完成，写操作的相关数据会被暂存到到非交换缓冲区中，在操作完成的时候，系统会自动释放缓冲区。此时发起完写操作，使用的内存就可以释放了。此时如果占用非交换缓冲太多会使系统停止响应。<br />
<strong><br />
3、<strong>完成端口</strong>（Completion Ports ）相关数据结构和创建<br />
</strong>&nbsp;&nbsp;&nbsp; 其实可以把<strong>完成端口</strong>看成系统维护的一个队列，操作系统把重叠IO操作完成的事件通知放到该队列里，由于是暴露 &#8220;操作完成&#8221;的事件通知，所以命名为&#8220;<strong>完成端口</strong>&#8221;（COmpletion Ports）。一个socket被创建后，可以在任何时刻和一个<strong>完成端口</strong>联系起来。<br />
<strong>完成端口</strong>相关最重要的是OVERLAPPED数据结构<br />
typedef struct _OVERLAPPED {&nbsp;<br />
&nbsp;&nbsp;&nbsp; ULONG_PTR Internal;//被系统内部赋值，用来表示系统状态&nbsp;<br />
&nbsp;&nbsp;&nbsp; ULONG_PTR InternalHigh;// 被系统内部赋值，传输的字节数&nbsp;<br />
&nbsp;&nbsp;&nbsp; union {&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct {&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DWORD Offset;//和OffsetHigh合成一个64位的整数，用来表示从文件头部的多少字节开始&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DWORD OffsetHigh;//操作，如果不是对文件I/O来操作，则必须设定为0&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PVOID Pointer;&nbsp;<br />
&nbsp;&nbsp;&nbsp; };&nbsp;<br />
&nbsp;&nbsp;&nbsp; HANDLE hEvent;//如果不使用，就务必设为0,否则请赋一个有效的Event句柄&nbsp;<br />
} OVERLAPPED, *LPOVERLAPPED;&nbsp;<br />
<br />
下面是异步方式使用ReadFile的一个例子&nbsp;<br />
OVERLAPPED Overlapped;&nbsp;<br />
Overlapped.Offset=345;&nbsp;<br />
Overlapped.OffsetHigh=0;&nbsp;<br />
Overlapped.hEvent=0;&nbsp;<br />
//假定其他参数都已经被初始化&nbsp;<br />
ReadFile(hFile,buffer,sizeof(buffer),&amp;dwNumBytesRead,&amp;Overlapped);&nbsp;<br />
这样就完成了异步方式读文件的操作，然后ReadFile函数返回，由操作系统做自己的事情，下面介绍几个与OVERLAPPED结构相关的函数&nbsp;<br />
等待重叠I/0操作完成的函数&nbsp;<br />
BOOL GetOverlappedResult (<br />
HANDLE hFile,<br />
LPOVERLAPPED lpOverlapped,//接受返回的重叠I/0结构<br />
LPDWORD lpcbTransfer,//成功传输了多少字节数<br />
BOOL fWait //TRUE只有当操作完成才返回，FALSE直接返回，如果操作没有完成，通过调//用GetLastError ( )函数会返回ERROR_IO_INCOMPLETE&nbsp;<br />
);<br />
宏HasOverlappedIoCompleted可以帮助我们测试重叠I/0操作是否完成，该宏对OVERLAPPED结构的Internal成员进行了测试，查看是否等于STATUS_PENDING值。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一般来说，一个应用程序可以创建多个工作线程来处理<strong>完成端口</strong>上的通知事件。工作线程的数量依赖于程序的具体需要。但是在理想的情况下，应该对应一个CPU创建一个线程。因为在<strong>完成端口</strong>理想模型中，每个线程都可以从系统获得一个&#8220;原子&#8221;性的时间片，轮番运行并检查<strong>完成端口</strong>，线程的切换是额外的开销。在实际开发的时候，还要考虑这些线程是否牵涉到其他堵塞操作的情况。如果某线程进行堵塞操作，系统则将其挂起，让别的线程获得运行时间。因此，如果有这样的情况，可以多创建几个线程来尽量利用时间。<br />
应用<strong>完成端口</strong>：<br />
&nbsp;&nbsp;&nbsp; 创建<strong>完成端口</strong>：<strong>完成端口</strong>是一个内核对象，使用时他总是要和至少一个有效的设备句柄进行关联，<strong>完成端口</strong>是一个复杂的内核对象，创建它的函数是：<br />
HANDLE CreateIoCompletionPort(&nbsp;<br />
&nbsp;&nbsp;&nbsp; IN HANDLE FileHandle,&nbsp;<br />
&nbsp;&nbsp;&nbsp; IN HANDLE ExistingCompletionPort,&nbsp;<br />
&nbsp;&nbsp;&nbsp; IN ULONG_PTR CompletionKey,&nbsp;<br />
&nbsp;&nbsp;&nbsp; IN DWORD NumberOfConcurrentThreads&nbsp;<br />
&nbsp;&nbsp;&nbsp; );&nbsp;<br />
<br />
通常创建工作分两步：<br />
第一步，创建一个新的<strong>完成端口</strong>内核对象，可以使用下面的函数：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HANDLE CreateNewCompletionPort(DWORD dwNumberOfThreads)&nbsp;<br />
{&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; return CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,NULL,dwNumberOfThreads);&nbsp;<br />
};<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
第二步，将刚创建的<strong>完成端口</strong>和一个有效的设备句柄关联起来，可以使用下面的函数：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bool AssicoateDeviceWithCompletionPort(HANDLE hCompPort,HANDLE hDevice,DWORD dwCompKey)&nbsp;<br />
{&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; HANDLE h=CreateIoCompletionPort(hDevice,hCompPort,dwCompKey,0);&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; return h==hCompPort;&nbsp;<br />
};&nbsp;<br />
说明&nbsp;<br />
1） CreateIoCompletionPort函数也可以一次性的既创建<strong>完成端口</strong>对象，又关联到一个有效的设备句柄&nbsp;<br />
2） CompletionKey是一个可以自己定义的参数，我们可以把一个结构的地址赋给它，然后在合适的时候取出来使用，最好要保证结构里面的内存不是分配在栈上，除非你有十分的把握内存会保留到你要使用的那一刻。<br />
3） NumberOfConcurrentThreads通常用来指定要允许同时运行的的线程的最大个数。通常我们指定为0，这样系统会根据CPU的个数来自动确定。创建和关联的动作完成后，系统会将<strong>完成端口</strong>关联的设备句柄、完成键作为一条纪录加入到这个<strong>完成端口</strong>的设备列表中。如果你有多个<strong>完成端口</strong>，就会有多个对应的设备列表。如果设备句柄被关闭，则表中自动删除该纪录。<br />
<strong><br />
4、<strong>完成端口</strong>线程的工作原理</strong><br />
<strong>完成端口</strong>可以帮助我们管理线程池，但是线程池中的线程需要我们使用_beginthreadex来创建，凭什么通知<strong>完成端口</strong>管理我们的新线程呢？答案在函数GetQueuedCompletionStatus。该函数原型：&nbsp;<br />
BOOL GetQueuedCompletionStatus(&nbsp;<br />
&nbsp;&nbsp;&nbsp; IN HANDLE CompletionPort,&nbsp;<br />
&nbsp;&nbsp;&nbsp; OUT LPDWORD lpNumberOfBytesTransferred,&nbsp;<br />
&nbsp;&nbsp;&nbsp; OUT PULONG_PTR lpCompletionKey,&nbsp;<br />
&nbsp;&nbsp;&nbsp; OUT LPOVERLAPPED *lpOverlapped,&nbsp;<br />
&nbsp;&nbsp;&nbsp; IN DWORD dwMilliseconds&nbsp;<br />
);&nbsp;<br />
这个函数试图从指定的<strong>完成端口</strong>的I/0完成队列中抽取纪录。只有当重叠I/O动作完成的时候，完成队列中才有纪录。凡是调用这个函数的线程将被放入到<strong>完成端口</strong>的等待线程队列中，因此<strong>完成端口</strong>就可以在自己的线程池中帮助我们维护这个线程。<strong>完成端口</strong>的I/0完成队列中存放了当重叠I/0完成的结果---- 一条纪录，该纪录拥有四个字段，前三项就对应GetQueuedCompletionStatus函数的2、3、4参数，最后一个字段是错误信息dwError。我们也可以通过调用PostQueudCompletionStatus模拟完成了一个重叠I/0操作。&nbsp;<br />
当I/0完成队列中出现了纪录，<strong>完成端口</strong>将会检查等待线程队列，该队列中的线程都是通过调用GetQueuedCompletionStatus函数使自己加入队列的。等待线程队列很简单，只是保存了这些线程的ID。<strong>完成端口</strong>会按照后进先出的原则将一个线程队列的ID放入到释放线程列表中，同时该线程将从等待GetQueuedCompletionStatus函数返回的睡眠状态中变为可调度状态等待CPU的调度。所以我们的线程要想成为<strong>完成端口</strong>管理的线程，就必须要调用GetQueuedCompletionStatus函数。出于性能的优化，实际上<strong>完成端口</strong>还维护了一个暂停线程列表，具体细节可以参考《Windows高级编程指南》，我们现在知道的知识，已经足够了。&nbsp;<strong>完成端口</strong>线程间数据传递线程间传递数据最常用的办法是在_beginthreadex函数中将参数传递给线程函数，或者使用全局变量。但是<strong>完成端口</strong>还有自己的传递数据的方法，答案就在于CompletionKey和OVERLAPPED参数。<br />
CompletionKey被保存在<strong>完成端口</strong>的设备表中，是和设备句柄一一对应的，我们可以将与设备句柄相关的数据保存到CompletionKey中，或者将CompletionKey表示为结构指针，这样就可以传递更加丰富的内容。这些内容只能在一开始关联<strong>完成端口</strong>和设备句柄的时候做，因此不能在以后动态改变。<br />
OVERLAPPED参数是在每次调用ReadFile这样的支持重叠I/0的函数时传递给<strong>完成端口</strong>的。我们可以看到，如果我们不是对文件设备做操作，该结构的成员变量就对我们几乎毫无作用。我们需要附加信息，可以创建自己的结构，然后将OVERLAPPED结构变量作为我们结构变量的第一个成员，然后传递第一个成员变量的地址给ReadFile函数。因为类型匹配，当然可以通过编译。当GetQueuedCompletionStatus函数返回时，我们可以获取到第一个成员变量的地址，然后一个简单的强制转换，我们就可以把它当作完整的自定义结构的指针使用，这样就可以传递很多附加的数据了。太好了！只有一点要注意，如果跨线程传递，请注意将数据分配到堆上，并且接收端应该将数据用完后释放。我们通常需要将ReadFile这样的异步函数的所需要的缓冲区放到我们自定义的结构中，这样当GetQueuedCompletionStatus被返回时，我们的自定义结构的缓冲区变量中就存放了I/0操作的数据。CompletionKey和OVERLAPPED参数，都可以通过GetQueuedCompletionStatus函数获得。<br />
线程的安全退出<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 很多线程为了不止一次的执行异步数据处理，需要使用如下语句<br />
while (true)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ......<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GetQueuedCompletionStatus(...);&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ......<br />
}<br />
那么如何退出呢，答案就在于上面曾提到的PostQueudCompletionStatus函数，我们可以用它发送一个自定义的包含了OVERLAPPED成员变量的结构地址，里面包含一个状态变量，当状态变量为退出标志时，线程就执行清除动作然后退出。<br />
<strong><br />
5、Windows<strong>完成端口</strong>的实例代码：<br />
</strong>DWORD WINAPI WorkerThread(LPVOID lpParam)<br />
{&nbsp;<br />
ULONG_PTR *PerHandleKey;<br />
OVERLAPPED *Overlap;<br />
OVERLAPPEDPLUS *OverlapPlus,<br />
*newolp;<br />
DWORD dwBytesXfered;<br />
while (1)<br />
{<br />
ret = GetQueuedCompletionStatus(<br />
hIocp,<br />
&amp;dwBytesXfered,<br />
(PULONG_PTR)&amp;PerHandleKey,<br />
&amp;Overlap,<br />
INFINITE);<br />
if (ret == 0)<br />
{<br />
// Operation failed<br />
continue;<br />
}<br />
OverlapPlus = CONTAINING_RECORD(Overlap, OVERLAPPEDPLUS, ol);<br />
switch (OverlapPlus-&gt;OpCode)<br />
{<br />
case OP_ACCEPT:<br />
// Client socket is contained in OverlapPlus.sclient<br />
// Add client to completion port<br />
CreateIoCompletionPort(<br />
(HANDLE)OverlapPlus-&gt;sclient,<br />
hIocp,<br />
(ULONG_PTR)0,<br />
0);<br />
// Need a new OVERLAPPEDPLUS structure<br />
// for the newly accepted socket. Perhaps<br />
// keep a look aside list of free structures.<br />
newolp = AllocateOverlappedPlus();<br />
if (!newolp)<br />
{<br />
// Error<br />
}<br />
newolp-&gt;s = OverlapPlus-&gt;sclient;<br />
newolp-&gt;OpCode = OP_READ;<br />
// This function divpares the data to be sent<br />
PrepareSendBuffer(&amp;newolp-&gt;wbuf);<br />
ret = WSASend(<br />
newolp-&gt;s,<br />
&amp;newolp-&gt;wbuf,<br />
1,<br />
&amp;newolp-&gt;dwBytes,<br />
0,<br />
&amp;newolp.ol,<br />
NULL);<br />
if (ret == SOCKET_ERROR)<br />
{<br />
if (WSAGetLastError() != WSA_IO_PENDING)<br />
{<br />
// Error<br />
}<br />
}<br />
// Put structure in look aside list for later use<br />
FreeOverlappedPlus(OverlapPlus);<br />
// Signal accept thread to issue another AcceptEx<br />
SetEvent(hAcceptThread);<br />
break;<br />
case OP_READ:<br />
// Process the data read&nbsp;<br />
// Repost the read if necessary, reusing the same<br />
// receive buffer as before<br />
memset(&amp;OverlapPlus-&gt;ol, 0, sizeof(OVERLAPPED));<br />
ret = WSARecv(<br />
OverlapPlus-&gt;s,<br />
&amp;OverlapPlus-&gt;wbuf,<br />
1,<br />
&amp;OverlapPlus-&gt;dwBytes,<br />
&amp;OverlapPlus-&gt;dwFlags,<br />
&amp;OverlapPlus-&gt;ol,<br />
NULL);<br />
if (ret == SOCKET_ERROR)<br />
{<br />
if (WSAGetLastError() != WSA_IO_PENDING)<br />
{<br />
// Error<br />
}<br />
}<br />
break;<br />
case OP_WRITE:<br />
// Process the data sent, etc.<br />
break;<br />
} // switch<br />
} // while<br />
} // WorkerThread<br />
</p>
<p>查看以上代码，注意如果Overlapped操作立刻失败（比如，返回SOCKET_ERROR或其他非WSA_IO_PENDING的错误），则没有任何完成通知时间会被放到<strong>完成端口</strong>队列里。反之，则一定有相应的通知时间被放到<strong>完成端口</strong>队列。更完善的关于Winsock的<strong>完成端口</strong>机制，可以参考MSDN的Microsoft PlatFormSDK，那里有<strong>完成端口</strong>的例子。访问<a href="http://msdn.microsoft.com/library/techart/msdn_servrapp.htm">http://msdn.microsoft.com/library/techart/msdn_servrapp.htm</a>可以获得更多信息。</p>
<p><strong>Linux的<strong>EPoll</strong>模型<br />
</strong>Linux 2.6内核中提高网络I/O性能的新方法-<strong>epoll</strong>&nbsp;I/O多路复用技术在比较多的TCP网络服务器中有使用，即比较多的用到select函数。<br />
<br />
<strong>1、为什么select落后<br />
</strong>首先，在Linux内核中，select所用到的FD_SET是有限的，即内核中有个参数__FD_SETSIZE定义了每个FD_SET的句柄个数，在我用的2.6.15-25-386内核中，该值是1024，搜索内核源代码得到：<br />
include/linux/posix_types.h:#define __FD_SETSIZE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1024<br />
也就是说，如果想要同时检测1025个句柄的可读状态是不可能用select实现的。或者同时检测1025个句柄的可写状态也是不可能的。其次，内核中实现select是用轮询方法，即每次检测都会遍历所有FD_SET中的句柄，显然，select函数执行时间与FD_SET中的句柄个数有一个比例关系，即select要检测的句柄数越多就会越费时。当然，在前文中我并没有提及poll方法，事实上用select的朋友一定也试过poll，我个人觉得select和poll大同小异，个人偏好于用select而已。</p>
<p><strong>2、内核中提高I/O性能的新方法<strong>epoll</strong></strong><br />
<strong>epoll</strong>是什么？按照man手册的说法：是为处理大批量句柄而作了改进的poll。要使用<strong>epoll</strong>只需要这三个系统调用：<strong>epoll</strong>_create(2)，&nbsp;<strong>epoll</strong>_ctl(2)，&nbsp;<strong>epoll</strong>_wait(2)。<br />
当然，这不是2.6内核才有的，它是在2.5.44内核中被引进的(<strong>epoll</strong>(4) is a new API introduced in Linux kernel 2.5.44)</p>
<p>Linux2.6内核<strong>epoll</strong>介绍<br />
先介绍2本书《The Linux Networking Architecture--Design and Implementation of Network Protocols in the Linux Kernel》，以2.4内核讲解Linux TCP/IP实现，相当不错.作为一个现实世界中的实现，很多时候你必须作很多权衡，这时候参考一个久经考验的系统更有实际意义。举个例子,linux内核中sk_buff结构为了追求速度和安全，牺牲了部分内存，所以在发送TCP包的时候，无论应用层数据多大,sk_buff最小也有272的字节.其实对于socket应用层程序来说，另外一本书《UNIX Network Programming Volume 1》意义更大一点.2003年的时候，这本书出了最新的第3版本，不过主要还是修订第2版本。其中第6章《I/O Multiplexing》是最重要的。Stevens给出了网络IO的基本模型。在这里最重要的莫过于select模型和Asynchronous I/O模型.从理论上说，AIO似乎是最高效的，你的IO操作可以立即返回，然后等待os告诉你IO操作完成。但是一直以来，如何实现就没有一个完美的方案。最著名的windows<strong>完成端口</strong>实现的AIO,实际上也是内部用线程池实现的罢了，最后的结果是IO有个线程池，你应用也需要一个线程池...... 很多文档其实已经指出了这带来的线程context-switch带来的代价。在linux 平台上，关于网络AIO一直是改动最多的地方，2.4的年代就有很多AIO内核patch,最著名的应该算是SGI那个。但是一直到2.6内核发布，网络模块的AIO一直没有进入稳定内核版本(大部分都是使用用户线程模拟方法，在使用了NPTL的linux上面其实和windows的<strong>完成端口</strong>基本上差不多了)。2.6内核所支持的AIO特指磁盘的AIO---支持io_submit(),io_getevents()以及对Direct IO的支持(就是绕过VFS系统buffer直接写硬盘，对于流服务器在内存平稳性上有相当帮助)。<br />
所以，剩下的select模型基本上就是我们在linux上面的唯一选择，其实，如果加上no-block socket的配置，可以完成一个"伪"AIO的实现，只不过推动力在于你而不是os而已。不过传统的select/poll函数有着一些无法忍受的缺点，所以改进一直是2.4-2.5开发版本内核的任务，包括/dev/poll，realtime signal等等。最终，Davide Libenzi开发的<strong>epoll</strong>进入2.6内核成为正式的解决方案<br />
<strong><br />
3、<strong>epoll</strong>的优点</strong><br />
&lt;1&gt;支持一个进程打开大数目的socket描述符(FD)<br />
select 最不能忍受的是一个进程所打开的FD是有一定限制的，由FD_SETSIZE设置，默认值是2048。对于那些需要支持的上万连接数目的IM服务器来说显然太少了。这时候你一是可以选择修改这个宏然后重新编译内核，不过资料也同时指出这样会带来网络效率的下降，二是可以选择多进程的解决方案(传统的Apache方案)，不过虽然linux上面创建进程的代价比较小，但仍旧是不可忽视的，加上进程间数据同步远比不上线程间同步的高效，所以也不是一种完美的方案。不过&nbsp;<strong>epoll</strong>则没有这个限制，它所支持的FD上限是最大可以打开文件的数目，这个数字一般远大于2048,举个例子,在1GB内存的机器上大约是10万左右，具体数目可以cat /proc/sys/fs/file-max察看,一般来说这个数目和系统内存关系很大。<br />
&lt;2&gt;IO效率不随FD数目增加而线性下降<br />
传统的select/poll另一个致命弱点就是当你拥有一个很大的socket集合，不过由于网络延时，任一时间只有部分的socket是"活跃"的，但是select/poll每次调用都会线性扫描全部的集合，导致效率呈现线性下降。但是<strong>epoll</strong>不存在这个问题，它只会对"活跃"的socket进行操作---这是因为在内核实现中<strong>epoll</strong>是根据每个fd上面的callback函数实现的。那么，只有"活跃"的socket才会主动的去调用 callback函数，其他idle状态socket则不会，在这点上，<strong>epoll</strong>实现了一个"伪"AIO，因为这时候推动力在os内核。在一些 benchmark中，如果所有的socket基本上都是活跃的---比如一个高速LAN环境，<strong>epoll</strong>并不比select/poll有什么效率，相反，如果过多使用<strong>epoll</strong>_ctl,效率相比还有稍微的下降。但是一旦使用idle connections模拟WAN环境,<strong>epoll</strong>的效率就远在select/poll之上了。<br />
&lt;3&gt;使用mmap加速内核与用户空间的消息传递。<br />
这点实际上涉及到<strong>epoll</strong>的具体实现了。无论是select,poll还是<strong>epoll</strong>都需要内核把FD消息通知给用户空间，如何避免不必要的内存拷贝就很重要，在这点上，<strong>epoll</strong>是通过内核于用户空间mmap同一块内存实现的。而如果你想我一样从2.5内核就关注<strong>epoll</strong>的话，一定不会忘记手工 mmap这一步的。<br />
&lt;4&gt;内核微调<br />
这一点其实不算<strong>epoll</strong>的优点了，而是整个linux平台的优点。也许你可以怀疑linux平台，但是你无法回避linux平台赋予你微调内核的能力。比如，内核TCP/IP协议栈使用内存池管理sk_buff结构，那么可以在运行时期动态调整这个内存pool(skb_head_pool)的大小--- 通过echo XXXX&gt;/proc/sys/net/core/hot_list_length完成。再比如listen函数的第2个参数(TCP完成3次握手的数据包队列长度)，也可以根据你平台内存大小动态调整。更甚至在一个数据包面数目巨大但同时每个数据包本身大小却很小的特殊系统上尝试最新的NAPI网卡驱动架构。<br />
4、<strong>epoll</strong>的工作模式<br />
令人高兴的是，2.6内核的<strong>epoll</strong>比其2.5开发版本的/dev/<strong>epoll</strong>简洁了许多，所以，大部分情况下，强大的东西往往是简单的。唯一有点麻烦是<strong>epoll</strong>有2种工作方式:LT和ET。<br />
LT(level triggered)是缺省的工作方式，并且同时支持block和no-block socket.在这种做法中，内核告诉你一个文件描述符是否就绪了，然后你可以对这个就绪的fd进行IO操作。如果你不作任何操作，内核还是会继续通知你的，所以，这种模式编程出错误可能性要小一点。传统的select/poll都是这种模型的代表．<br />
ET (edge-triggered)是高速工作方式，只支持no-block socket。在这种模式下，当描述符从未就绪变为就绪时，内核通过<strong>epoll</strong>告诉你。然后它会假设你知道文件描述符已经就绪，并且不会再为那个文件描述符发送更多的就绪通知，直到你做了某些操作导致那个文件描述符不再为就绪状态了(比如，你在发送，接收或者接收请求，或者发送接收的数据少于一定量时导致了一个EWOULDBLOCK 错误）。但是请注意，如果一直不对这个fd作IO操作(从而导致它再次变成未就绪)，内核不会发送更多的通知(only once),不过在TCP协议中，ET模式的加速效用仍需要更多的benchmark确认。<br />
<strong>epoll</strong>只有<strong>epoll</strong>_create,<strong>epoll</strong>_ctl,<strong>epoll</strong>_wait 3个系统调用，具体用法请参考<a href="http://www.xmailserver.org/linux-patches/nio-improve.html">http://www.xmailserver.org/linux-patches/nio-improve.html</a>&nbsp;，在<a href="http://www.kegel.com/rn/">http://www.kegel.com/rn/</a>也有一个完整的例子，大家一看就知道如何使用了<br />
Leader/follower模式线程pool实现，以及和<strong>epoll</strong>的配合。<br />
<br />
<strong>5、&nbsp;<strong>epoll</strong>的使用方法</strong><br />
&nbsp;&nbsp;&nbsp; 首先通过create_<strong>epoll</strong>(int maxfds)来创建一个<strong>epoll</strong>的句柄，其中maxfds为你<strong>epoll</strong>所支持的最大句柄数。这个函数会返回一个新的<strong>epoll</strong>句柄，之后的所有操作将通过这个句柄来进行操作。在用完之后，记得用close()来关闭这个创建出来的<strong>epoll</strong>句柄。 之后在你的网络主循环里面，每一帧的调用<strong>epoll</strong>_wait(int epfd,&nbsp;<strong>epoll</strong>_event events, int max events, int timeout)来查询所有的网络接口，看哪一个可以读，哪一个可以写了。基本的语法为：&nbsp;<br />
nfds =&nbsp;<strong>epoll</strong>_wait(kdpfd, events, maxevents, -1);&nbsp;<br />
其中kdpfd为用<strong>epoll</strong>_create创建之后的句柄，events是一个<strong>epoll</strong>_event*的指针，当<strong>epoll</strong>_wait这个函数操作成功之后，<strong>epoll</strong>_events里面将储存所有的读写事件。max_events是当前需要监听的所有socket句柄数。最后一个timeout是<strong>epoll</strong>_wait的超时，为0的时候表示马上返回，为-1的时候表示一直等下去，直到有事件范围，为任意正整数的时候表示等这么长的时间，如果一直没有事件，则范围。一般如果网络主循环是单独的线程的话，可以用-1来等，这样可以保证一些效率，如果是和主逻辑在同一个线程的话，则可以用0来保证主循环的效率。</p>
<p><strong>epoll</strong>_wait范围之后应该是一个循环，遍利所有的事件：&nbsp;<br />
for(n = 0; n &lt; nfds; ++n) {&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(events[n].data.fd == listener) { //如果是主socket的事件的话，则表示有新连接进入了，进行新连接的处理。&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; client = accept(listener, (struct sockaddr *) &amp;local,&nbsp;<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; &amp;addrlen);&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(client &lt; 0){&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; perror("accept");&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; continue;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&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; setnonblocking(client); // 将新连接置于非阻塞模式&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ev.events = EPOLLIN | EPOLLET; // 并且将新连接也加入<strong>EPOLL</strong>的监听队列。&nbsp;<br />
注意，这里的参数EPOLLIN | EPOLLET并没有设置对写socket的监听，如果有写操作的话，这个时候<strong>epoll</strong>是不会返回事件的，如果要对写操作也监听的话，应该是EPOLLIN | EPOLLOUT | EPOLLET&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ev.data.fd = client;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (<strong>epoll</strong>_ctl(kdpfd,&nbsp;<strong>EPOLL</strong>_CTL_ADD, client, &amp;ev) &lt; 0) {&nbsp;<br />
// 设置好event之后，将这个新的event通过<strong>epoll</strong>_ctl加入到<strong>epoll</strong>的监听队列里面，这里用<strong>EPOLL</strong>_CTL_ADD来加一个新的<strong>epoll</strong>事件，通过<strong>EPOLL</strong>_CTL_DEL来减少一个<strong>epoll</strong>事件，通过<strong>EPOLL</strong>_CTL_MOD来改变一个事件的监听方式。&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fprintf(stderr, "<strong>epoll</strong>&nbsp;set insertion error: fd=%d0,&nbsp;<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; client);&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -1;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&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;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else // 如果不是主socket的事件的话，则代表是一个用户socket的事件，则来处理这个用户socket的事情，比如说read(fd,xxx)之类的，或者一些其他的处理。&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; do_use_fd(events[n].data.fd);&nbsp;<br />
}</p>
<p>对，<strong>epoll</strong>的操作就这么简单，总共不过4个API：<strong>epoll</strong>_create,&nbsp;<strong>epoll</strong>_ctl,&nbsp;<strong>epoll</strong>_wait和close。&nbsp;<br />
如果您对<strong>epoll</strong>的效率还不太了解，请参考我之前关于网络游戏的网络编程等相关的文章。</p>
<p><br />
以前公司的服务器都是使用HTTP连接，但是这样的话，在手机目前的网络情况下不但显得速度较慢，而且不稳定。因此大家一致同意用SOCKET来进行连接。虽然使用SOCKET之后，对于用户的费用可能会增加(由于是用了CMNET而非CMWAP)，但是，秉着用户体验至上的原则，相信大家还是能够接受的(希望那些玩家月末收到帐单不后能够保持克制...)。<br />
这次的服务器设计中，最重要的一个突破，是使用了<strong>EPOLL</strong>模型，虽然对之也是一知半解，但是既然在各大PC网游中已经经过了如此严酷的考验，相信他不会让我们失望，使用后的结果，确实也是表现相当不错。在这里，我还是主要大致介绍一下这个模型的结构。<br />
6、Linux下<strong>EPOll</strong>编程实例<br />
<strong>EPOLL</strong>模型似乎只有一种格式，所以大家只要参考我下面的代码，就能够对<strong>EPOLL</strong>有所了解了，代码的解释都已经在注释中：</p>
<p>while (TRUE)<br />
{<br />
int nfds =&nbsp;<strong>epoll</strong>_wait (m_<strong>epoll</strong>_fd, m_events, MAX_EVENTS,&nbsp;<strong>EPOLL</strong>_TIME_OUT);//等待<strong>EPOLL</strong>时间的发生，相当于监听，至于相关的端口，需要在初始化<strong>EPOLL</strong>的时候绑定。<br />
if (nfds &lt;= 0)<br />
continue;<br />
m_bOnTimeChecking = FALSE;<br />
G_CurTime = time(NULL);<br />
for (int i=0; i<br />
{<br />
try<br />
{<br />
if (m_events[i].data.fd == m_listen_http_fd)//如果新监测到一个HTTP用户连接到绑定的HTTP端口，建立新的连接。由于我们新采用了SOCKET连接，所以基本没用。<br />
{<br />
OnAcceptHttpEpoll ();<br />
}<br />
else if (m_events[i].data.fd == m_listen_sock_fd)//如果新监测到一个SOCKET用户连接到了绑定的SOCKET端口，建立新的连接。<br />
{<br />
OnAcceptSockEpoll ();<br />
}<br />
else if (m_events[i].events &amp; EPOLLIN)//如果是已经连接的用户，并且收到数据，那么进行读入。<br />
{<br />
OnReadEpoll (i);<br />
}</p>
<p>OnWriteEpoll (i);//查看当前的活动连接是否有需要写出的数据。<br />
}<br />
catch (int)<br />
{<br />
PRINTF ("CATCH捕获错误\n");<br />
continue;<br />
}<br />
}<br />
m_bOnTimeChecking = TRUE;<br />
OnTimer ();//进行一些定时的操作，主要就是删除一些短线用户等。<br />
}<br />
其实<strong>EPOLL</strong>的精华，也就是上述的几段短短的代码，看来时代真的不同了，以前如何接受大量用户连接的问题，现在却被如此轻松的搞定，真是让人不得不感叹，对哪。</p>
<p><br />
<strong>总结<br />
</strong>Windows<strong>完成端口</strong>与Linux&nbsp;<strong>epoll</strong>技术方案是这2个平台上实现异步IO和设计开发一个大容量，具可扩展性的winsock程序指服务程序的很好的选择，本文对这2中技术的实现原理和实际的使用方法做了一个详细的介绍。</p>
@import url(http://www.cppblog.com/CuteSoft_Client/CuteEditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css);<img src ="http://www.cppblog.com/singohgod/aggbug/152376.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/singohgod/" target="_blank">大宝天天见</a> 2011-08-03 17:43 <a href="http://www.cppblog.com/singohgod/archive/2011/08/03/152376.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转载]linux下automake用法</title><link>http://www.cppblog.com/singohgod/archive/2011/08/01/152224.html</link><dc:creator>大宝天天见</dc:creator><author>大宝天天见</author><pubDate>Mon, 01 Aug 2011 09:40:00 GMT</pubDate><guid>http://www.cppblog.com/singohgod/archive/2011/08/01/152224.html</guid><wfw:comment>http://www.cppblog.com/singohgod/comments/152224.html</wfw:comment><comments>http://www.cppblog.com/singohgod/archive/2011/08/01/152224.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/singohgod/comments/commentRss/152224.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/singohgod/services/trackbacks/152224.html</trackback:ping><description><![CDATA[<div>
<div>作为Linux下的程序开发人员，大家一定都遇到过Makefile，用make命令来编译自己写的程序确实是很方便。一般情况下，大家都是手工写一个简单Makefile，如果要想写出一个符合自由软件惯例的Makefile就不那么容易了。&nbsp;</div>
</div>
<div>
<p><br />
在本文中，将给大家介绍如何使用&nbsp;autoconf和automake两个工具来帮助我们自动地生成符合自由软件惯例的Makefile，这样就可以象常见的GNU程序一样，只要使用&#8220;./configure&#8221;，&#8220;make&#8221;，&#8220;make install&#8221;就可以把程序安装到Linux系统中去了。这将特别适合想做开放源代码软件的程序开发人员，又或如果你只是自己写些小的Toy程序，那么这个文章对你也会有很大的帮助。</p>
<p>编译一个简单的源文件main.c,需要自动生成一个makefile,以下是步骤：</p>
<p>第一步：</p>
<p>----------</p>
<p>在/root/project/main目录下创建一个文件main.c,其内容如下：</p>
<p>------------------------------------------------</p>
<p>#include &lt;stdio.h&gt;</p>
<p>int main(int argc, char** argv)</p>
<p>{</p>
<p>printf("Hello, Auto Makefile!\n");</p>
<p>return 0;</p>
<p>}</p>
<p>------------------------------------------------</p>
<p>此时状态如下：</p>
<p>[root@localhost main]#&nbsp;<strong>pwd</strong></p>
<p>/root/project/main</p>
<p>[root@localhost main]#&nbsp;<strong>ls</strong></p>
<p><strong>main.c</strong></p>
<p>[root@localhost main]#</p>
<p>第二步：</p>
<p>----------</p>
<p>运行&nbsp;<strong>autoscan</strong>&nbsp;, 自动创建两个文件： autoscan.log configure.scan</p>
<p>此时状态如下：</p>
<p>[root@localhost main]#&nbsp;<strong>autoscan</strong></p>
<p>[root@localhost main]#&nbsp;<strong>ls</strong></p>
<p><strong>autoscan.log configure.scan</strong>&nbsp;main.c</p>
<p>[root@localhost main]#</p>
<p>第三步：</p>
<p>----------</p>
<p>修改configure.scan的文件名为configure.in</p>
<p>查看<strong>configure.in</strong>的内容：</p>
<p>------------------------------------------------</p>
<p># -*- Autoconf -*-</p>
<p># Process this file with autoconf to produce a configure script.</p>
<p>AC_PREREQ(2.61)</p>
<p>AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS)</p>
<p>AC_CONFIG_SRCDIR([main.c])</p>
<p>AC_CONFIG_HEADER([config.h])</p>
<p># Checks for programs.</p>
<p>AC_PROG_CC</p>
<p># Checks for libraries.</p>
<p># Checks for header files.</p>
<p># Checks for typedefs, structures, and compiler characteristics.</p>
<p># Checks for library functions.</p>
<p>AC_OUTPUT</p>
<p>------------------------------------------------</p>
<p>解读以上的文件：</p>
<p>------------------------------------------------</p>
<p># -*- Autoconf -*-</p>
<p># Process this file with autoconf to produce a configure script.</p>
<p># AC_PREREQ:</p>
<p># 确保使用的是足够新的Autoconf版本。如果用于创建configure的Autoconf的版</p>
<p># 本比version 要早，就在标准错误输出打印一条错误消息并不会创建configure。</p>
<p>AC_PREREQ(2.61)</p>
<p>#</p>
<p># 初始化,定义软件的基本信息,包括设置包的全称,版本号以及报告BUG时需要用的邮箱地址</p>
<p>#</p>
<p>AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS)</p>
<p>#</p>
<p># 用来侦测所指定的源码文件是否存在，来确定源码目录的有效性</p>
<p>#</p>
<p>AC_CONFIG_SRCDIR([main.c])</p>
<p>#</p>
<p># 用于生成config.h文件，以便autoheader使用</p>
<p>#</p>
<p>AC_CONFIG_HEADER([config.h])</p>
<p># Checks for programs.</p>
<p>AC_PROG_CC</p>
<p># Checks for libraries.</p>
<p># Checks for header files.</p>
<p># Checks for typedefs, structures, and compiler characteristics.</p>
<p># Checks for library functions.</p>
<p>#</p>
<p># 创建输出文件。在`configure.in'的末尾调用本宏一次。</p>
<p>#</p>
<p>AC_OUTPUT</p>
<p>------------------------------------------------</p>
<p>修改动作:</p>
<p>1.修改AC_INIT里面的参数: AC_INIT(main,1.0, pgpxc@163.com)</p>
<p>2.添加宏AM_INIT_AUTOMAKE, 它是automake所必备的宏，也同前面一样，PACKAGE是所要产生软件套件的名称，VERSION是版本编号。</p>
<p>3.在AC_OUTPUT后添加输出文件Makefile</p>
<p>修改后的结果:</p>
<p>------------------------------------------------</p>
<p># -*- Autoconf -*-</p>
<p># Process this file with autoconf to produce a configure script.</p>
<p>AC_PREREQ(2.61)</p>
<p><strong>AC_INIT(main, 1.0, pgpxc@163.com)</strong></p>
<p>AC_CONFIG_SRCDIR([main.c])</p>
<p>AC_CONFIG_HEADER([config.h])</p>
<p><strong>AM_INIT_AUTOMAKE(main,1.0)</strong></p>
<p># Checks for programs.</p>
<p>AC_PROG_CC</p>
<p># Checks for libraries.</p>
<p># Checks for header files.</p>
<p># Checks for typedefs, structures, and compiler characteristics.</p>
<p># Checks for library functions.</p>
<p><strong>AC_OUTPUT([Makefile])</strong></p>
<p>------------------------------------------------</p>
<p>第四步:</p>
<p>运行&nbsp;<strong>aclocal</strong>, 生成一个&#8220;<strong>aclocal.m4</strong>&#8221;文件和一个缓冲文件夹<strong>autom4te.cache</strong>，该文件主要处理本地的宏定义。</p>
<p>此时的状态是：</p>
<p>[root@localhost main]#&nbsp;<strong>aclocal</strong></p>
<p>[root@localhost main]#&nbsp;<strong>ls</strong></p>
<p><strong>aclocal.m4 autom4te.cache</strong>&nbsp;autoscan.log configure.in configure.in~ main.c</p>
<p>[root@localhost main]#</p>
<p>第五步：</p>
<p>运行&nbsp;<strong>autoconf</strong>, 目的是生成 configure</p>
<p>此时的状态是：</p>
<p>[root@localhost main]#&nbsp;<strong>autoconf</strong></p>
<p>[root@localhost main]#&nbsp;<strong>ls</strong></p>
<p>aclocal.m4 autoscan.log configure.in main.c</p>
<p>autom4te.cache&nbsp;<strong>configure</strong>&nbsp;configure.in~</p>
<p>[root@localhost main]#</p>
<p>第六步：</p>
<p>运行&nbsp;<strong>autoheader</strong>，它负责生成config.h.in文件。该工具通常会从&#8220;acconfig.h&#8221;文件中复制用户附加的符号定义，因此此处没有附加符号定义，所以不需要创建&#8220;acconfig.h&#8221;文件。</p>
<p>此时的状态是：</p>
<p>[root@localhost main]#&nbsp;<strong>autoheader</strong></p>
<p>[root@localhost main]#&nbsp;<strong>ls</strong></p>
<p>aclocal.m4 autoscan.log configure configure.in~</p>
<p>autom4te.cache&nbsp;<strong>config.h.in</strong>&nbsp;configure.in main.c</p>
<p>[root@localhost main]#</p>
<p>第七步：</p>
<p>下面即将运行&nbsp;<strong>automake</strong>, 但在此之前应该做一下准备工作!</p>
<p>首先</p>
<p>创建一个&nbsp;<strong>Makefile.am</strong>.这一步是创建Makefile很重要的一步，automake要用的脚本配置文件是Makefile.am，用户需要自己创建相应的文件。之后，automake工具转换成Makefile.in。</p>
<p>这个Makefile.am的内容如下：</p>
<p>------------------------------------------------</p>
<p>AUTOMAKE_OPTIONS=foreign</p>
<p>bin_PROGRAMS=main</p>
<p>main_SOURCES=main.c</p>
<p>------------------------------------------------</p>
<p>下面对该脚本文件的对应项进行解释。</p>
<p>其中的AUTOMAKE_OPTIONS为设置automake的选项。由于GNU（在第1章中已经有所介绍）对自己发布的软件有严格的规范，比如必须附 带许可证声明文件COPYING等，否则automake执行时会报错。automake提供了三种软件等级：foreign、gnu和gnits，让用 户选择采用，默认等级为gnu。在本例使用foreign等级，它只检测必须的文件。</p>
<p>bin_PROGRAMS定义要产生的执行文件名。如果要产生多个执行文件，每个文件名用空格隔开。</p>
<p>main_SOURCES定义&#8220;main&#8221;这个执行程序所需要的原始文件。如果&#8221;main&#8221;这个程序是由多个原始文件所产生的，则必须把它所用到的所有原 始文件都列出来，并用空格隔开。例如：若目标体&#8220;main&#8221;需要&#8220;main.c&#8221;、&#8220;sunq.c&#8221;、&#8220;main.h&#8221;三个依赖文件，则定义 main_SOURCES=main.c sunq.c main.h。要注意的是，如果要定义多个执行文件，则对每个执行程序都要定义相应的file_SOURCES。</p>
<p>其次</p>
<p>使用automake对其生成&#8220;configure.in&#8221;文件，在这里使用选项&#8220;&#8212;adding-missing&#8221;可以让automake自动添加有一些必需的脚本文件。</p>
<p>运行后的状态是：</p>
<p>------------------------------------------------</p>
<p>[root@localhost main]#&nbsp;<strong>automake --add-missing</strong></p>
<p>configure.in:8: installing `./missing'</p>
<p>configure.in:8: installing `./install-sh'</p>
<p>Makefile.am: installing `./depcomp'</p>
<p>[root@localhost main]#&nbsp;<strong>ls</strong></p>
<p>aclocal.m4 config.h.in configure.in~ main.c Makefile.in</p>
<p>autom4te.cache configure&nbsp;<strong>depcomp</strong>&nbsp;<strong>Makefile.am</strong>&nbsp;<strong>missing</strong></p>
<p>autoscan.log configure.in&nbsp;<strong>install-sh</strong>&nbsp;Makefile.am~</p>
<p>[root@localhost main]#</p>
<p>------------------------------------------------</p>
<p>第八步</p>
<p>运行<strong>configure</strong>，在这一步中，通过运行自动配置设置文件configure，把Makefile.in变成了最终的Makefile。</p>
<p>运行的结果如下：</p>
<p>------------------------------------------------</p>
<p>[root@localhost main]#&nbsp;<strong>./configure</strong></p>
<p>checking for a BSD-compatible install... /usr/bin/install -c</p>
<p>checking whether build environment is sane... yes</p>
<p>checking for a thread-safe mkdir -p... /bin/mkdir -p</p>
<p>checking for gawk... gawk</p>
<p>checking whether make sets $(MAKE)... yes</p>
<p>checking for gcc... gcc</p>
<p>checking for C compiler default output file name... a.out</p>
<p>checking whether the C compiler works... yes</p>
<p>checking whether we are cross compiling... no</p>
<p>checking for suffix of executables...</p>
<p>checking for suffix of object files... o</p>
<p>checking whether we are using the GNU C compiler... yes</p>
<p>checking whether gcc accepts -g... yes</p>
<p>checking for gcc option to accept ISO C89... none needed</p>
<p>checking for style of include used by make... GNU</p>
<p>checking dependency style of gcc... gcc3</p>
<p>configure: creating ./config.status</p>
<p><strong>config.status: creating Makefile</strong></p>
<p>config.status: creating config.h</p>
<p>config.status: executing depfiles commands</p>
<p>[root@localhost main]# ls</p>
<p>aclocal.m4 config.h.in configure.in main.c Makefile.in</p>
<p>autom4te.cache config.log configure.in~ Makefile&nbsp;<strong>missing</strong></p>
<p>autoscan.log config.status&nbsp;<strong>depcomp</strong>&nbsp;Makefile.am&nbsp;<strong>stamp-h1</strong></p>
<p><strong>config.h</strong>&nbsp;configure&nbsp;<strong>install-sh</strong>&nbsp;Makefile.am~</p>
<p>[root@localhost main]#</p>
<p>------------------------------------------------</p>
<p>第九步</p>
<p>运行&nbsp;<strong>make</strong>，对配置文件Makefile进行测试一下</p>
<p>此时的状态如下:</p>
<p>------------------------------------------------</p>
<p>[root@localhost main]#&nbsp;<strong>make</strong></p>
<p>cd . &amp;&amp; /bin/sh /root/project/main/missing --run aclocal-1.10</p>
<p>cd . &amp;&amp; /bin/sh /root/project/main/missing --run automake-1.10 --foreign</p>
<p>cd . &amp;&amp; /bin/sh /root/project/main/missing --run autoconf</p>
<p>/bin/sh ./config.status --recheck</p>
<p>running CONFIG_SHELL=/bin/sh /bin/sh ./configure --no-create --no-recursion</p>
<p>checking for a BSD-compatible install... /usr/bin/install -c</p>
<p>checking whether build environment is sane... yes</p>
<p>checking for a thread-safe mkdir -p... /bin/mkdir -p</p>
<p>checking for gawk... gawk</p>
<p>checking whether make sets $(MAKE)... yes</p>
<p>checking for gcc... gcc</p>
<p>checking for C compiler default output file name... a.out</p>
<p>checking whether the C compiler works... yes</p>
<p>checking whether we are cross compiling... no</p>
<p>checking for suffix of executables...</p>
<p>checking for suffix of object files... o</p>
<p>checking whether we are using the GNU C compiler... yes</p>
<p>checking whether gcc accepts -g... yes</p>
<p>checking for gcc option to accept ISO C89... none needed</p>
<p>checking for style of include used by make... GNU</p>
<p>checking dependency style of gcc... gcc3</p>
<p>configure: creating ./config.status</p>
<p>/bin/sh ./config.status</p>
<p>config.status: creating Makefile</p>
<p>config.status: creating config.h</p>
<p>config.status: config.h is unchanged</p>
<p>config.status: executing depfiles commands</p>
<p>cd . &amp;&amp; /bin/sh /root/project/main/missing --run autoheader</p>
<p>rm -f stamp-h1</p>
<p>touch config.h.in</p>
<p>make all-am</p>
<p>make[1]: Entering directory `/root/project/main'</p>
<p>gcc -DHAVE_CONFIG_H -I. -g -O2 -MT main.o -MD -MP -MF .deps/main.Tpo -c -o main.o main.c</p>
<p>mv -f .deps/main.Tpo .deps/main.Po</p>
<p>gcc -g -O2 -o main main.o</p>
<p>cd . &amp;&amp; /bin/sh ./config.status config.h</p>
<p>config.status: creating config.h</p>
<p>config.status: config.h is unchanged</p>
<p>make[1]: Leaving directory `/root/project/main'</p>
<p>[root@localhost main]#&nbsp;<strong>ls</strong></p>
<p>aclocal.m4 autoscan.log config.h.in config.status configure.in depcomp&nbsp;<strong>main main.o</strong>&nbsp;Makefile.am Makefile.in stamp-h1</p>
<p>autom4te.cache config.h config.log configure configure.in~ install-sh main.c Makefile Makefile.am~ missing</p>
<p>[root@localhost main]#</p>
<p>------------------------------------------------</p>
<p>第十步</p>
<p>运行生成的文件 main：</p>
<p>------------------------------------------------</p>
<p>[root@localhost main]#&nbsp;<strong>./main</strong></p>
<p>Hello, Auto Makefile!</p>
<p>[root@localhost main]#</p>
<p>------------------------------------------------</p>
<p>我用的是ubuntu</p>
<p>以上就是全文了.但有一处要改:用aclocal</p>
<p>全报有一个m4文件有错.找到报错的那一行.把变量加个中括号就可以了</p>
</div>
@import url(http://www.cppblog.com/CuteSoft_Client/CuteEditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css);<img src ="http://www.cppblog.com/singohgod/aggbug/152224.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/singohgod/" target="_blank">大宝天天见</a> 2011-08-01 17:40 <a href="http://www.cppblog.com/singohgod/archive/2011/08/01/152224.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转载]Linux服务器空闲后自动断开的相关设置</title><link>http://www.cppblog.com/singohgod/archive/2011/07/14/150991.html</link><dc:creator>大宝天天见</dc:creator><author>大宝天天见</author><pubDate>Thu, 14 Jul 2011 08:46:00 GMT</pubDate><guid>http://www.cppblog.com/singohgod/archive/2011/07/14/150991.html</guid><wfw:comment>http://www.cppblog.com/singohgod/comments/150991.html</wfw:comment><comments>http://www.cppblog.com/singohgod/archive/2011/07/14/150991.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/singohgod/comments/commentRss/150991.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/singohgod/services/trackbacks/150991.html</trackback:ping><description><![CDATA[&nbsp;怎样让服务器和一定时间没有任何操作的终端自动断开连接？ # vi /etc/profile 增加： TMOUT=1800 这样30分钟没操作就自动LOGOUT<br />
<br />
最近发现 SecureCRT连接到sshd服务器后在一段时间内不操作就老会自动断开，在网上查了一下，发现原来是因为客户端与服务器之间存在防火墙，安全起见，在超过特定的时间后就会把空闲连接断开。 解决方法： 既然会断开超时的空闲连接，那么我们就应该让客户端与服务器之间的连接&#8220;忙&#8221;起来，方法有两个: <br />
从服务器方面入手： 修改/etc/ssh/sshd_config配置文件 ClientAliveInterval 300（默认为0） 这个参数的是意思是每5分钟，服务器向客户端发一个消息，用于保持连接 service sshd reload 生效 <br />
从客户端入手： 上面是配置需要服务器权限，如果没有服务器权限则可以使用这个方法，其思想是：客户端向服务器发一个消息，用于保持连接 secureCRT在选项 终端 反空闲 中设置每隔多少秒发送一个字符串，或者是NO-OP协议包 putty：putty -&gt; Connection -&gt; Seconds between keepalives ( 0 to turn off ), 默认为0, 改为300.
@import url(http://www.cppblog.com/CuteSoft_Client/CuteEditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css);<img src ="http://www.cppblog.com/singohgod/aggbug/150991.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/singohgod/" target="_blank">大宝天天见</a> 2011-07-14 16:46 <a href="http://www.cppblog.com/singohgod/archive/2011/07/14/150991.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[原创]linux缺少库时添加查找路径</title><link>http://www.cppblog.com/singohgod/archive/2011/07/10/150604.html</link><dc:creator>大宝天天见</dc:creator><author>大宝天天见</author><pubDate>Sun, 10 Jul 2011 11:02:00 GMT</pubDate><guid>http://www.cppblog.com/singohgod/archive/2011/07/10/150604.html</guid><wfw:comment>http://www.cppblog.com/singohgod/comments/150604.html</wfw:comment><comments>http://www.cppblog.com/singohgod/archive/2011/07/10/150604.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/singohgod/comments/commentRss/150604.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/singohgod/services/trackbacks/150604.html</trackback:ping><description><![CDATA[<p>打开/etc/ld.so.conf文件在其后面添加链接查找路径：/usr/local/lib（或其他库所在路径），为了启用该配置在终端输入ldconfig。<br />
<br />
今天安装codeblocks就遇到了这个问题，库在/usr/lib下，不加上这个配置始终提示：<br />
./codeblocks: error while loading shared libraries: libcodeblocks.so.0: cannot open shared object file: No such file or directory<br />
<br />
加上后问题解决！~</p>
@import url(http://www.cppblog.com/CuteSoft_Client/CuteEditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css);<img src ="http://www.cppblog.com/singohgod/aggbug/150604.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/singohgod/" target="_blank">大宝天天见</a> 2011-07-10 19:02 <a href="http://www.cppblog.com/singohgod/archive/2011/07/10/150604.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转载]Flex 4里的fx、mx以及s命名空间</title><link>http://www.cppblog.com/singohgod/archive/2011/06/27/149595.html</link><dc:creator>大宝天天见</dc:creator><author>大宝天天见</author><pubDate>Mon, 27 Jun 2011 10:09:00 GMT</pubDate><guid>http://www.cppblog.com/singohgod/archive/2011/06/27/149595.html</guid><wfw:comment>http://www.cppblog.com/singohgod/comments/149595.html</wfw:comment><comments>http://www.cppblog.com/singohgod/archive/2011/06/27/149595.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/singohgod/comments/commentRss/149595.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/singohgod/services/trackbacks/149595.html</trackback:ping><description><![CDATA[<p>Flex 4带给我们的，是全新的命名空间。了解这些命名空间必定是一件好事情。Flex 4有三个非常重要的命名空间，分别是：</p>
<p><strong>xmlns:fx=&#8221;http://ns.adobe.com/mxml/2009&#8243; <br />xmlns:mx=&#8221;library://ns.adobe.com/flex/halo&#8221; <br />xmlns:s=&#8221;library://ns.adobe.com/flex/spark&#8221;</strong> <br /><br /><strong>1、xmlns:fx=&#8221;http://ns.adobe.com/mxml/2009&#8243;</strong><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fx命名空间下包含ActionScript顶级元素和内建到MXML编译器里的标签。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 前者ActionScript顶级元素就是指 Object、Number、Boolean以及Array对象等等，在《Adobe Flex 4 Beta Language Reference》的顶级包（Top Level）里可以查看完整的顶级元素。后者内建到MXML编译器里的标签包括&lt;fx:Script&gt;、&lt;fx:Declarations&gt;和&lt;fx:Style&gt;等等，在《Adobe Flex 4 Beta Language Reference》附录（Appendixes）里的&#8220;MXML Only Tags&#8221;可以查看完整的编译器元素。值得注意的是，这个命名空间并不包含 Halo 和 Spark 组件（Halo是以前版本的组件库，而Spark是Flex 4新出的组件库）。在Flash Builder安装目录下可以找到&#8220;mxml-2009-manifest.xml&#8221;文件（例如我的电脑是C:\Program Files\Adobe\Flash Builder Beta\sdks\4.0.0\frameworks\mxml-2009-manifest.xml），这个xml文件描述了完整的 ActionScript顶级类。不过你可以注意到，它并没有包含MXML编译器标签，那是因为这些标签是内建到MXML编译器。</p>
<p><br /><strong>2、xmlns:mx=&#8221;library://ns.adobe.com/flex/halo&#8221;</strong><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mx命名空间包含着放在 mx.* 包里那些组件，Flex图表、Flex数据可视化组件等等。对Flex 3很熟悉的话，mx包里的组件你也不陌生了。在Flex 4 SDK的安装目录下可以找到&#8220;halo-manifest.xml&#8221;文件（例如我的电脑是C:\Program Files\Adobe\Flash Builder Beta\sdks\4.0.0\frameworks\halo-manifest.xml），这个XML文件列出了所有组件了。</p>
<p><br /><strong>3、xmlns:s=&#8221;library://ns.adobe.com/flex/spark&#8221;</strong><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s命名空间可真是新鲜事了，spark.* 包里的组件都在这个命名空间里，不只spark包，flashx.*包的text framework类也在这个命名空间里。这个命名空间包含不少RPC类，例如 WebService、HTTPService和RemoteObject组件，这些组件同时也在mx命名空间下，也就是说，创建这些组件时，你不但可以使用&#8220;S:&#8221;前缀，也可以使用&#8220;mx:&#8221;前缀。其实不只这些RPC组件共用两个命名空间，像graphics、effect和state类也是共用 s 和 mx 命名空间的。在Flex 4 SDK安装目录下打开spark-manifest.xml文件来看看完整的spark组件吧。</p>
<p><a href="http://www.fengfly.com/plus/view-172216-1.html"></a>&nbsp;</p>
<p>&nbsp;</p><img src ="http://www.cppblog.com/singohgod/aggbug/149595.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/singohgod/" target="_blank">大宝天天见</a> 2011-06-27 18:09 <a href="http://www.cppblog.com/singohgod/archive/2011/06/27/149595.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转载]Flex是咋回事</title><link>http://www.cppblog.com/singohgod/archive/2011/06/27/149591.html</link><dc:creator>大宝天天见</dc:creator><author>大宝天天见</author><pubDate>Mon, 27 Jun 2011 09:58:00 GMT</pubDate><guid>http://www.cppblog.com/singohgod/archive/2011/06/27/149591.html</guid><wfw:comment>http://www.cppblog.com/singohgod/comments/149591.html</wfw:comment><comments>http://www.cppblog.com/singohgod/archive/2011/06/27/149591.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/singohgod/comments/commentRss/149591.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/singohgod/services/trackbacks/149591.html</trackback:ping><description><![CDATA[<p><strong>Flex是咋回事之一 集CS和BS之大成的RIA</strong><br /></p>
<p>用了一年多Flex，感触多多。偶尔有同行的朋友问我啥是Flex，说实话，一时半会儿我还真说不清楚。尤其是对于一个从未接触过Flex的朋友，想要由浅入深地只用嘴巴不用电脑给他讲明白，这确实难为一个整天只跟机器打交道的程序员了。后来我想了一个办法，我说你知道开心农场吧，那就是拿Flex做的。这下子很多人有兴趣了，呵呵，如果你也有兴趣，请继续往下看。失言未察之处，欢迎拍砖。</p>
<p>&nbsp;</p>
<p>一般来说，一项技术的产生都是为了解决业界的重大难题而出现的。那么说到Flex我们就不得不先说一下RIA。RIA这个概念其实早就出现了，我最初是07年在《程序员》杂志上关于Ajax技术的介绍时看到的。到了08年，伴随着网络视频的飞速发展，RIA应用已经搞得有声有色热火朝天了，其实翻译过来就是个富客户端（Rich Internet Application），相较于BS的瘦客户端，也可以称之为胖客户端。当然如果你已经被这些名词概念熏得焦头烂额，请连跳四段（小黑好心提示，本部分仅余四段。。。）。</p>
<p>&nbsp;</p>
<p>RIA简单的说，就是CS+BS的开发部署模式。CS和BS大家都很熟悉，CS的全拼是Client/Server，它的优点在于借助局域网的信息安全和带宽优势，充分利用客户机器的运算能力从而降低服务器压力，缺点就是安装部署更新麻烦，比如老板让我跑到一千公里外的客户那安装一千台机器的客户端，过几天我回来了，老板说那边有几台机器运行有问题，你去维护一下~！过几个月，老板说你去把那一千台机器全部升级一遍，他们自己不会装。。。呵呵，这些痛苦我当然不曾经历，我杜撰的。</p>
<p>&nbsp;</p>
<p>那么在1998年，互联网风起云涌的时候，BS，Browser/Server，逢时而生。BS充分利用互联网的优势，解决了CS安装部署更新的一大难题。通过把业务逻辑处理放在服务器端，然后解析为HTML，利用HTTP协议传输到客户的浏览器上就万事大吉。看起来很美，其实干过就知道也很痛苦。哪儿痛呢，痛的当然是我们这些开发者。安装部署更新倒是省事儿了，装个IE，给个网址就能让客户登录了。但是，基于HTML+JavaScript的技术让人很崩溃。JavaScript我好久不用了，在以前毕业实习的时候，感觉开发和调试都不方便，而且还面临着不同浏览器不兼容的噩梦（据说现在上述问题随着Ajax的风行有所改善，我不太了解）。另外，BS还有一些潜在的缺点。比如，客户端体验简单，不易开发丰富的效果来展示数据（这和当时的网络带宽也有关系）；必须联网才能运行，信息安全无法保障；应用程序需要通过其他技术辅助才能操作客户端资源；服务器负载过高而客户机运算能力未充分使用等。</p>
<p>&nbsp;</p>
<p>综合来讲，BS仍然是一个不错的解决方案，它的Web应用程序和CS的桌面应用程序曾一度二分天下，各领风骚数十年。从解耦角度来看，CS以数据库的方式把数据从程序中分离，BS以浏览器页面的方式把界面和逻辑再次分离，然而第二次分离是不彻底的。表面上只是代码结构的分离，从实质上看表现层仍然是逻辑层的附庸，前台UI完全和后台实现技术绑死（把已有项目后台从C#换成JAVA是不可能的。。。）为了解决这个问题，RIA出现了（顺便搞定了一些其他问题，比如页面异步刷新，前台UI不够丰富等等），RIA基本实现了不依赖于特定后台技术，能与多种服务端搭配使用。</p>
<p>&nbsp;</p>
<p>在2002年，MacroMedia公司（简称MM，05年被Adobe收购）首先在Flash Player6中引入了RIA概念。2004年，MM正式发布Flex1.0（汗，终于说到Flex了），随着Ajax的火爆，RIA开始受到广泛关注。RIA主要有两个方面的含义，一是用户界面的丰富即富客户端，二是数据模型的智能，服务器已经变成了支持客户端正常运行的数据服务，并提供了异步数据传输和脱机缓存机制等复杂的数据处理能力。前面提到，RIA本质上就是CS+BS，它想集大成，想搞总结，想终结CS和BS二分天下的局面。说浅显点就是，如果以前的CS程序现在能在网络上运行，并且保持了原来的功能和特征，那么这就是一个RIA。关于RIA的详细介绍GOOGLE上一搜一大把，在此就不继续作详细展开。回到当下，RIA各种技术一番拼杀，现在广为人知的只剩下四个NB小伙：Ajax、Flex、SilverLight、JavaFx。在本文第二部分中，我将简要介绍一下Flex（貌似进度有点儿慢，多谢支持。。。）</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><strong>Flex是咋回事之二 前世今生</strong>&nbsp;</p>
<p>&nbsp;</p>
<p>先说一下Flash Player（简称FP）。经常上网的朋友一定遇到过Flash Player版本升级的提示吧，这东西其实就是浏览器插件，据说已经有了98%的安装普及率，没办法，谁让咱们这么爱看视频呢（FP具体介绍请见<a href="http://baike.baidu.com/view/1585492.htm">http://baike.baidu.com/view/1585492.htm</a>）。Flex生成的页面主要是通过Html包装一下生成的swf文件，和Flash生成的swf一样，它也靠FP才能完美运行，这有点类似JVM虚拟机和.NET FRAMEWORK（FP里内嵌了AVM虚拟机）。FP又分调试版和产品版，总体来讲，咱们只管用FP提供的API，以及及时关注最新版本的功能，其余不会过多接触（我对FP10关于3D方面的支持很感兴趣，不过貌似其支持效果不太理想）。</p>
<p>&nbsp;</p>
<p>再说一下Flash的历史。在1996年,小软件公司FutureWave Software为了给Netscape开发一个全新的网页浏览插件，创建了名为Future Splash Animator的动态小程序，该产品基于Java，是由一个称为SmartSketch的产品演化而来，这就是Flash的老祖了。具有讽刺意味的是，这家FutureWave的公司本来是打算把这项技术卖给Adobe的，但在那个时候Adobe根本不睬它。而Macromedia（简称MM）却很有兴趣，就这样在1996年11月,MM在拥有了FutureWave这家公司的技术后，把FutureSplash重新命名为Flash Player 1.0。在随后的许多年间，Flash被打包为Studio套件的一部分，并与其他Studio产品（如Dreamweaver和Fireworks）一起发布，世人称网页三剑客。。。三剑客横行无敌，到了05年4月18日这天，ADOBE实在看不下去了，阔绰出手，又以34亿美元天价收购MM。。。ADOBE大叔估计很后悔当年没收购Future Splash，搞到现在，被MM给做大了（Flash具体历史介绍参见<a href="http://flash.9ria.com/viewthread.php?tid=13194">http://flash.9ria.com/viewthread.php?tid=13194</a>和<a href="http://space.flash8.net/space/?625743/viewspace-350122">http://space.flash8.net/space/?625743/viewspace-350122</a>）</p>
<p>&nbsp;</p>
<p>如同今年4月Oracle收购Sun一样，MM嫁入ADOBE豪门，在当时的业界也是一片哗然炸雷。许多MM的忠实粉丝觉得，那三剑客就是被ADOBE大叔招安了啊，依据其收购产品的一贯猥琐恶行，这几位剑侠估计很快就会被不声不响地给整掉了（当时Flex还是襁褓，大家都没注意到。。。）Fireworks是PhotoShop的老对头了，肯定是斩立决；Dreamweaver要不就是改装变身，要不就是各种理由直接缓死；Flash日子会好过些，但其一贯的MM风格是否能延续也很难保证。</p>
<p>&nbsp;</p>
<p>然而ADOBE这次出乎意料的善良，三剑客无一遗弃，相反还忍痛把自己推行多年的SVG死缓（个人也很喜欢SVG，无奈和FLASH冲突，出于商业策略，这孩子被牺牲了）。在最新的CS4（Creative Suite 4）产品系列中，三剑客依然活力四射地与其他成员工具们和谐奋进。那么事隔收购事件四年多之后，我们已经渐渐接受了MM产品前面强行加上的ADOBE标签。可以说，ADOBE充分吸纳整合了MM的精神和风格，无论是FP还是三剑客，ADOBE一直都在努力地做得更好更和谐。（本人现在已经是ADOBE FANS了，哈哈，不过还是挺怀念Flash MX2004 和Dreamweaver2004那个时代的，尽管当时也没闪出啥东西来。。。）</p>
<p>&nbsp;</p>
<p>说了这么多关于Flash的事情，其实是因为Flash比Flex更出名，ADOBE也察觉到这一点，所以在预备推出FLEX4时，又将其更名为Flash，只是SDK仍然沿用FLEX的名号。FLEX和FLASH并没有本质区别，它们最终都是转为ActionScript源文件，然后被编译为二进制的swf文件（就和JAVA文件被编译成class一样），再交由FP（FP就像JVM虚拟机一样）来执行。不同的是，FLASH更偏向于设计人员，它有时间轴和帧的概念，能更好地实现动画、特效、短片等美工效果。Flex是面向开发者的，隐藏了时间轴的概念（只有两帧），更专注于解决企业应用的表现层方案，提供了大量的通用组件用于构建前端页面、通过数据服务技术能更好的分离界面和逻辑业务层。</p>
<p>&nbsp;</p>
<p>从04年3月MM手中的Flex1.0，到05年10月ADOBE手中的Flex2.0，再到07年1月伴随着强大的面向对象语言ActionScript3出现的Flex3.0,再到明年初发布的强力Flex4.0。借着RIA的春风，Flex在不断走向成熟的同时，也被更多的业界开发者和企业用户所关注接受。如果看到这里你很感兴趣，推荐在GOOGLE上搜索一把，现在不是08年了，网上已经涌现出大量的简易教程供我们参考学习。当然如果你有些闲钱，或是想系统地学习一下，也可以买几本书。（有时间我会整理些网站博客和书籍推荐的）</p>
<p>&nbsp;</p>
<p>在本文第三部分中，我将结合项目经验谈一下Flex的优缺点和使用心得。没用过Flex的可能无法共鸣吧，那就直接跳过不看了，呵呵</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><strong>Flex是咋回事之三　谁用谁知道</strong></p>
<p>&nbsp;</p>
<p>一项技术，从概念提出到技术研发到商业发布，再到实际应用，最终将产品呈现在用户面前，这是一个漫长而复杂的过程。在这当中，很多有创意有生命力的技术因为各种原因小小遗憾地不幸夭折了。Flex能走到今天确实不易，下面让我们从不同的角度来看一下它是如何过关斩将，赢得众多青睐的。</p>
<p>&nbsp;</p>
<p>技术角度：</p>
<p>（１）具备了RIA时代富客户端的优点（C/S+B/S）</p>
<p>（２）支持多种服务器语言（JAVA、.NET、PHP）及主流框架（Spring、Hibernate）</p>
<p>（３）与Java结合后相当强大，能充分利用Java的资源背景</p>
<p>（４）拥有丰富的组件和第三方组件，对企业级的数据汇总和业务流程展现力较强悍</p>
<p>（５）借助开源的力量，拥有众多民间组织和牛人支持</p>
<p>（６）Adobe公司（还有MM多年积累）的强大背景</p>
<p>（７）源于Flash的天生丽质，轻松使用多媒体资源，动态交互性强</p>
<p>（８）借助FlashPlayer的安装普及度，轻松实现跨浏览器跨平台</p>
<p>（９）良好的架构设计和制作精良的文档示例（明年FLEX４同步推出中文版）</p>
<p>（１０）借助于插件丰富的Eclipse开发平台并拥有独立的IDE</p>
<p>（１１）框架设计重用性高，有利于模块化设计</p>
<p>（１２）近几年发展态势良好，获得了广泛认可，产品和技术也越发成熟</p>
<p>&nbsp;</p>
<p>开发者角度：</p>
<p>（１）开源，透明（国人没有不喜欢开源的，哈哈）</p>
<p>（２）基于Eclipse开发平台，易上手，且插件丰富（巨人的肩膀啊~）</p>
<p>（３）基于Eclipse平台，开发调试方便(FB4中的条件断点）</p>
<p>（４）ActionScript语言与Java的融合度和相似度较高，易学易用</p>
<p>（５）MXML标签与XML相似，逻辑清晰可读性强</p>
<p>（６）架构设计良好，耦合度低，有利于组件重用</p>
<p>（７）无需针对不同浏览器编写代码，摆脱编写和调试的噩梦（针对JS说的）</p>
<p>（８）类似VB的可视化拖拽组件，快速创建界面</p>
<p>（９）方便定制及使用第三方的皮肤和样式，无需美工也有好效果</p>
<p>（１０）支持多媒体资源，轻易开发动态交互性强的界面</p>
<p>（１１）众多的RPC组件保障对后台数据访问的安全性和效率</p>
<p>（１２）文档示例丰富，通过网络可以获取大量的学习资源</p>
<p>（１３）近两年发展态势良好，前景光明</p>
<p>&nbsp;</p>
<p>企业角度：</p>
<p>（１）开源，免费（其实很多时候还是直接用破解的。。。）</p>
<p>（２）具备了RIA时代富客户端的优点（C/S+B/S）（潮流啊~！）</p>
<p>（３）项目和组件的重用性高，易于资源积累和快速构建</p>
<p>（４）Flex提供了与其他语言的结合，能广泛利用已有的资源</p>
<p>（５）界面华丽，客户认可度高</p>
<p>（６）学习曲线一般，培训成本低</p>
<p>&nbsp;</p>
<p>用户角度：</p>
<p>（１）部署和更新方便</p>
<p>（２）界面漂亮，交互性强</p>
<p>（３）安全</p>
<p>&nbsp;</p>
<p>说了这么多好话，再来综合说一下缺点。鉴于我着迷于Flex的光环效应，没有看到的缺点还请诸位多多提出。</p>
<p>缺点：</p>
<p>（１）不擅长处理复杂的业务流程，主要还是适合展现（Flex不是万能的）</p>
<p>（２）继承了Flash的诸多优点，却唯独丢掉了Flash的小巧轻盈（减肥是永恒的话题）</p>
<p>（３）目前尚没有比较好的减肥策略，带宽较好时这不是问题（不是一般的卡。。。）</p>
<p>（４）对服务器和客户端的硬件设备都有一定要求（CPU和内存占用很生猛。。。）</p>
<p>（５）运行期内存泄露状况严重，尽管可以通过一定手段改善（这个很崩溃）</p>
<p>（６）对一些较专业的领域涉及较少，需要第三方组件支持（比如地质方面的）</p>
<p>（７）Adobe公司对中国分部的支持不够（感觉宣讲和文档都做得不够）</p>
<p>（８）搜索引擎对swf文件的支持不够（Adobe一直在努力）</p>
<p>（９）与以往浏览习惯不同，比如右键被屏蔽，图片无法保存（可以改善）</p>
<p>&nbsp;</p>
<p>鉴于Flex生成的swf文件太肥是其主要缺点（加载慢，运行慢，内存占用多），我就主要从减肥和优化的角度来说一下使用心得。</p>
<p>使用心得：</p>
<p>（１）Flex只是前台展现，需要搭配强大的后台（注意前后台的均衡和优化）</p>
<p>（２）考虑异步加载（比如分步加载外部资源）</p>
<p>（３）界面推荐使用相对布局，合理组合，避免多余嵌套</p>
<p>（４）界面加载图片推荐使用外部加载方式，尽可能多使用矢量图形</p>
<p>（５）规范CSS样式表，尤其注意使用的外部字体大小</p>
<p>（６）使用额外的皮肤和特效时需要综合考虑生成的文件大小和执行效率</p>
<p>（７）适当地考虑延时加载策略，主界面只显示必要的内容</p>
<p>（８）规范编码，提高执行效率，避免内存泄露</p>
<p>（９）使用RSL和Module和其他有效方式努力减肥</p>
<p>（１０）尽可能重写一些继承底层类的组件，执行效率更好</p>
<p>（１１）慎重使用重量级组件（比如DataGrid，AdvancedDataGrid）</p>
<p>&nbsp;</p>
<p>原文来自：雨枫技术教程网 <a href="http://www.fengfly.com">http://www.fengfly.com</a><br /></p><img src ="http://www.cppblog.com/singohgod/aggbug/149591.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/singohgod/" target="_blank">大宝天天见</a> 2011-06-27 17:58 <a href="http://www.cppblog.com/singohgod/archive/2011/06/27/149591.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转载]Linux API 网址转换(DWORD, IP,域名)</title><link>http://www.cppblog.com/singohgod/archive/2011/06/27/149588.html</link><dc:creator>大宝天天见</dc:creator><author>大宝天天见</author><pubDate>Mon, 27 Jun 2011 09:46:00 GMT</pubDate><guid>http://www.cppblog.com/singohgod/archive/2011/06/27/149588.html</guid><wfw:comment>http://www.cppblog.com/singohgod/comments/149588.html</wfw:comment><comments>http://www.cppblog.com/singohgod/archive/2011/06/27/149588.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/singohgod/comments/commentRss/149588.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/singohgod/services/trackbacks/149588.html</trackback:ping><description><![CDATA[<span class="Apple-style-span" style="word-spacing: 0px; font: medium Simsun; text-transform: none; color: rgb(0,0,0); text-indent: 0px; white-space: normal; letter-spacing: normal; border-collapse: separate; orphans: 2; widows: 2; webkit-border-horizontal-spacing: 0px; webkit-border-vertical-spacing: 0px; webkit-text-decorations-in-effect: none; webkit-text-size-adjust: auto; webkit-text-stroke-width: 0px"><span class="Apple-style-span" style="font-size: 14px; line-height: 21px; font-family: verdana, sans-serif; text-align: left"> 
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 0px; margin: 1em 0px 0.5em; padding-top: 0px"><br /><br />做网络模块的时候经常会遇到有关网址的处理.一般大致的情形是3种:</p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 0px; margin: 1em 0px 0.5em; padding-top: 0px">1.得到的是域名,如:www.3322.org</p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 0px; margin: 1em 0px 0.5em; padding-top: 0px">2.得到的是实际的IP地址,如:61.160.235.203</p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 0px; margin: 1em 0px 0.5em; padding-top: 0px">3.得到的是经过inet_addr处理过的IP,为unsigned long(DWORD)</p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 0px; margin: 1em 0px 0.5em; padding-top: 0px">一.那么如果是给出点分制的IP要转为DWORD型是如何转化呢?这个其实最简单,有专门的函数专门处理此事</p><pre><span style="color: rgb(0,0,255)">unsigned</span> <span style="color: rgb(0,0,255)">long</span> dwIP = inet_addr("<span style="color: rgb(139,0,0)">222.212.12.77</span>");
<span style="color: rgb(0,0,255)">printf</span>("<span style="color: rgb(139,0,0)">IP(%s)-&gt;DWORD(%lu)\n</span>");

<span style="color: rgb(0,128,0)">//output</span>
IP(222.212.12.77)-&gt;DWORD(1292686558)</pre>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 0px; margin: 1em 0px 0.5em; padding-top: 0px">二.第一种情况的逆转化</p><pre>#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;sys/select.h&gt;
#include &lt;netdb.h&gt;
#include &lt;sys/socket.h&gt;
#include &lt;netinet/in.h&gt;
#include &lt;arpa/inet.h&gt;
#include &lt;errno.h&gt;
#include &lt;string.h&gt;

<span style="color: rgb(0,0,255)">int</span> main(<span style="color: rgb(0,0,255)">int</span> argc, <span style="color: rgb(0,0,255)">char</span> *argv[])
{
	<span style="color: rgb(0,0,255)">struct</span> in_addr net;
	<span style="color: rgb(0,0,255)">char</span> tmp[16] = {0};

	<span style="color: rgb(0,0,255)">if</span>(argc != 3)
	{
		<span style="color: rgb(0,0,255)">printf</span>("<span style="color: rgb(139,0,0)">You MUST enter 3 varibal.No.1:func name No.2:case.No.3:ip(string or DWORD)\n</span>");
		<span style="color: rgb(0,0,255)">return</span> 0;
	}

	<span style="color: rgb(0,0,255)">if</span>(<span style="color: rgb(0,0,255)">strcmp</span>("<span style="color: rgb(139,0,0)">1</span>", argv[1]) == 0) 
	{
		<span style="color: rgb(0,0,255)">char</span>* ip_string;
		ip_string = argv[2];
		<span style="color: rgb(0,0,255)">unsigned</span> <span style="color: rgb(0,0,255)">long</span> dword = inet_addr(ip_string);

		<span style="color: rgb(0,0,255)">printf</span>("<span style="color: rgb(139,0,0)">IP(%s)--&gt;DWORD(%lu)\n</span>", ip_string, dword);
	}
	<span style="color: rgb(0,0,255)">else</span> <span style="color: rgb(0,0,255)">if</span>(<span style="color: rgb(0,0,255)">strcmp</span>("<span style="color: rgb(139,0,0)">2</span>", argv[1]) == 0)
	{
		net.s_addr = (<span style="color: rgb(0,0,255)">unsigned</span> <span style="color: rgb(0,0,255)">long</span>)<span style="color: rgb(0,0,255)">atol</span>(argv[2]);
		<span style="color: rgb(0,0,255)">strcpy</span>(tmp, inet_ntoa(net));
		<span style="color: rgb(0,0,255)">printf</span>("<span style="color: rgb(139,0,0)">DWORD(%s)--&gt;IP(%s)\n</span>",argv[2], tmp);
	}
	<span style="color: rgb(0,0,255)">return</span> 0;
}</pre><pre>这里给出一个点分制IP和DWORD相互转化的程序</pre><pre>三.如果给出的是域名而想得到点分制的IP呢?</pre><pre>这里给出一个接口,支持输入的类型是点分制和域名2中类型,返回的是DWORD型的IP</pre><pre>有一点要声明的是gethostbyname这个函数必须在网络连通的情况下才能正确完成域名的解析,你想,连个网都不通,它怎么解析?</pre><pre>#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;sys/select.h&gt;
#include &lt;netdb.h&gt;
#include &lt;sys/socket.h&gt;
#include &lt;netinet/in.h&gt;
#include &lt;arpa/inet.h&gt;
#include &lt;errno.h&gt;
#include &lt;string.h&gt;


#define DWORD <span style="color: rgb(0,0,255)">unsigned</span> <span style="color: rgb(0,0,255)">long</span>

DWORD platform_domain2ip(<span style="color: rgb(0,0,255)">const</span> <span style="color: rgb(0,0,255)">char</span> *szDomain, <span style="color: rgb(0,0,255)">char</span> *szDotNumIP)
{
	<span style="color: rgb(0,0,255)">char</span> szAddr[32] = {0};
	<span style="color: rgb(0,0,255)">struct</span> hostent *pHost;

	<span style="color: rgb(0,0,255)">printf</span>("<span style="color: rgb(139,0,0)">input domain name(%s)\n</span>", szDomain);
	

	<span style="color: rgb(0,0,255)">if</span>((pHost = gethostbyname(szDomain)) == NULL)
	{
		<span style="color: rgb(0,0,255)">printf</span>("<span style="color: rgb(139,0,0)">can not parse domain\n</span>");
		<span style="color: rgb(0,0,255)">return</span> -1;
	}
	<span style="color: rgb(0,0,255)">printf</span>("<span style="color: rgb(139,0,0)">HostName :%s\n</span>",pHost-&gt;h_name);
	<span style="color: rgb(0,0,255)">strcpy</span>(szAddr, inet_ntoa(*((<span style="color: rgb(0,0,255)">struct</span> in_addr *)pHost-&gt;h_addr)));
	<span style="color: rgb(0,0,255)">printf</span>("<span style="color: rgb(139,0,0)">IP Address :%s\n</span>", szAddr);
	<span style="color: rgb(0,0,255)">strcpy</span>(szDotNumIP, szAddr);

	<span style="color: rgb(0,0,255)">return</span> inet_addr(szAddr);
}

<span style="color: rgb(0,0,255)">int</span> main(<span style="color: rgb(0,0,255)">int</span> argc, <span style="color: rgb(0,0,255)">char</span> *argv[])
{
	DWORD dwip;
	<span style="color: rgb(0,0,255)">char</span> *ip = <span style="color: rgb(0,0,255)">malloc</span>(32);
	<span style="color: rgb(0,128,0)">//dwip = platform_domain2ip("www.3322.org", ip);</span>
	dwip = platform_domain2ip("<span style="color: rgb(139,0,0)">61.160.235.203</span>", ip);
	<span style="color: rgb(0,0,255)">printf</span>("<span style="color: rgb(139,0,0)">ip 1 (%s) 2 dw(%lu)\n</span>", ip, dwip);
	<span style="color: rgb(0,0,255)">return</span> 0;
}</pre><pre>//可以将main的注册分别打开来判断下结果是否正确,这里给出运行的结果,有图有真相</pre><pre>编译的命令再说下吧,怕有人不知道</pre><pre>gcc gethost.c &#8211;Wall &#8211;o gethost//在linux下</pre><pre>arm-hismall-linux-gcc gethost.c &#8211;Wall &#8211;o gethost//嵌入式环境下</pre><pre>&nbsp;<img alt="" src="http://www.cppblog.com/images/cppblog_com/singohgod/1.gif" border="0" /></pre><pre></pre><pre><img alt="" src="http://www.cppblog.com/images/cppblog_com/singohgod/2.gif" border="0" /></pre><pre><img alt="" src="http://www.cppblog.com/images/cppblog_com/singohgod/3.gif" border="0" /></pre><pre>此接口已经在我的工程中使用,在平台IP的解析和3322的解析中得到了应用,所以是稳定可行的.</pre><pre>这3中IP的转化都了解了的话,那么网络编程不就扫除了一个大石头吗?呵呵,大家功能进步</pre><pre>&nbsp;</pre><pre>网上比较流行的gethostbyname的例子如下,受到了启发</pre><pre>#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;sys/select.h&gt;
#include &lt;netdb.h&gt;
#include &lt;sys/socket.h&gt;
#include &lt;netinet/in.h&gt;
#include &lt;arpa/inet.h&gt;
#include &lt;errno.h&gt;
#include &lt;string.h&gt;

<span style="color: rgb(0,0,255)">int</span> main(<span style="color: rgb(0,0,255)">int</span> argc, <span style="color: rgb(0,0,255)">char</span> **argv)
{
    <span style="color: rgb(0,0,255)">char</span> *ptr,**pptr;
    <span style="color: rgb(0,0,255)">struct</span> hostent *hptr;
    <span style="color: rgb(0,0,255)">char</span> str[32];

<span style="color: rgb(0,128,0)">    /* 取得命令后第一个参数，即要解析的域名或主机名 */</span> 
    ptr = argv[1];

<span style="color: rgb(0,128,0)">    /* 调用gethostbyname()。调用结果都存在hptr中 */</span> 
    <span style="color: rgb(0,0,255)">if</span>((hptr = gethostbyname(ptr)) == NULL)
    {
        <span style="color: rgb(0,0,255)">printf</span>("<span style="color: rgb(139,0,0)">gethostbyname error for host:%s\n</span>", ptr);
        <span style="color: rgb(0,0,255)">return</span> 1; /* 如果调用gethostbyname发生错误，返回1 */
    }

<span style="color: rgb(0,128,0)">    </span> 
    <span style="color: rgb(0,0,255)">printf</span>("<span style="color: rgb(139,0,0)">official hostname:%s\n</span>",hptr-&gt;h_name);

<span style="color: rgb(0,128,0)">    /* 主机可能有多个别名，将所有别名分别打出来 */</span> 
    <span style="color: rgb(0,0,255)">for</span>(pptr = hptr-&gt;h_aliases; *pptr != NULL; pptr++)
        <span style="color: rgb(0,0,255)">printf</span>("<span style="color: rgb(139,0,0)">  alias:%s\n</span>",*pptr);

    <span style="color: rgb(0,128,0)">/* 根据地址类型，将地址打出来 */</span>
    <span style="color: rgb(0,0,255)">switch</span>(hptr-&gt;h_addrtype)
    {
        <span style="color: rgb(0,0,255)">case</span> AF_INET:
        <span style="color: rgb(0,0,255)">case</span> AF_INET6:
            pptr=hptr-&gt;h_addr_list;

            <span style="color: rgb(0,128,0)">/* 将刚才得到的所有地址都打出来。其中调用了inet_ntop()函数*/</span>
            <span style="color: rgb(0,0,255)">for</span>(;*pptr!=NULL;pptr++)
            <span style="color: rgb(0,0,255)">printf</span>("<span style="color: rgb(139,0,0)">  address:%s\n</span>", inet_ntop(hptr-&gt;h_addrtype,*pptr, str, <span style="color: rgb(0,0,255)">sizeof</span>(str)));
        <span style="color: rgb(0,0,255)">break</span>;
        <span style="color: rgb(0,0,255)">default</span>:
            <span style="color: rgb(0,0,255)">printf</span>("<span style="color: rgb(139,0,0)">unknown address type\n</span>");
        <span style="color: rgb(0,0,255)">break</span>;
    }

    <span style="color: rgb(0,0,255)">return</span> 0;
}</pre></span></span><br class="Apple-interchange-newline" /><img src ="http://www.cppblog.com/singohgod/aggbug/149588.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/singohgod/" target="_blank">大宝天天见</a> 2011-06-27 17:46 <a href="http://www.cppblog.com/singohgod/archive/2011/06/27/149588.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转载]linux下C++开发工具</title><link>http://www.cppblog.com/singohgod/archive/2011/05/08/145950.html</link><dc:creator>大宝天天见</dc:creator><author>大宝天天见</author><pubDate>Sun, 08 May 2011 07:18:00 GMT</pubDate><guid>http://www.cppblog.com/singohgod/archive/2011/05/08/145950.html</guid><wfw:comment>http://www.cppblog.com/singohgod/comments/145950.html</wfw:comment><comments>http://www.cppblog.com/singohgod/archive/2011/05/08/145950.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/singohgod/comments/commentRss/145950.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/singohgod/services/trackbacks/145950.html</trackback:ping><description><![CDATA[<div style="background-color: rgb(238, 238, 238); font-size: 13px; border-left-color: rgb(204, 204, 204); padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; "><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000; ">就C＋＋开发工具而言，与Windows下微软（VC，&nbsp;VS2005等）一统天下相比，Linux</span><span style="color: #000000; ">/</span><span style="color: #000000; ">Unix下C＋＋开发，可谓五花八门，各式各样。Emacs,&nbsp;vi,&nbsp;eclipse,&nbsp;anjuta，kdevelop等层出不穷。<br>Windows下，开发工具多以集成开发环境IDE的形式展现给最终用户。例如，VS2005集成了编辑器，宏汇编ml，C&nbsp;</span><span style="color: #000000; ">/</span><span style="color: #000000; ">C</span><span style="color: #000000; ">++</span><span style="color: #000000; ">编译器cl，资源编译器rc，调试器，文档生成工具,&nbsp;nmake。它们以集成方式提供给最终用户，对于初学者而言十分方便。但是，这种商业模式，直接导致用户可定制性差，不利于自动化，集成第三方工具的能力弱。例如，无法定制一些宏来处理一些重复操作；体会不到自动化makefile一步到位快感；无法远程登录到服务器上进行开发；无法使用某种&#8221;粘合剂&#8221;来把第三方工具（例如，文本工具，字符串工具）有效地调用起来。可以说，良好的商业支持和傻瓜式开发，是它们主要的优点。<br>在linux下，开发工具被切割成一个个独立的小工具。各自处理不同的问题。例如，编辑器（emacs,&nbsp;vim)用来进行编辑程序的，调试器（gdb)用来调试程序，编译器（GCC）用来编译和链接程序的，性能分析工具（gcov,&nbsp;gprof)用来优化程序的，文档生成器（doxygen）用来生成文档的。同时，还有一些系统工具和系统知识，我们是很有必要了解的：程序自动化机制&nbsp;makefile，系统粘合剂shell，系统查找工具grep,&nbsp;locate,&nbsp;find。其它的工具（例如ctags，&nbsp;OCI公司的MPC等等），一旦熟练掌握，它们将成为你手中的利器。<br>本文主要是一些针对LINUX下开发工具使用的经验之谈。由于，工具品种繁多，我们没有能力也没有必要一一介绍。对于LINUX下IDE工具，例如&nbsp;eclipse,&nbsp;anjuta等，它们虽然也很实用，但是使用起来比较简单，而且目前还算不上主流。所以，它们将不被着重介绍。同时，本文也不打算写成各个工具的操作手册，只着眼于介绍各个工具的想要解决的问题、运行机理和主要特性。<br>正文<br>编辑器<br>要进行开发，第一件事情就是选择一个合适的编辑器。编辑器选择有几个要素：<br></span><span style="color: #000000; ">1</span><span style="color: #000000; ">）减少不必要的编辑动作，减少编辑的时间。<br>一切能够无二义性描述出来的编辑任务，都可以而且应该能被自动化。例如，每一个C＋＋程序都会有一个main函数；我们在定义.h文件时，都希望加入一些预处理指令＃define来帮我们解决重复引用同一个头文件而带来的麻烦。鼠标操作总是比键盘操作要慢的。这方面EMACS做得可算是到了极致。所以，&nbsp;EMACS用户经常会吹嘘：他们编辑的速度等同于他们思考的速度。<br></span><span style="color: #000000; ">2</span><span style="color: #000000; ">）可扩展性高。<br>程序员预期的编辑器应该能提供一些编程的帮助，例如，语法高亮，自动补齐，自动排版，语法检查等等。留心观察一下gedit,&nbsp;vim,&nbsp;emacs,&nbsp;ultraEdit，就会发现它们提供的远不是windows&nbsp;记事本，写字板提供的那么简陋的功能。对于一种新的语言，新的语法，它们应该能很方便地提供支持，而不停留在一种或几种固定的语言上。<br></span><span style="color: #000000; ">3</span><span style="color: #000000; ">）用户可定制性高。<br>如果想长期从事研发，&nbsp;特别是linux</span><span style="color: #000000; ">/</span><span style="color: #000000; ">unix下研发的话，那么你很有必要学好一个功能足够的编辑器。有这么一句话：Linux下程序员分为三种，使用emacs的，使用vi的，还有其它。<br>EMACS是Stallman用lisp语言写的一个GPL的编辑器。我们这里所说的emacs指的是GNU&nbsp;emacs，而非Xemacs。由于它的开放性，我们可以把它打造成一个功能强大的IDE。我们在安装好CGYwin之后，也可以在Windows系统下使用&nbsp;EMACS。CGYwin和MINGW是第三方写的一个在Windows系统上模拟POSIX系统的工具。<br>EMACS与其说的是一个编辑器，倒不如说它是一个操作系统。我们可以用它来写编程，写wiki，收发邮件等等。EMACS主要是通过两种方式来进行扩展：el脚本(elisp是lisp的一种方言）和第三方扩展包。EMACS的入门成本很高。由于是纯键盘操作，所以需要记忆大量的快捷键；功能强大是通过用户添加一些扩展包，lisp脚本来实现的。如何正确配置和修改是很需要耐心和技巧的。<br>编译器<br>编译器首选GCC（GNU&nbsp;COMPILER&nbsp;COLLECTION)。原因有两个，它是GNU开源的，同时它对标准C</span><span style="color: #000000; ">++</span><span style="color: #000000; ">的支持度高达96.</span><span style="color: #000000; ">15</span><span style="color: #000000; ">%</span><span style="color: #000000; ">。而VC</span><span style="color: #000000; ">++</span><span style="color: #000000; ">6</span><span style="color: #000000; ">.0的支持度只有83.</span><span style="color: #000000; ">43</span><span style="color: #000000; ">%</span><span style="color: #000000; ">。&nbsp;GCC不仅是通常意义上的C或C</span><span style="color: #000000; ">++</span><span style="color: #000000; ">的编译器，它还可以编译java等其它语言。gcc是gnu&nbsp;c的编译器,g</span><span style="color: #000000; ">++</span><span style="color: #000000; ">是gnu&nbsp;c</span><span style="color: #000000; ">++</span><span style="color: #000000; ">的编译器,&nbsp;而EGCS(Enhanced&nbsp;GNU&nbsp;Compiler&nbsp;Suite)可以认为是gcc的改进版。<br>编译语言从源程序到目标代码会经过如下几个阶段：源程序－＞汇编程序－＞编译成obj程序－</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">链接成最终可执行程序。我们可以通过一条编译指令来完成所有步骤。也可以分步执行。gcc有三个重要选项</span><span style="color: #000000; ">-</span><span style="color: #000000; ">E(只进行预处理),&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">S(生成汇编代码),&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">g(生成带原代码调试符号的可执行文件，如果想用gdb调试的话，就应该在编译时打开这个选项）。<br>GCC可以看作一个软件包，除了编译工具，它还集成了调试器gdb，性能分析工具gcov,&nbsp;gprof。只要我们装好了GCC，这些强大工具就可以直接使用了。<br>通过gcov，我们可以查看一个程序，源代码中每行代码的运行次数。我们优化运行次数最多的代码，那么就可以大大优化程序。使用gcov时，需要打开&nbsp;GCC的fprofile</span><span style="color: #000000; ">-</span><span style="color: #000000; ">arcs和ftest</span><span style="color: #000000; ">-</span><span style="color: #000000; ">coverage两个选项。gcov中常用的选项有</span><span style="color: #000000; ">-</span><span style="color: #000000; ">b分支统计信息。<br>通过gprof工具，我们可以查看函数之间的调用顺序，及各个函数运行的时间。我们可以将gprof理解为linux</span><span style="color: #000000; ">/</span><span style="color: #000000; ">unix自带工具time的加强版。使用gprof时，需要打开GCC的pg选项。<br>gcov和&nbsp;gprof的共同点是在编译程序时，加入自己的一些辅助信息，由此来进行程序诊断。除了，这些优化手段，我们还可以使用一些内存泄漏工具，来减少野指针，未释放的内存空间。<br>调试器<br>GDB即GNU的调试器，它是GCC附带的一个性能优质的调试器。通过GDB和脚本结合，我们可以很好的实现回归测试。<br>GDB可以运行于CLI和GUI两种模式。默认GDB是CLI模式的，我们可以去下载和安装GUI模式的GDB，例如xxgdb，&nbsp;ddd等。一个更好的方式是在&nbsp;EMACS中使用GDB。GDB包括visual&nbsp;studio工具的所有调试功能，还包括它没有的功能。它除了支持，我们一般的设置断点，单步跟踪，step&nbsp;</span><span style="color: #0000FF; ">in</span><span style="color: #000000; ">,&nbsp;step&nbsp;</span><span style="color: #0000FF; ">out</span><span style="color: #000000; ">,&nbsp;step&nbsp;over等，还有一些强大的功能。在gdb中，我们可以有以下几种暂停方式：断点（BreakPoint）、观察点（WatchPoint）、捕捉点（CatchPoint）、信号（Signals）、线程停止（Thread&nbsp;Stops）。<br>下面列举几个让我印象深刻的功能。</span><span style="color: #000000; ">1</span><span style="color: #000000; ">）通过&nbsp;watch指令，可以让程序在某个变量的值发生变化时，暂停下来。</span><span style="color: #000000; ">2</span><span style="color: #000000; ">）通过print指令，在程序运行时，设置变量的值，运行一个程序自身支持的一个方法。</span><span style="color: #000000; ">3</span><span style="color: #000000; ">）通过until指令，我们可以让程序在运行到某个程序时暂停下来。</span><span style="color: #000000; ">4</span><span style="color: #000000; ">）通过break..&nbsp;if指令，使得程序在满足某个bool表达式时，暂停下来。<br>粘合剂<br>我想通过&#8220;粘合剂&#8221;这个词来表达将多个工具粘合起来的&#8220;胶水&#8221;。例如，通过shell脚本，我们可以把OS命令，sed指令，awk指令，其它脚本文件等串联起来，发挥它们的合力。在linux&nbsp;C</span><span style="color: #000000; ">++</span><span style="color: #000000; ">编程中，我们不可避免地会使用makefile文件。通过，它我们可以把编译指令，生成文档操作，清除操作等等串联起来。从某种意义上来看，它也相当于一个粘合剂。<br>makefile的出发点是，维护好一个项目中众多文件的依赖关系，由此得到一个源程序的拓扑图。当我们只修改图中某个结点时，重新编译时就只需要将拓扑图中关联的链路进行编译就好了。由此，大大缩短了编译的时间。make有两大概念：dependencies和rules。规则rule即针对每一个依赖关系&nbsp;dependency定义一个操作规则。这个细粒度的分离，就可以使我们可以定制软件构建的行为。例如，修改使用的编译器，修改includepath,&nbsp;修改libpath,&nbsp;修改编译选项等等。我们常见的VC中的nmake，功能和make是类似的。<br>make使用的重点和难点是编写Makefile文件。Makefile的语法相对其它语言来说是很不一样的，我们要特别注意TAB键和空格键的区别。有很多工具可以用来帮助我们生成Makefile。最出名的就是GNU的autoconf了。一个GNU程序的编写，需要autoscan,&nbsp;aclocal,&nbsp;autoconf,&nbsp;automake这四个工具。<br>我们知道GNU软件安装的三步曲是：.</span><span style="color: #000000; ">/</span><span style="color: #000000; ">configure,&nbsp;make,&nbsp;make&nbsp;install。其中.</span><span style="color: #000000; ">/</span><span style="color: #000000; ">configure就是根据autoconf,&nbsp;alocal等工具生成一个makefile文件。make指令就是调用make指令来根据makefile文件的规则来编译源程序。而make&nbsp;install就是执行makefile中的install规则指出的操作（一般是copy操作）。而make&nbsp;clean就是执行makefile中的clean规则指出的操作（一般是rm操作）。我们用Eclispe</span><span style="color: #000000; ">+</span><span style="color: #000000; ">CDT开发Managed&nbsp;C</span><span style="color: #000000; ">++</span><span style="color: #000000; ">&nbsp;Project时，它就是通过objects.mk,subdir.mk,sources.mk三个文件来生成Makefile。我们注意观察编译时的输出信息，就可以看到显示的Makefile文件的内容。<br>可以说，如果想编译出跨平台的C＋＋程序，那么makefile是一种最方便的机制。<br>OCI公司为Douglas&nbsp;C.Schmidt的ACE，TAO开源社区编写了一段伟大的perl脚本－－MPC。它由平台信息，一个规则文件，源代码，生成用户想要的工程文件，例如Make,&nbsp;Nmake,&nbsp;Visual&nbsp;C</span><span style="color: #000000; ">++</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">6</span><span style="color: #000000; ">,&nbsp;Visual&nbsp;C</span><span style="color: #000000; ">++</span><span style="color: #000000; ">&nbsp;7等等。Google&nbsp;Web&nbsp;Tookit,&nbsp;Celtix做的事情与之类似，不过它们是针对JAVA的，而MPC是针对C＋＋的。<br>结束语<br>国内资料太多的低层次的重复，经常是一个网页被多次转载，而且回答问题时深度不够。个人找资料的顺序是：查看quick&nbsp;start或how&nbsp;to文档－＞自带的帮助（如果看起来不太吃力话）－＞百度查一下中文网页，来理清一下基本概念－＞google查一下－＞几个大的，相关的网站查下资料－＞看自带帮助。再者，面对面的交流是十分重要的，大家可以相互理一下概念，交流一下心得。可惜，我身边这种氛围还是不够。<br>Linux下开发还可以更友好一些。个人感觉，&nbsp;linux开发要在国内普通程序员中大规模普及，还有一段很长的路要走。ubuntu火爆的主要原因，就是它帮用户搭好一些默认配置。用户如果想新加一些服务，它们提供了良好，有效地支持。所以，我想我们可以在IDE和现在linux这种一个个小部件的这两种状态之间，取一个折衷。也就是针对几种主要需求的用户，发布一些配置好的环境。尤其是emacs的各种el脚本（例如界面主题的color</span><span style="color: #000000; ">-</span><span style="color: #000000; ">theme，&nbsp;C</span><span style="color: #000000; ">/</span><span style="color: #000000; ">C</span><span style="color: #000000; ">++</span><span style="color: #000000; ">语言编辑策略，代码样式设置脚本，各种emacs系统设置），&nbsp;第三方扩展包（模板template,&nbsp;编程支持包cedet等）。每一个用户浪费时间来进行这些配置是十分没有意义的！工具始终只是工具，我们不能沦为工具的奴隶，不能把一大部分精力浪费在配置工具上。<br>值得注意的是现在方兴未艾的eclipse有向这方面迈进的趋势。但是，现在emacs已经做得很好了，ecilpse能否超越它，我们还有待观察。我们可以通过在eclipse上安装SDT插件来进行C</span><span style="color: #000000; ">++</span><span style="color: #000000; ">开发。但是，它目前还不支持调试功能，而且不太稳定，功能不够强。例如，有时会无故死掉；如果想通过eclipse来转向函数原型的话，那么迎接你的将是一个漫长、焦急的等待。<br>由于本人缺少在linux下进行实际大规模程序的开发经验，对很多工具和机制的理解还比较肤浅。对它们的熟悉程度离真正实用，还有一段很长的路要走。<br>我之前是一个C程序员，而且是个Windows的程序员，在windows下使用VC6.</span><span style="color: #000000; ">0</span><span style="color: #000000; ">/</span><span style="color: #000000; ">VS2005等microsoft的傻瓜式工具工作，&nbsp;对于那个vc&nbsp;</span><span style="color: #000000; ">6.0</span><span style="color: #000000; ">/</span><span style="color: #000000; ">vs2005的快捷操作，debug操作是那么的熟悉，可以说vc&nbsp;</span><span style="color: #000000; ">6.0</span><span style="color: #000000; ">/</span><span style="color: #000000; ">vs2005是window下开发c</span><span style="color: #000000; ">/</span><span style="color: #000000; ">c</span><span style="color: #000000; ">++</span><span style="color: #000000; ">最好用的工具了，可以查看调用堆栈，内存变化情况，变量值，另外安装&nbsp;visual&nbsp;assist&nbsp;x后让VC看起来是那么的完美。<br>但是windows下写成代码到了linux下是有问题的，所以建议在vc中将工具</span><span style="color: #000000; ">-</span><span style="color: #000000; ">》选项—》制表符—》制表符大小4，插入空格，另外的问题就是&nbsp;那个回车换行的问题，例如windows下是0d,0a，到了linux下用vi看到的都是</span><span style="color: #000000; ">^</span><span style="color: #000000; ">M，给别人带来不便，所以如果提交的服务器是linux，而&nbsp;你是在windows下开发，可以在svn</span><span style="color: #000000; ">/</span><span style="color: #000000; ">cvs中进行设置，就可以自动进行dos2unix的转换，相关的文档可以查看svn</span><span style="color: #000000; ">/</span><span style="color: #000000; ">cvs的相关手册，其&nbsp;中都有这样的设置。<br>有幸这次我转到了Linux下开发，有幸认识了linux，但是随之而来的就是特别头疼的问题：Linux下使用什么工具进行编码，编译，&nbsp;debug呢？？我感到非常的迷茫，然后就是网上大搜索，看到那么多的网友推荐VIM时，我失望了，特别的失望，然后用VIM敲了一个下午，累的手的麻&nbsp;了，感到特别的不爽，就像是用左手拿筷子一样，全身的力量无法施展，所以&nbsp;我还是计划再找找看。不过后来我还是找到了适合自己的工具。呵呵，真是太高兴了，今天把我自己这几天搜集的一些资料整理一下，给以后转向linux的程序&nbsp;员一点提示吧</span><span style="color: #000000; ">!</span><span style="color: #000000; "><br>主要的工具如下：<br></span><span style="color: #000000; ">1</span><span style="color: #000000; ">.&nbsp;vim&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;ctags&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;taglist&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;cscope&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;cppcomplete&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;global<br>这个我也试过了，比较有用的帖子如下：<br>http:</span><span style="color: #008000; ">//</span><span style="color: #008000; ">www.linuxsir.org/bbs/showthread.php?t=241578</span><span style="color: #008000; "><br></span><span style="color: #000000; ">http:</span><span style="color: #008000; ">//</span><span style="color: #008000; ">blog.csdn.net/wooin/archive/2007/10/31/1858917.aspx</span><span style="color: #008000; "><br></span><span style="color: #000000; ">但是这个要记大量的命令，不过还好，这些命令有两三天就可以记住了，<br>我这里有个简单的册子：<br></span><span style="color: #000000; ">2</span><span style="color: #000000; ">、文本的操作<br></span><span style="color: #000000; ">~</span><span style="color: #000000; "><br>:e</span><span style="color: #000000; ">!</span><span style="color: #000000; ">&nbsp;file1&nbsp;在当前文件下编辑新的文件<br>:r&nbsp;</span><span style="color: #000000; ">/</span><span style="color: #000000; ">etc</span><span style="color: #000000; ">/</span><span style="color: #000000; ">passwd&nbsp;实现文件的读入功能<br>:wq&nbsp;保持并退出<br>:q</span><span style="color: #000000; ">!</span><span style="color: #000000; ">&nbsp;强行退出<br>O&nbsp;：重起一行<br>U：撤销&nbsp;：&nbsp;C</span><span style="color: #000000; ">-</span><span style="color: #000000; ">R&nbsp;：重做<br>dd&nbsp;删除一行&nbsp;d$删除行后的<br>e:移动单词&nbsp;ge&nbsp;</span><span style="color: #000000; ">?</span><span style="color: #000000; ">—&#8211;&nbsp;&#8211;&#224;&nbsp;e<br></span><span style="color: #000000; ">%</span><span style="color: #000000; ">:括号匹配<br>33G：跳到33行<br>gg&nbsp;:跳到第一行<br>C</span><span style="color: #000000; ">-</span><span style="color: #000000; ">O&nbsp;</span><span style="color: #000000; ">/</span><span style="color: #000000; ">C</span><span style="color: #000000; ">-</span><span style="color: #000000; ">I来回跳转<br>H&nbsp;&#8211;HOME&nbsp;L&nbsp;&#8211;last<br>ma&nbsp;:定义标签&nbsp;a，&#8216;a:回到a<br>C</span><span style="color: #000000; ">-</span><span style="color: #000000; ">V文本块操作<br></span><span style="color: #000000; ">/</span><span style="color: #000000; ">\<br>yy&nbsp;:复制一行，p:粘贴<br></span><span style="color: #000000; ">^</span><span style="color: #000000; ">&nbsp;将光标快速跳转到本行的首行字符<br>$&nbsp;将光标快速跳转到本行的行尾字符<br>:m,ny&nbsp;复制第m行到第n行之间的文本到VI缓冲区<br><br></span><span style="color: #000000; ">5.3</span><span style="color: #000000; ">、替换操作<br>:s</span><span style="color: #000000; ">/</span><span style="color: #000000; ">old</span><span style="color: #000000; ">/</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;替换当前行的第一个字符old为字符new<br>:s</span><span style="color: #000000; ">/</span><span style="color: #000000; ">old</span><span style="color: #000000; ">/</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">/</span><span style="color: #000000; ">g&nbsp;替换当前行的所有字符old为字符new<br>:m,ns</span><span style="color: #000000; ">/</span><span style="color: #000000; ">old</span><span style="color: #000000; ">/</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">/</span><span style="color: #000000; ">g&nbsp;替换当前行号m到行号n的所有字符old为字符new<br>:</span><span style="color: #000000; ">%</span><span style="color: #000000; ">s</span><span style="color: #000000; ">/</span><span style="color: #000000; ">old</span><span style="color: #000000; ">/</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">/</span><span style="color: #000000; ">g&nbsp;替换整个文本的所有字符old为字符new<br><br></span><span style="color: #000000; ">5.7</span><span style="color: #000000; ">、使用替换的确认功能<br>:s</span><span style="color: #000000; ">/</span><span style="color: #000000; ">old</span><span style="color: #000000; ">/</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">/</span><span style="color: #000000; ">c&nbsp;替换当前行的第一个字符old为字符new并提示用户确认操作<br>:s</span><span style="color: #000000; ">/</span><span style="color: #000000; ">old</span><span style="color: #000000; ">/</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">/</span><span style="color: #000000; ">gc&nbsp;替换当前行的所有字符old为字符new并提示用户确认操作<br>:m,ns</span><span style="color: #000000; ">/</span><span style="color: #000000; ">old</span><span style="color: #000000; ">/</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">/</span><span style="color: #000000; ">gc&nbsp;替换当前行号m到行号n的所有字符old为字符new并提示用户确认操作<br>:</span><span style="color: #000000; ">%</span><span style="color: #000000; ">s</span><span style="color: #000000; ">/</span><span style="color: #000000; ">old</span><span style="color: #000000; ">/</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">/</span><span style="color: #000000; ">gc&nbsp;替换整个文本的所有字符old为字符new并提示用户确认操作<br>：edit&nbsp;foo.txt&nbsp;—编辑另一个文档<br>：next&nbsp;进行文件切换<br>C</span><span style="color: #000000; ">-</span><span style="color: #000000; ">W&nbsp;切换窗口<br>vimdiff&nbsp;main.c</span><span style="color: #000000; ">~</span><span style="color: #000000; ">&nbsp;main.c<br>:g</span><span style="color: #000000; ">+</span><span style="color: #008000; ">//</span><span style="color: #008000; ">+s/foobar/barfoo/g</span><span style="color: #008000; "><br></span><span style="color: #000000; ">CTags:<br>Ctags&nbsp;&#8211;R</span><span style="color: #000000; ">/</span><span style="color: #000000; ">ctags&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; "><br>:</span><span style="color: #0000FF; ">set</span><span style="color: #000000; ">&nbsp;tags&nbsp;</span><span style="color: #000000; ">=/</span><span style="color: #000000; ">..</span><span style="color: #000000; ">/</span><span style="color: #000000; ">tags<br>：Tlist<br>F3查找<br>：make<br>:cw&nbsp;:cn&nbsp;:cp<br>mm&nbsp;标签，F2&nbsp;切换<br>cscope&nbsp;&#8211;Rbq<br>:cs&nbsp;add&nbsp;</span><span style="color: #000000; ">/</span><span style="color: #000000; ">..</span><span style="color: #000000; ">/</span><span style="color: #000000; ">cscope.</span><span style="color: #0000FF; ">out</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">/</span><span style="color: #000000; ">..</span><span style="color: #000000; ">/</span><span style="color: #000000; "><br>:cs&nbsp;find&nbsp;g&nbsp;xxx<br>:cs&nbsp;find&nbsp;c&nbsp;vim_strsave<br>:cw<br>按tab键自动补全。<br>缺点是：&nbsp;自动补全功能麻烦，必须先建立ctags，写代码还是很累，我写了一下午，写的手都麻了。出错检查&nbsp;啊，括号自动匹配啊，<br>单词补全功能啊，都不满意，另外对C</span><span style="color: #000000; ">++</span><span style="color: #000000; ">的支持不好。<br>比如我刚写了2个config.h,config.cpp，这2个文件<br>没有进行CTAG,CSCOPE操作，就不能单词补全，括号匹配不能检测，不知道是我配置有问题还是怎么回事啊。<br>另外不能进行DEBUG,所以我只能放弃。<br></span><span style="color: #000000; ">2</span><span style="color: #000000; ">.emacs</span><span style="color: #000000; ">+</span><span style="color: #000000; ">插件<br>可以查看<br>http:</span><span style="color: #008000; ">//</span><span style="color: #008000; ">blog.163.com/yu_hongchang/blog/static/3989413820081121512613/</span><span style="color: #008000; "><br></span><span style="color: #000000; ">这个我没有试验，估计和vim一样，都是命令操作，听说这个功能强大一些，能够通过xterm进行调试，这个我之前用过，但是那个xterm真的不怎么好用，界面，鼠标，我都不喜欢。<br></span><span style="color: #000000; ">3</span><span style="color: #000000; ">.&nbsp;kdevelop<br>这个工具做的比较差劲吧，我也不喜欢，比如他的自动补全功能很不爽，比如：有个函数<br>Int&nbsp;test(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;c1,</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;c2)<br>当我们敲下&nbsp;tes时，只能出现test，而后面的参数列表都不能显示，所以当代码量比较大，函数参数比较多的时候，我们都记不住参数，没有参数列表提示，就会觉得很不爽。不过还好，它集成了kgdb可以进行debug.<br></span><span style="color: #000000; ">4</span><span style="color: #000000; ">.eclipse&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">cdt<br>好多人用这个IDE，还算好吧，但是eclipse是个java的，运行速度慢的很，另外单词补全功能太差劲了，只能补全结构体或者类，在写下.</span><span style="color: #000000; ">/</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">之后才能补全，另外要按&nbsp;control</span><span style="color: #000000; ">+/</span><span style="color: #000000; ">&nbsp;才能补全，不能在敲代码的同时自动显示，eclipse对c</span><span style="color: #000000; ">/</span><span style="color: #000000; ">c</span><span style="color: #000000; ">++</span><span style="color: #000000; ">的支持远远不如对JAVA的支持强大，但是我至少认为比在vim中写要舒服一些，可能&nbsp;是个人习惯了那个IDE的工作环境。<br></span><span style="color: #000000; ">5</span><span style="color: #000000; ">.code::blocks<br>可以查看：<br>http:</span><span style="color: #008000; ">//</span><span style="color: #008000; ">www.codeblocks.org/</span><span style="color: #008000; "><br></span><span style="color: #000000; ">支持的平台不全，我的是redhat&nbsp;企业版&nbsp;</span><span style="color: #000000; ">5.0</span><span style="color: #000000; ">，就安装不上，所以我也没有能够一睹它的芳容，可惜啊。<br></span><span style="color: #000000; ">6</span><span style="color: #000000; ">.&nbsp;anjuta<br>这个我下载了安装不上，不知道为什么，而且要求配置的比较多，也比较麻烦，如果你感兴趣，可以看<br>http:</span><span style="color: #008000; ">//</span><span style="color: #008000; ">hi.baidu.com/my2008space/blog/item/140de5255fab81084c088d1e.html</span><span style="color: #008000; "><br></span><span style="color: #000000; ">7</span><span style="color: #000000; ">.&nbsp;Kylix<br>这个没有试。<br></span><span style="color: #000000; ">8</span><span style="color: #000000; ">.netbeans<br>这个也不错，我装过试了试，能满足我的功能，但是可定制稍微差点，但是能满足需要了，也还不错吧，如果没有下面要提到的slick&nbsp;edit,我就会选择它了。<br></span><span style="color: #000000; ">9</span><span style="color: #000000; ">.windows&nbsp;ue</span><span style="color: #000000; ">+</span><span style="color: #000000; ">ssh<br>有很多的人用这个方法，我不太喜欢，可能是不喜欢ue那个界面吧，应该和vim之类的类似。<br></span><span style="color: #000000; ">10</span><span style="color: #000000; ">.slick&nbsp;edit<br>呵呵，我最终选择的是这个，很好用，可定制性强，支持的语言多，非常的好用，能够直接进行debug,而且速度也很快，界面和vc&nbsp;</span><span style="color: #000000; ">6</span><span style="color: #000000; ">.0很相似，是一个唯一可以和&nbsp;vc&nbsp;相媲美的工具，但不是免费的，不过还是要感谢那些的黑客，让这个软件得到了破解，<br>你可以通过下面的链接下载：<br>http:</span><span style="color: #008000; ">//</span><span style="color: #008000; ">www.slickedit.com/content/view/409/239/</span><span style="color: #008000; "><br></span><span style="color: #000000; ">下载SlickEdit&nbsp;v14.</span><span style="color: #000000; ">0.2</span><span style="color: #000000; ">.</span><span style="color: #000000; ">2</span><span style="color: #000000; "><br>然后到http:</span><span style="color: #008000; ">//</span><span style="color: #008000; ">download.csdn.net/source/1481066</span><span style="color: #008000; "><br></span><span style="color: #000000; ">去下载破解的文件，然后覆盖就可以了。<br>这个工具非常的好用啊，大家可以试一试啊，<br>这个工具最好的地方就是可以查看memory的情况，这点我喜欢。呵呵<br></span><span style="color: #000000; ">11</span><span style="color: #000000; ">.编译工具和DEBUG工具<br>主要的编译工具都是gcc，当代码量大的时候就要写makefile了，另外的调试工具主要都是gdb，这些可视化的IDE基本都是包装了gcc,&nbsp;gdb。所以slickedit对于我这种刚转到Linux,对makefile不熟悉的人来说无疑是一根救命的稻草，能让我很快的进入工作状态，当然，&nbsp;你只是把它当成编辑的工具，也会发现它能大大缩小你编码的时间，让你的手不会因为写代码而感到疲惫。<br>终于尘埃落定，以后我要用slickedit来开始我的Linux之旅了。<br></span><span style="color: #000000; ">1</span><span style="color: #000000; ">.&nbsp;c</span><span style="color: #000000; ">/</span><span style="color: #000000; ">c</span><span style="color: #000000; ">++</span><span style="color: #000000; ">编译器&nbsp;gcc</span><span style="color: #000000; ">/</span><span style="color: #000000; ">g</span><span style="color: #000000; ">++</span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;<br>详情请参考网站:http:</span><span style="color: #008000; ">//</span><span style="color: #008000; ">gcc.gnu.org/</span><span style="color: #008000; "><br></span><span style="color: #000000; ">2</span><span style="color: #000000; ">.&nbsp;UML建模工具&nbsp;Bouml<br>linux下比较好用的建模工具，相当于windows下的rational&nbsp;rose，具成了程序UML模型设计，代码编辑，代码生成功能等功能.<br>详情请参考网站：http:</span><span style="color: #008000; ">//</span><span style="color: #008000; ">bouml.free.fr/</span><span style="color: #008000; "><br></span><span style="color: #000000; ">3</span><span style="color: #000000; ">.&nbsp;makefile文件编写工具&nbsp;：autoconf,automake<br>无论是在Linux还是在Unix环境中，make都是一个非常重要的编译命令。不管是自己进行项目开发还是安装应用软件，<br>我们都经常要用到make或&nbsp;make&nbsp;install。利用make工具，我们可以将大型的开发项目分解成为多个更易于管理的模块，<br>对于一个包括几百个源文件的应用程序，但是如果通过查阅make的帮助文档来手工编写Makefile,对任何程序员都是一场挑战。<br>幸而有GNU&nbsp;提供的Autoconf及Automake这两套工具使得编写makefile不再是一个难题<br>使用make和&nbsp;makefile工具就可以轻而易举的理顺各个源文件之间纷繁复杂的相互关系,autoconf,automake一般配合libtool使用。<br>详情请参考网站：<br>http:</span><span style="color: #008000; ">//</span><span style="color: #008000; ">www.ibm.com/developerworks/cn/linux/l-makefile/</span><span style="color: #008000; "><br></span><span style="color: #000000; ">http:</span><span style="color: #008000; ">//</span><span style="color: #008000; ">www.gnu.org/software/autoconf/</span><span style="color: #008000; "><br></span><span style="color: #000000; ">http:</span><span style="color: #008000; ">//</span><span style="color: #008000; ">www.gnu.org/software/automake/</span><span style="color: #008000; "><br></span><span style="color: #000000; ">http:</span><span style="color: #008000; ">//</span><span style="color: #008000; ">www.gnu.org/software/libtool/</span><span style="color: #008000; "><br></span><span style="color: #000000; ">4</span><span style="color: #000000; ">.&nbsp;调试工具：gdb<br>在window下编程，调试工具已经具成到VS环境，在linux</span><span style="color: #000000; ">/</span><span style="color: #000000; ">Unix下调试则通过gdb来调试，个人觉得gdb调试比vs调试高效很多。<br>详情请参考网站：http:</span><span style="color: #008000; ">//</span><span style="color: #008000; ">www.gnu.org/software/gdb/</span><span style="color: #008000; "><br></span><span style="color: #000000; ">5</span><span style="color: #000000; ">.&nbsp;内存泄漏工具：valgrind<br>对于动则成千上万行的代码，很难通过手工的方式去保证内存没有泄漏，<br>valgrind通过内存申请、释放匹配的原则来检测内存泄漏，内存越界的BUG。当然，良好的编程习惯也是保证代码质量高效必不可少的条件。<br>参考网站：http:</span><span style="color: #008000; ">//</span><span style="color: #008000; ">valgrind.org/</span><span style="color: #008000; "><br></span><span style="color: #000000; ">6</span><span style="color: #000000; ">.&nbsp;源代码管理工具：svn<br>软件开发不再是个人大师的年代，都是以团队的方式来开发，如何保证代码的同步，协同开发，svn给我们提了很好的帮助。<br>详情请参考网站：http:</span><span style="color: #008000; ">//</span><span style="color: #008000; ">svncorp.org/</span><span style="color: #008000; "><br></span><span style="color: #000000; ">7</span><span style="color: #000000; ">.&nbsp;网络协议分析工具：wireshark<br>编写网络程序，就不可避免要处理网络协议,分析网络数据.wireshark提供了关于网络层和上层协议的各种信息。<br>命令行下分析网络协议可以使用tcpdump.</span></div><img src ="http://www.cppblog.com/singohgod/aggbug/145950.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/singohgod/" target="_blank">大宝天天见</a> 2011-05-08 15:18 <a href="http://www.cppblog.com/singohgod/archive/2011/05/08/145950.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转载]从Windows转到Linux下C++编程的过程</title><link>http://www.cppblog.com/singohgod/archive/2011/02/18/140249.html</link><dc:creator>大宝天天见</dc:creator><author>大宝天天见</author><pubDate>Fri, 18 Feb 2011 02:09:00 GMT</pubDate><guid>http://www.cppblog.com/singohgod/archive/2011/02/18/140249.html</guid><wfw:comment>http://www.cppblog.com/singohgod/comments/140249.html</wfw:comment><comments>http://www.cppblog.com/singohgod/archive/2011/02/18/140249.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/singohgod/comments/commentRss/140249.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/singohgod/services/trackbacks/140249.html</trackback:ping><description><![CDATA[<div id=content>
<p>学习Unix常用的命令,ls,ll,cd,su,mkdir,cp,mv,rm -rf,Vim操作，安装CTags，TList插件。</p>
<p>学习MakeFile文件。</p>
<p>特别注意当前程序需要哪些.h文件，哪些lib文件。需要编译成什么文件。注意编译的路径就好了。</p>
<p>Svn操作。上传，下载，更新。</p>
<p>主要是svn co，下载</p>
<p>svn add 添加文件或者文件夹<!--iwms_ad_begin-->
<table border=0 width="97%" align=center>
    <tbody>
        <tr>
            <td colSpan=3>
            <div align=center>
            <script language=javaScript type=text/javascript src="../../system/system60.js"></script>
            </div>
            </td>
        </tr>
    </tbody>
</table>
<!--iwms_ad_end--></p>
<p>svn info 查看信息</p>
<p>svn ci 提交修改</p>
<p>svn up 下载信息。</p>
<p>SecureCRT，putty。</p>
<p>lcd 变更本地路径。put 上传，get 下载。</p>
<p>shell脚本，sed，python</p>
</div>
<br>
<img src ="http://www.cppblog.com/singohgod/aggbug/140249.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/singohgod/" target="_blank">大宝天天见</a> 2011-02-18 10:09 <a href="http://www.cppblog.com/singohgod/archive/2011/02/18/140249.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[摘录]Linux c++ 编程课程</title><link>http://www.cppblog.com/singohgod/archive/2011/02/16/140182.html</link><dc:creator>大宝天天见</dc:creator><author>大宝天天见</author><pubDate>Wed, 16 Feb 2011 11:43:00 GMT</pubDate><guid>http://www.cppblog.com/singohgod/archive/2011/02/16/140182.html</guid><wfw:comment>http://www.cppblog.com/singohgod/comments/140182.html</wfw:comment><comments>http://www.cppblog.com/singohgod/archive/2011/02/16/140182.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/singohgod/comments/commentRss/140182.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/singohgod/services/trackbacks/140182.html</trackback:ping><description><![CDATA[看到一套课程表,还不错,慢慢学吧<br><br>一、Linux操作系统 <br><br>&nbsp;&nbsp;&nbsp; * 系统环境：Ubuntu GNU/Linux、RedHat Linux AS5、FreeBSD <br>&nbsp;&nbsp;&nbsp; * 课程要求：熟练使用常用的Linux/UNIX命令。 <br>&nbsp;&nbsp;&nbsp; * 时间：1周。 <br><br>二、Linux C++开发环境搭建、开发工具的使用 <br><br>&nbsp;&nbsp;&nbsp; * 涉及内容：vi、GCC、GDB、Make、CVS、Subversion、Eclipse CDT <br>&nbsp;&nbsp;&nbsp; * 课程要求： <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; o 熟练使用vi文本编辑器； <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; o 熟练使用GCC工具链进行编译、调试、构建可执行文件或共享库/静态库； <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; o 熟练编写Makefile； <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; o 熟练配置、使用CVS和Subversion两种版本控制工具； <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; o 熟练配置、使用Eclipse CDT开发工具。 <br>&nbsp;&nbsp;&nbsp; * 时间：1周 <br><br>三、C++语言 <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; C++是一门多范型编程语言，相对于C、Java、C#等C系语言，复杂度高，但一旦领悟C++的精髓，则能发挥C++语言的强大威力，为了让学员掌握C++语言编程技术，我们将这部分的课程分为五个部分： <br><br>&nbsp;&nbsp;&nbsp; * 面向过程编程: Core C++ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; o 涉及技术：C++基础：类型和声明、指针与数组、表达式与语句、函数、名字空间、异常、代码文件的组织 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; o 课程要求：掌握扎实的C++基础知识。 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; o 时间：1.5周。 <br>&nbsp;&nbsp;&nbsp; * 面向对象编程: 封装、继承与多态（encapsulation、inherit &amp; Polymorphism） <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; o 涉及技术：类设计、运算符重载、继承与多态。 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; o 课程要求：正确理解面向对象的概念，用面向对象的思维和方法构建软件，正确地设计和使用类以及继承体系。 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; o 时间：1.5周。 <br>&nbsp;&nbsp;&nbsp; * 泛型编程: C++模板（Template） <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; o 涉及技术：类模板、函数模板、函数对象（Function object）。 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; o 课程要求：C++模板是C++强大威力的技术支撑，是构建C++标准库、Boost类库、ACE框架等的基础，必须熟练掌握C++模板技术。 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; o 时间：1.5周。 <br>&nbsp;&nbsp;&nbsp; * 数据结构与算法 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; o 涉及内容：常用数据结构(顺序容器、链表、树)和算法(排序与搜索)的C++实现。 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; o 课程要求：能实现常规的数据结构（容器如vector、list、statck、queue等），排序和搜索算法。 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; o 时间：1.5周。 <br>&nbsp;&nbsp;&nbsp; * C++标准库应用 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; o 涉及技术：标准容器（STL容器）：vector、list、map、set等等；迭代器、算法库、IO流、C语言数学库等 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; o 课程要求：对常用的部分如容器、迭代器、常用的算法、IO流，必须牢固掌握、熟练使用，对其它部分必须有认识，以免日后工作中频繁的编写标准库中存在的内容，重复制造轮子。 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; o 时间：2周。 <br><br>四、C++ Boost模板库 <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Boost是由C++标准委员会成员发起、众多C++界高手参与设计并实现的一个涉及面广、质量高且业已广泛使用的C++标准后备库，其中TR1已经被纳入C++0x标准库。这部分的课程将涉及其中一些常用的类库。 <br><br>&nbsp;&nbsp;&nbsp; * 涉及技术：Aiso、Thread、Interprocess、System、File System、Date Time、Format、Array、Lambda、Signals、TR1中的部分（Regex、Tuple、Smart Point、Hash Map、Hash Set等）。 <br>&nbsp;&nbsp;&nbsp; * 课程要求：必须掌握的类库有：Aiso、Thread、Date Time以及TR1中部分内容。 <br>&nbsp;&nbsp;&nbsp; * 时间：2周。 <br><br>五、ACE框架 <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ACE是一个被广泛使用、设计优雅、高性能的C++通信框架（不仅仅是通信框架），其设计及实现被众多开源框架所借鉴。是构建稳定、高性能、高吞吐量、跨平台的服务器端程序的优秀框架。 <br><br>&nbsp;&nbsp;&nbsp; * 涉及技术：ACE Reactor框架、ACE Proactor框架、MultiThread支撑、Timer（Scheduler）、ACE Service Configurator。 <br>&nbsp;&nbsp;&nbsp; * 课程要求：以上列举的部分是服务器端编程必不可少的部分，均需熟练使用。 <br>&nbsp;&nbsp;&nbsp; * 时间：2周。 <br><br>六、数据库开发 <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 专注Oracle 10g、MySQL5.0+。这部分的课程分为以下三大块： <br><br>&nbsp;&nbsp;&nbsp; * SQL语言： <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; o 涉及技术：数据查询语言DQL，数据操纵语言DML，数据定义语言DDL，数据控制语言DCL。 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; o 课程要求：熟练使用SQL语言。 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; o 时间：1周。 <br>&nbsp;&nbsp;&nbsp; * Oracle和MySQL存储过程、函数、触发器 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; o 涉及技术：PL/SQL。 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; o 课程要求：熟练编写Oracle和MySQL存储过程、函数、触发器。 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; o 时间：1周。 <br>&nbsp;&nbsp;&nbsp; * C++数据库开发 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; o 涉及技术：OTL或DTL（两个高性能、易用的C++模板类，针对各大主流数据库如：Oracle、DB2、SqlServer、MySQL等）。 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; o 课程要求：熟练使用OTL和DTL进行数据库编程。 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; o 时间：0.5周。 <br><br>七、软件工程 <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一个优秀的软件工程师不仅具备优秀的编码能力，更应该拥有优秀的软件设计思维和方法，以下课程也是轩辕学员必修的内容。 <br><br>&nbsp;&nbsp;&nbsp; * 涉及技术：数据库建模、软件建模、GOF设计模式、文档编写 <br>&nbsp;&nbsp;&nbsp; * 课程要求：掌握数据库建模、软件建模的思想和方法，熟练使用建模工具，尝试用设计模式来思考软件的架构。至少学会编写《详细设计说明书》、《概要设计说明书》、《数据库设计说明书》。 <br>&nbsp;&nbsp;&nbsp; * 时间：1.5周。 <br><br>八、项目实战 <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 轩辕提供多个企业级实战项目供学员选择，如：电信级IM Server、电信级Billing Server等基于UNIX或Linux下的高负荷、大压力的C++ Server端项目，同时提供Client端程序以便联调及测试。 <br><br>&nbsp;&nbsp;&nbsp; * 涉及技术：本项目将涉及学习阶段所有内容。 <br>&nbsp;&nbsp;&nbsp; * 项目要求：学员按分组，分工、协作，共同完成项目，最终评估两个方面：软件架构设计、软件代码实现质量。 <br>&nbsp;&nbsp;&nbsp; * 时间：4周
<img src ="http://www.cppblog.com/singohgod/aggbug/140182.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/singohgod/" target="_blank">大宝天天见</a> 2011-02-16 19:43 <a href="http://www.cppblog.com/singohgod/archive/2011/02/16/140182.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[摘录]rapidxml,一个快速的xml库</title><link>http://www.cppblog.com/singohgod/archive/2010/11/15/133685.html</link><dc:creator>大宝天天见</dc:creator><author>大宝天天见</author><pubDate>Mon, 15 Nov 2010 09:24:00 GMT</pubDate><guid>http://www.cppblog.com/singohgod/archive/2010/11/15/133685.html</guid><wfw:comment>http://www.cppblog.com/singohgod/comments/133685.html</wfw:comment><comments>http://www.cppblog.com/singohgod/archive/2010/11/15/133685.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/singohgod/comments/commentRss/133685.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/singohgod/services/trackbacks/133685.html</trackback:ping><description><![CDATA[近来找到一个快速的xml库,试用了一下,方法和现在使用的tinyxml差不多,很容易上手,如果有机会可以移植到项目里面试试<br><br>自从用了xml后对他是又爱又恨,他的确能代替配置文件,但是当文件容量大到一定量的时候灾难就降临了,比如读取一个50M的xml文件,往往读取花上10秒,解析再花上20秒,还要占用大量内存空间,十分头痛.所以实际项目中都会将xml再转为二进制文件来处理,但是xml的灵活性的确很方便,如果rapidxml能接近二进制的速度,当然就太好啦,还没有测试过,下面是一些介绍.<br><br>貌似tinyxml会遇到unicode障碍,rapidxml不会,如果项目要做多语言版本就必须面临解决这个问题...<br><br>
<hr>
<br>rapidxml是一个快速的xml库，官方网站： <a href="http://rapidxml.sourceforge.net/">http://rapidxml.sourceforge.net/</a>，根据manual看到，他竟然比tinyxml快了50-100倍<br><br>
<hr>
<p>目前我公司开发的Nexus Engine的底层对象序列化使用了TinyXML来读写XML文件。TinyXML有两个不爽的地方，一是它的接口使用FILE*，另外一个是它对 wchar_t不能很好的支持。前阵子看Boost库的更新中多了一个PropertyTree，他在处理XML时用到了另外一个小的库 &#8211;RapidXML。既然间接的是Boost库的一部分，所以是值得一试的。于是找到其官方网站（<a title=http://rapidxml.sourceforge.net/ href="http://rapidxml.sourceforge.net/" target=_blank><font color=#5c7a99>http://rapidxml.sourceforge.net/</font></a>）研究了一番。一看之下，甚是满意，也推荐给大家看看！</p>
<p>首先就是速度，据它自己宣称比TinyXML快30到60倍，比Xerces DOM快50到100倍！详细的测试比较请见其用户手册（<a title=http://rapidxml.sourceforge.net/manual.html href="http://rapidxml.sourceforge.net/manual.html" target=_blank><font color=#5c7a99>http://rapidxml.sourceforge.net/manual.html</font></a>）的&#8220;4. Performance &#8221;一节。</p>
<p>其次它的设计非常的简洁，只依赖于标准库中的几个基本的类。它的输入输出都是字符串，这样很好，一个库就应该关注自己核心的内容，做尽量少的事情。它的API其实和TinyXML倒是有几分相似，用过TinyXML的人应该很容易上手：</p>
<p>TinyXML主要接口类 &nbsp;&nbsp; &nbsp;RapidXML的主要接口类</p>
<table cellSpacing=1 cellPadding=2 width=543 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=300><strong>TinyXML主要接口类</strong></td>
            <td vAlign=top width=238><strong>RapidXML的主要接口类</strong></td>
        </tr>
        <tr>
            <td width=300>class TiXmlDocument</td>
            <td vAlign=top width=238>template&lt;class Ch = char&gt;<br>class xml_document</td>
        </tr>
        <tr>
            <td vAlign=top width=300>class TiXmlNode</td>
            <td vAlign=top width=238>template&lt;class Ch = char&gt;<br>class xml_node</td>
        </tr>
        <tr>
            <td vAlign=top width=300>class TiXmlAttribute</td>
            <td vAlign=top width=238>template&lt;class Ch = char&gt;<br>class xml_attribute</td>
        </tr>
    </tbody>
</table>
<p>下面还是看一个具体的例子来体验一下，下面是TinyXML官方教程中创建XML文档的一段代码：</p>
<blockquote>
<p>void build_simple_doc( )<br>{<br>// Make xml: &lt;?xml ..&gt;&lt;Hello&gt;World&lt;/Hello&gt;<br>TiXmlDocument doc;<br>TiXmlDeclaration * decl = new TiXmlDeclaration( &#8220;1.0&#8243;, &#8220;&#8221;, &#8220;&#8221; );<br>TiXmlElement * element = new TiXmlElement( &#8220;Hello&#8221; );<br>TiXmlText * text = new TiXmlText( &#8220;World&#8221; );<br>element-&gt;LinkEndChild( text );<br>doc.LinkEndChild( decl );<br>doc.LinkEndChild( element );<br>doc.SaveFile( &#8220;madeByHand.xml&#8221; );<br>}</p>
</blockquote>
<p>下面是使用RapidXML实现类似功能的代码：</p>
<blockquote>
<p>void build_simple_doc_by_rapidxml()<br>{<br>xml_document&lt;&gt; doc;<br>xml_node&lt;&gt;* decl = doc.allocate_node(node_declaration);<br>xml_attribute&lt;&gt;* decl_ver =<br>doc.allocate_attribute(&#8220;version&#8221;, &#8220;1.0&#8243;);<br>decl-&gt;append_attribute(decl_ver);<br>doc.append_node(decl);</p>
<p>xml_node&lt;&gt;* node =<br>doc.allocate_node(node_element,&nbsp;&nbsp;&nbsp; &#8220;Hello&#8221;, &#8220;World&#8221;);<br>doc.append_node(node);</p>
<p>string text;<br>rapidxml::print(std::back_inserter(text), doc, 0);</p>
<p>// write text to file by yourself<br>}</p>
</blockquote>
<p>下面是使用RapidXML分析XML的样例代码：</p>
<blockquote>
<p>void parse_doc_by_rapidxml(char* xml_doc)<br>{<br>xml_document&lt;&gt; doc;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // character type defaults to char<br>doc.parse&lt;0&gt;(xml_doc);&nbsp; // 0 means default parse flags</p>
<p>xml_node&lt;&gt; *node = doc.first_node(&#8220;Hello&#8221;);<br>string node_val = node-&gt;value();<br>}</p>
</blockquote><br>
<hr>
<p>前两天有朋友问，我的<a href="http://multi-crash.com/?page_id=161" target=_blank><span style="COLOR: #0000ff">SlimXml</span></a>有没有和<a href="http://rapidxml.sourceforge.net/" target=_blank><span style="COLOR: #0000ff">RapidXml</span></a>对比过效率？我是第一次听说这个库，更不用说对比效率了，于是上他们网站看了下。</p>
<p>好家伙，居然号称比<a href="http://sourceforge.net/projects/tinyxml/" target=_blank><span style="COLOR: #0000ff">TinyXml</span></a>快30～60倍，而且是<a href="http://boost.org/"><span style="COLOR: #0000ff">Boost.PropertyTree</span></a>的默认xml解析器。</p>
<p>于是有点好奇，因为以前也没有特别关心过SlimXml的效率。</p>
<p>于是分别下载了TinyXml-2.6.1和RapidXml-1.13，迅速用vc8建立了两个测试工程，在系统中搜&#8221;*.xml&#8221;，找到了一个比较合适的测试文件。它足够大（1.5M），utf-8编码并且包含中/英文，有一定层次深度，大约3.3万行。测试文件可以<a href="http://multi-crash.com/download/test.zip" target=_blank><span style="COLOR: #0000ff">从这里下载</span></a></p>
<p>测试对象是三个库从内存字符串解析xml的函数，这样能排除从硬盘上读文件这种不稳定因素的干扰，而且RapidXml貌似只支持从内存里解析</p>
<ul>
    <li>slim::XmlDocument::loadFromMemory()
    <li>TiXmlDocument::Parse()
    <li>rapidxml::xml_document&lt;char&gt;::parse&lt;flag&gt;() </li>
</ul>
<p>要说明的是，RapidXml的这个parse是一个模板函数，必须给一个flag的参数，我测试的时候给的是默认的0</p>
<p>测试结果，解析这个3.3万行，1.5M大小的xml，三个库分别花了</p>
<ul>
    <li>SlimXml: 22ms
    <li>TinyXml: 54ms
    <li>RapidXml: 4ms! </li>
</ul>
<p>结论是，RapidXml果然很强悍，居然比我的SlimXml快5倍多。但是并没有如作者所说比TinyXml快30~60倍，只有不到15倍。据说对比用的是一个约50k大小的xml文件，可惜并没有提供下载，不然可以验证一下。</p>
<p>比较欣慰的是，在我并没有很关注效率的情况下，SlimXml仍然比TinyXml快2.5倍。SlimXml走的是简单小巧路线，源代码只有32k，而TinyXml和RapidXml的源码分别是147k和141k，有这样的效率可以满意了。在我有很多空闲以前，估计我也不会再去优化它，因为这个库主要还是针对几十上百行的小文件，解析特别大的xml不在我考虑的范围之内。</p>
<p>以下是RapidXml提供的常见xml库效率对照表，其中还很牛鼻地提供了和strlen()函数的效率对比</p>
<p><a href="http://multi-crash.com/blog/wp-content/uploads/2010/07/xml.png"><img class="alignnone size-full wp-image-279" title=xml height=275 src="http://hiphotos.baidu.com/5iprog/pic/item/1878fd197c684c4235fa4182.jpg" width=582></a></p>
<p>我估计RapidXml速度快的主要原因是对memory pool的使用，毕竟在解析过程中需要创建大量的string，可以想象用memory pool和直接走默认的new很容易产生超过一个数量级的效率差异。</p>
<br>
<hr>
<br><br><br><br><br><br>
<img src ="http://www.cppblog.com/singohgod/aggbug/133685.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/singohgod/" target="_blank">大宝天天见</a> 2010-11-15 17:24 <a href="http://www.cppblog.com/singohgod/archive/2010/11/15/133685.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转载]介绍LuaPlus: 好用的Lua For C++扩展(修订)</title><link>http://www.cppblog.com/singohgod/archive/2010/11/15/133678.html</link><dc:creator>大宝天天见</dc:creator><author>大宝天天见</author><pubDate>Mon, 15 Nov 2010 09:11:00 GMT</pubDate><guid>http://www.cppblog.com/singohgod/archive/2010/11/15/133678.html</guid><wfw:comment>http://www.cppblog.com/singohgod/comments/133678.html</wfw:comment><comments>http://www.cppblog.com/singohgod/archive/2010/11/15/133678.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/singohgod/comments/commentRss/133678.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/singohgod/services/trackbacks/133678.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 打算把lua作为项目的脚本语言,下面是不不错的教程,收藏虽然很早前研究过Lua,但还没有在放到项目中进行检验,要亲自用过才知道好坏~LuaPlus是Lua的C++增强，也就是说，LuaPlus本身就是在Lua的源码上进行增强得来的。用它与C++进行合作，是比较好的一个选择。LuaPlus目前版本为：LuaPlus for Lua 5.01 Distribution Build 1080 (Febr...&nbsp;&nbsp;<a href='http://www.cppblog.com/singohgod/archive/2010/11/15/133678.html'>阅读全文</a><img src ="http://www.cppblog.com/singohgod/aggbug/133678.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/singohgod/" target="_blank">大宝天天见</a> 2010-11-15 17:11 <a href="http://www.cppblog.com/singohgod/archive/2010/11/15/133678.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转载]C++ 程序文档生成器介绍(doxygen)</title><link>http://www.cppblog.com/singohgod/archive/2010/11/15/133677.html</link><dc:creator>大宝天天见</dc:creator><author>大宝天天见</author><pubDate>Mon, 15 Nov 2010 09:07:00 GMT</pubDate><guid>http://www.cppblog.com/singohgod/archive/2010/11/15/133677.html</guid><wfw:comment>http://www.cppblog.com/singohgod/comments/133677.html</wfw:comment><comments>http://www.cppblog.com/singohgod/archive/2010/11/15/133677.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/singohgod/comments/commentRss/133677.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/singohgod/services/trackbacks/133677.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 程序文档，曾经是程序员的一个头痛问题。写一个程序文档，比较花时间，但不是很难；麻烦的是当程序修改后，程序文档也要跟着同步更新，否则文档和程序就要脱节，文档也就变成没用的东西了。好在有许多好用的文档生成器来解决这个问题。目前比较流行的C++文档生成器是doxygen。本文就简单的介绍一下doxygen的文档注释方法，以供初学者参考：C++ 程序文档生成器介绍(doxygen)&nbsp;&nbsp;...&nbsp;&nbsp;<a href='http://www.cppblog.com/singohgod/archive/2010/11/15/133677.html'>阅读全文</a><img src ="http://www.cppblog.com/singohgod/aggbug/133677.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/singohgod/" target="_blank">大宝天天见</a> 2010-11-15 17:07 <a href="http://www.cppblog.com/singohgod/archive/2010/11/15/133677.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转载]Lua脚本语法说明(修订)</title><link>http://www.cppblog.com/singohgod/archive/2010/11/15/133676.html</link><dc:creator>大宝天天见</dc:creator><author>大宝天天见</author><pubDate>Mon, 15 Nov 2010 09:05:00 GMT</pubDate><guid>http://www.cppblog.com/singohgod/archive/2010/11/15/133676.html</guid><wfw:comment>http://www.cppblog.com/singohgod/comments/133676.html</wfw:comment><comments>http://www.cppblog.com/singohgod/archive/2010/11/15/133676.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/singohgod/comments/commentRss/133676.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/singohgod/services/trackbacks/133676.html</trackback:ping><description><![CDATA[这么好的教程一定要收藏一份~<br><br>Lua脚本语法说明（增加lua5.1部份特性）<br><br>　　Lua 的语法比较简单，学习起来也比较省力，但功能却并不弱。<br>　　所以，我只简单的归纳一下Lua的一些语法规则，使用起来方便好查就可以了。估计看完了，就懂得怎么写Lua程序了。<br><br>　　在Lua中，一切都是变量，除了关键字。<br><br>I.&nbsp; 首先是注释<br>　　写一个程序，总是少不了注释的。<br>　　在Lua中，你可以使用单行注释和多行注释。<br>　　单行注释中，连续两个减号"--"表示注释的开始，一直延续到行末为止。相当于C++语言中的"//"。<br>　　多行注释中，由"--[["表示注释开始，并且一直延续到"]]"为止。这种注释相当于C语言中的"/*...*/"。在注释当中，"[["和"]]"是可以嵌套的（<span style="COLOR: red">在lua5.1中，中括号中间是可以加若干个"="号的，如 [==[ ... ]==]</span>），见下面的字符串表示说明。<br><br>II.&nbsp; Lua编程<br>　　经典的"Hello world"的程序总是被用来开始介绍一种语言。在Lua中，写一个这样的程序很简单：<br>　　print("Hello world")<br>　　在Lua中，语句之间可以用分号"；"隔开，也可以用空白隔开。一般来说，如果多个语句写在同一行的话，建议总是用分号隔开。<br>　　Lua 有好几种程序控制语句，如：<br>
<table style="WIDTH: 760px; BORDER-COLLAPSE: collapse; HEIGHT: 124px" cellSpacing=0 cellPadding=3 border=1>
    <tbody>
        <tr>
            <td style="COLOR: red">控制语句</td>
            <td style="COLOR: red">格式</td>
            <td style="COLOR: red">示例</td>
        </tr>
        <tr>
            <td style="WIDTH: 80px">If</td>
            <td style="WIDTH: 313px; HEIGHT: 44px">if 条件 then ... elseif 条件 then ... else ... end</td>
            <td>
            <div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">then</span><span style="COLOR: #000000">&nbsp;print(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">true</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)<br></span><span style="COLOR: #0000ff">elseif</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">then</span><span style="COLOR: #000000">&nbsp;print(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">true</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)<br></span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000">&nbsp;print(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">false</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)&nbsp;</span><span style="COLOR: #0000ff">end</span></div>
            <br></td>
        </tr>
        <tr>
            <td>While</td>
            <td>while 条件 do ... end</td>
            <td>
            <div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">do</span><span style="COLOR: #000000">&nbsp;print(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">true</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)&nbsp;</span><span style="COLOR: #0000ff">end</span></div>
            <br></td>
        </tr>
        <tr>
            <td>Repeat</td>
            <td>repeat ... until 条件</td>
            <td>
            <div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="COLOR: #000000"><span style="COLOR: #2000ff">repeat</span>&nbsp;</span><span style="COLOR: #0000ff">print</span><span style="COLOR: #000000">(</span><span style="FONT-WEIGHT: bold; COLOR: #000000">"</span><span style="FONT-WEIGHT: bold; COLOR: #000000">Hello</span><span style="FONT-WEIGHT: bold; COLOR: #000000">"</span><span style="COLOR: #000000">)&nbsp;</span><span style="COLOR: #0000ff">until</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #800000">1</span><span style="COLOR: #000000">+</span><span style="COLOR: #800000">1</span><span style="COLOR: #000000">~=</span><span style="COLOR: #800000">2</span></div>
            <br></td>
        </tr>
        <tr>
            <td>For</td>
            <td>for 变量=初值, 终点值, 步进 do&nbsp;... end</td>
            <td>
            <div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><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">1</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">10</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">do</span><span style="COLOR: #000000">&nbsp;print(i)&nbsp;</span><span style="COLOR: #0000ff">end</span></div>
            <br></td>
        </tr>
        <tr>
            <td>For</td>
            <td>for 变量1, 变量2, ... 变量n in 表或枚举函数 do ... end</td>
            <td>
            <div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">&nbsp;a,b&nbsp;</span><span style="COLOR: #0000ff">in</span><span style="COLOR: #000000">&nbsp;mylist&nbsp;</span><span style="COLOR: #0000ff">do</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">print</span><span style="COLOR: #000000">(a,&nbsp;b)&nbsp;</span><span style="COLOR: #0000ff">end</span></div>
            <br></td>
        </tr>
    </tbody>
</table>
<br>　　注意一下，for的循环变量总是只作用于for的局部变量；当省略步进值时，for循环会使用1作为步进值。<br>　　使用break可以用来中止一个循环。<br>　　相对C语言来说，Lua有几个地方是明显不同的，所以面要特别注意一下：<br><br>　　．<strong>语句块</strong><br>　　　　语句块在C中是用"{"和"}"括起来的，在Lua中，它是用do 和 end 括起来的。比如：<br>　　　　do print("Hello") end<br>　　　　可以在 <strong>函数</strong> 中和 <strong>语句块</strong> 中定局部变量。<br><br>　　．<strong>赋值语句</strong><br>　　　　赋值语句在Lua被强化了。它可以同时给多个变量赋值。<br>　　　　例如：<br>　　　　a,b,c,d=1,2,3,4<br>　　　　甚至是：<br>　　　　a,b=b,a&nbsp; -- 多么方便的交换变量功能啊。<br>　　　　在默认情况下，变量总是认为是全局的。假如需要定义局部变量，则在第一次赋值的时候，需要用local说明。比如：<br>　　　　local a,b,c = 1,2,3&nbsp; -- a,b,c都是局部变量<br><br>　　．<strong>数值运算</strong><br>　　　　和C语言一样，支持 +, -, *, /。但Lua还多了一个"^"。这表示指数乘方运算。比如2^3 结果为8, 2^4结果为16。<br>　　　　连接两个字符串，可以用".."运处符。如：<br>　　　　"This a " .. "string." -- 等于 "this a string"<br><br>　　．<strong>比较运算<br></strong>
<table style="WIDTH: 543px; BORDER-COLLAPSE: collapse; HEIGHT: 70px" cellSpacing=0 cellPadding=3 border=1>
    <tbody>
        <tr>
            <td style="COLOR: red">比较符号</td>
            <td>&lt;</td>
            <td>&gt;</td>
            <td>&lt;=</td>
            <td>&gt;=</td>
            <td>==</td>
            <td>~=</td>
        </tr>
        <tr>
            <td style="COLOR: red">含义</td>
            <td>小于</td>
            <td>大于</td>
            <td>小于或等于</td>
            <td>大于或等于</td>
            <td>相等</td>
            <td>不相等</td>
        </tr>
    </tbody>
</table>
<br>　　　　所有这些操作符总是返回true或false。<br>　　　　对于Table，Function和Userdata类型的数据，只有 == 和 ~=可以用。相等表示两个变量引用的是同一个数据。比如：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">　　　　a</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">{</span><span style="FONT-WEIGHT: bold; COLOR: #800000">1</span><span style="COLOR: #000000">,</span><span style="FONT-WEIGHT: bold; COLOR: #800000">2</span><span style="COLOR: #000000">}<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>　　　　b</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">a<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>　　　　</span><span style="COLOR: #0000ff">print</span><span style="COLOR: #000000">(a</span><span style="COLOR: #808080">==</span><span style="COLOR: #000000">b,&nbsp;a</span><span style="COLOR: #808080">~=</span><span style="COLOR: #000000">b)&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">输出&nbsp;true,&nbsp;false</span><span style="COLOR: #008080"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">　　　　a</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">{</span><span style="FONT-WEIGHT: bold; COLOR: #800000">1</span><span style="COLOR: #000000">,</span><span style="FONT-WEIGHT: bold; COLOR: #800000">2</span><span style="COLOR: #000000">}<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>　　　　b</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">{</span><span style="FONT-WEIGHT: bold; COLOR: #800000">1</span><span style="COLOR: #000000">,</span><span style="FONT-WEIGHT: bold; COLOR: #800000">2</span><span style="COLOR: #000000">}<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>　　　　</span><span style="COLOR: #0000ff">print</span><span style="COLOR: #000000">(a</span><span style="COLOR: #808080">==</span><span style="COLOR: #000000">b,&nbsp;a</span><span style="COLOR: #808080">~=</span><span style="COLOR: #000000">b)&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">输出&nbsp;false,&nbsp;true</span><span style="COLOR: #008080"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<br><br>　　．逻辑运算<br>　　　　and, or, not<br>　　　　其中，and 和 or 与C语言区别特别大。<br>　　　　在这里，请先记住，在Lua中，只有false和nil才计算为false，其它任何数据都计算为true，0也是true！<br>　　　　and 和 or的运算结果不是true和false，而是和它的两个操作数相关。<br>　　　　a and b：如果a为false，则返回a；否则返回b<br>　　　　a or b：如果 a 为true，则返回a；否则返回b<br><br>　　　　举几个例子：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">　　　　&nbsp;</span><span style="COLOR: #0000ff">print</span><span style="COLOR: #000000">(</span><span style="FONT-WEIGHT: bold; COLOR: #800000">4</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #808080">and</span><span style="COLOR: #000000">&nbsp;</span><span style="FONT-WEIGHT: bold; COLOR: #800000">5</span><span style="COLOR: #000000">)&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">输出&nbsp;5</span><span style="COLOR: #008080"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">　　　　&nbsp;</span><span style="COLOR: #0000ff">print</span><span style="COLOR: #000000">(nil&nbsp;</span><span style="COLOR: #808080">and</span><span style="COLOR: #000000">&nbsp;</span><span style="FONT-WEIGHT: bold; COLOR: #800000">13</span><span style="COLOR: #000000">)&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">输出&nbsp;nil</span><span style="COLOR: #008080"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">　　　　&nbsp;</span><span style="COLOR: #0000ff">print</span><span style="COLOR: #000000">(false&nbsp;</span><span style="COLOR: #808080">and</span><span style="COLOR: #000000">&nbsp;</span><span style="FONT-WEIGHT: bold; COLOR: #800000">13</span><span style="COLOR: #000000">)&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">输出&nbsp;false</span><span style="COLOR: #008080"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">　　　　&nbsp;</span><span style="COLOR: #0000ff">print</span><span style="COLOR: #000000">(</span><span style="FONT-WEIGHT: bold; COLOR: #800000">4</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #808080">or</span><span style="COLOR: #000000">&nbsp;</span><span style="FONT-WEIGHT: bold; COLOR: #800000">5</span><span style="COLOR: #000000">)&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">输出&nbsp;4</span><span style="COLOR: #008080"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">　　　　&nbsp;</span><span style="COLOR: #0000ff">print</span><span style="COLOR: #000000">(false&nbsp;</span><span style="COLOR: #808080">or</span><span style="COLOR: #000000">&nbsp;</span><span style="FONT-WEIGHT: bold; COLOR: #800000">5</span><span style="COLOR: #000000">)&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">输出&nbsp;5</span><span style="COLOR: #008080"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<br>　　　　在Lua中这是很有用的特性，也是比较令人混洧的特性。<br>　　　　我们可以模拟C语言中的语句：x = a? b : c，在Lua中，可以写成：x = a and b or c。<br>　　　　最有用的语句是： x = x or v，它相当于：if not x then x = v end 。<br><br>　　．运算符优先级，从低到高顺序如下：<br>
<table style="WIDTH: 320px; BORDER-COLLAPSE: collapse" cellSpacing=0 cellPadding=3 border=1>
    <tbody>
        <tr>
            <td>&nbsp;&nbsp;&nbsp;&nbsp; or<br>&nbsp;&nbsp;&nbsp;&nbsp; and<br>&nbsp;&nbsp;&nbsp;&nbsp; &lt;&nbsp;&nbsp;&nbsp;&nbsp; &gt;&nbsp;&nbsp;&nbsp;&nbsp; &lt;=&nbsp;&nbsp;&nbsp; &gt;=&nbsp;&nbsp;&nbsp; ~=&nbsp;&nbsp;&nbsp; ==<br>&nbsp;&nbsp;&nbsp;&nbsp; .. (字符串连接)<br>&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; not&nbsp;&nbsp; #(<span style="COLOR: red">lua5.1 取长度运算</span>)&nbsp;&nbsp;&nbsp;&nbsp; - (一元运算)<br>&nbsp;&nbsp;&nbsp;&nbsp; ^</td>
        </tr>
    </tbody>
</table>
和C语言一样，括号可以改变优先级。<br><br>III.&nbsp; 关键字<br>　　关键字是不能做为变量的。Lua的关键字不多，就以下几个：<br>&nbsp;&nbsp;&nbsp;&nbsp;
<table style="WIDTH: 426px; BORDER-COLLAPSE: collapse; HEIGHT: 105px" cellSpacing=0 cellPadding=3 border=1>
    <tbody>
        <tr>
            <td>and</td>
            <td>break</td>
            <td>do</td>
            <td>else</td>
            <td>elseif</td>
            <td></td>
        </tr>
        <tr>
            <td>end</td>
            <td>false</td>
            <td>for</td>
            <td>function</td>
            <td>if</td>
            <td></td>
        </tr>
        <tr>
            <td>in</td>
            <td>local</td>
            <td>nil</td>
            <td>not</td>
            <td>or</td>
            <td></td>
        </tr>
        <tr>
            <td>repeat</td>
            <td>return</td>
            <td>then</td>
            <td>true</td>
            <td>until</td>
            <td>while</td>
        </tr>
    </tbody>
</table>
<br>IV.&nbsp; 变量类型<br>　　怎么确定一个变量是什么类型的呢？大家可以用type()函数来检查。Lua支持的类型有以下几种：<br>
<table style="WIDTH: 758px; BORDER-COLLAPSE: collapse; HEIGHT: 143px" cellSpacing=0 cellPadding=3 border=1>
    <tbody>
        <tr>
            <td style="WIDTH: 74px">Nil</td>
            <td>空值，所有没有使用过的变量，都是nil。nil既是值，又是类型。</td>
        </tr>
        <tr>
            <td>Boolean</td>
            <td>布尔值，只有两个有效值：true和false</td>
        </tr>
        <tr>
            <td>Number</td>
            <td>数值，在Lua里，数值相当于C语言的double</td>
        </tr>
        <tr>
            <td>String</td>
            <td>字符串，如果你愿意的话，字符串是可以包含"\0"字符的（这和C语言总是以"\0"结尾是不一样的）</td>
        </tr>
        <tr>
            <td>Table</td>
            <td>关系表类型，这个类型功能比较强大，请参考后面的内容。</td>
        </tr>
        <tr>
            <td>Function</td>
            <td>函数类型，不要怀疑，函数也是一种类型，也就是说，所有的函数，它本身就是一个变量。</td>
        </tr>
        <tr>
            <td>Userdata</td>
            <td>嗯，这个类型专门用来和Lua的宿主打交道的。宿主通常是用C和C++来编写的，在这种情况下，Userdata可以是宿主的任意数据类型，常用的有Struct和指针。</td>
        </tr>
        <tr>
            <td>Thread</td>
            <td><span style="TEXT-DECORATION: line-through">线程类型，在Lua中没有真正的线程。Lua中可以将一个函数分成几部份运行。</span>如果感兴趣的话，可以去看看Lua的文档。<br>现在回过头来看看，倒觉得不是线程类型。反而象是用来做遍历的，象是Iterator函数。<br>如：<br>
            <div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000">&nbsp;range(n)<br>&nbsp; <span style="COLOR: #2000ff">local</span> i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">(i&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">&nbsp;n)&nbsp;</span><span style="COLOR: #0000ff">do</span><span style="COLOR: #000000"></span> <br>&nbsp;&nbsp;&nbsp; coroutine.yield( i )<br><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;i&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">end</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">end</span></div>
            可惜的是要继续运行，需要coroutine.resume函数，有点鸡肋。请指教。<br></td>
        </tr>
    </tbody>
</table>
<br>V.&nbsp; 变量的定义<br>　　所有的语言，都要用到变量。在Lua中，不管在什么地方使用变量，都不需要声明，并且所有的这些变量总是全局变量，除非我们在前面加上"local"。这一点要特别注意，因为我们可能想在函数里使用局部变量，却忘了用local来说明。<br>　　至于变量名字，它是大小写相关的。也就是说，A和a是两个不同的变量。<br>　　定义一个变量的方法就是赋值。"＝"操作就是用来赋值的<br>　　我们一起来定义几种常用类型的变量吧。<br>　　A.&nbsp; Nil<br>　　　　正如前面所说的，没有使用过的变量的值，都是Nil。有时候我们也需要将一个变量清除，这时候，我们可以直接给变量赋以nil值。如：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">　　　　var1</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">nil&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">&nbsp;请注意&nbsp;nil&nbsp;一定要小写</span></div>
<br>　　B.&nbsp; Boolean<br>　　　　布尔值通常是用在进行条件判断的时候。布尔值有两种：true 和 false。在Lua中，只有false和nil才被计算为false，而所有任何其它类型的值，都是true。比如0，空串等等，都是true。不要被 C语言的习惯所误导，0在Lua中的的确确是true。你也可以直接给一个变量赋以Boolean类型的值，如：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">　　　　theBoolean&nbsp;</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">&nbsp;true</span></div>
<br>　　C.&nbsp; Number<br>　　　　在Lua中，是没有整数类型的，也不需要。一般情况下，只要数值不是很大（比如不超过100,000,000,000,000），是不会产生舍入误差的。在WindowsXP能跑的当今主流PC上，实数的运算并不比整数慢。<br>　　　　实数的表示方法，同C语言类似，如：<br>　　　　4 0.4 4.57e-3 0.3e12 5e+20<br><br>　　D.&nbsp; String<br>　　　　字符串，总是一种非常常用的高级类型。在Lua中，我们可以非常方便的定义很长很长的字符串。<br>　　　　字符串在Lua中有几种方法来表示，最通用的方法，是用双引号或单引号来括起一个字符串的，如：<br>　　　　"That's go!"<br>　　　　或<br>　　　　'Hello world!'<br><br>　　　　和C语言相同的，它支持一些转义字符，列表如下：<br>　　　　\a&nbsp; bell<br>　　　　\b&nbsp; back space<br>　　　　\f&nbsp; form feed<br>　　　　\n&nbsp; newline<br>　　　　\r&nbsp; carriage return<br>　　　　\t&nbsp; horizontal tab<br>　　　　\v&nbsp; vertical tab<br>　　　　\\&nbsp; backslash<br>　　　　\"&nbsp; double quote<br>　　　　\"&nbsp; single quote<br>　　　　\[&nbsp; left square bracket<br>　　　　\]&nbsp; right square bracket<br><br>　　　　由于这种字符串只能写在一行中，因此，不可避免的要用到转义字符。加入了转义字符的串，看起来实在是不敢恭维，比如：<br>　　　　"one line\nnext line\n\"in quotes\", "in quotes""<br>　　　　一大堆的"\"符号让人看起来很倒胃口。如果你与我有同感，那么，我们在Lua中，可以用另一种表示方法：用"[["和"]]"将多行的字符串括起来。（<span style="COLOR: red">lua5.1: 中括号中间可以加入若干个"="号，如 [==[ ... ]==]，详见下面示例</span>）<br>　　　　示例：下面的语句所表示的是完全相同的字符串：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">a&nbsp;</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #ff0000">alo\n123"</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #000000"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>a&nbsp;</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">&nbsp;<span style="COLOR: red">"alo\n123\""</span><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>a&nbsp;</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #ff0000">\97lo\10\04923"</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #000000"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>a&nbsp;</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #ff0000">[</span><span style="COLOR: #ff0000">[alo<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>123"</span><span style="COLOR: #ff0000">]</span><span style="COLOR: #000000">]<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>a&nbsp;</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #ff0000">[</span><span style="COLOR: #ff0000">==[<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>alo<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>123"</span><span style="COLOR: #ff0000">]</span><span style="COLOR: #808080">==</span><span style="COLOR: #000000">]</span></div>
<br>　　　　值得注意的是，在这种字符串中，如果含有单独使用的"[["或"]]"就仍然得用"\["或"\]"来避免歧义。当然，这种情况是极少会发生的。<br><br>　　E.&nbsp; Table<br>　　　　关系表类型，这是一个很强大的类型。我们可以把这个类型看作是一个数组。只是C语言的数组，只能用正整数来作索引；在Lua中，你可以用任意类型来作数组的索引，除了nil。同样，在C语言中，数组的内容只允许一种类型；在Lua中，你也可以用任意类型的值来作数组的内容，除了nil。<br>　　　　Table的定义很简单，它的主要特征是用"{"和"}"来括起一系列数据元素的。比如：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">　　　　T1&nbsp;</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">&nbsp;{}&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">&nbsp;定义一个空表</span><span style="COLOR: #008080"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">　　　　T1</span><span style="COLOR: #ff0000">[</span><span style="COLOR: #ff0000">1</span><span style="COLOR: #ff0000">]</span><span style="COLOR: #808080">=</span><span style="FONT-WEIGHT: bold; COLOR: #800000">10</span><span style="COLOR: #000000">&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">&nbsp;然后我们就可以象C语言一样来使用它了。</span><span style="COLOR: #008080"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">　　　　T1</span><span style="COLOR: #ff0000">[</span><span style="COLOR: #ff0000">"John"</span><span style="COLOR: #ff0000">]</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">{Age</span><span style="COLOR: #808080">=</span><span style="FONT-WEIGHT: bold; COLOR: #800000">27</span><span style="COLOR: #000000">,&nbsp;Gender</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">"Male"}<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>　　　　这一句相当于：<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>　　　　T1</span><span style="COLOR: #ff0000">[</span><span style="COLOR: #ff0000">"John"</span><span style="COLOR: #ff0000">]</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">{}&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">&nbsp;必须先定义成一个表，还记得未定义的变量是nil类型吗</span><span style="COLOR: #008080"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">　　　　T1</span><span style="COLOR: #ff0000">[</span><span style="COLOR: #ff0000">"John"</span><span style="COLOR: #ff0000">][</span><span style="COLOR: #ff0000">"Age"</span><span style="COLOR: #ff0000">]</span><span style="COLOR: #808080">=</span><span style="FONT-WEIGHT: bold; COLOR: #800000">27</span><span style="COLOR: #000000"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>　　　　T1</span><span style="COLOR: #ff0000">[</span><span style="COLOR: #ff0000">"John"</span><span style="COLOR: #ff0000">][</span><span style="COLOR: #ff0000">"Gender"</span><span style="COLOR: #ff0000">]</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">"Male"<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>　　　　当表的索引是字符串的时候，我们可以简写成：<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>　　　　T1.John</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">{}<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>　　　　T1.John.Age</span><span style="COLOR: #808080">=</span><span style="FONT-WEIGHT: bold; COLOR: #800000">27</span><span style="COLOR: #000000"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>　　　　T1.John.Gender</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">"Male"<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>　　　　或<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>　　　　T1.John{Age</span><span style="COLOR: #808080">=</span><span style="FONT-WEIGHT: bold; COLOR: #800000">27</span><span style="COLOR: #000000">,&nbsp;Gender</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">"Male"}</span></div>
这是一个很强的特性。<br><br>　　　　在定义表的时候，我们可以把所有的数据内容一起写在"{"和"}"之间，这样子是非常方便，而且很好看。比如，前面的T1的定义，我们可以这么写：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">　　　　T1</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>　　　　{<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>　　　　　　</span><span style="FONT-WEIGHT: bold; COLOR: #800000">10</span><span style="COLOR: #000000">,&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">&nbsp;相当于&nbsp;[1]&nbsp;=&nbsp;10</span><span style="COLOR: #008080"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">　　　　　　</span><span style="COLOR: #ff0000">[</span><span style="COLOR: #ff0000">100</span><span style="COLOR: #ff0000">]</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">&nbsp;</span><span style="FONT-WEIGHT: bold; COLOR: #800000">40</span><span style="COLOR: #000000">,<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>　　　　　　John</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">&nbsp;如果你原意，你还可以写成：["John"]&nbsp;=</span><span style="COLOR: #008080"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">　　　　　　{<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>　　　　　　　　Age</span><span style="COLOR: #808080">=</span><span style="FONT-WEIGHT: bold; COLOR: #800000">27</span><span style="COLOR: #000000">,&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">&nbsp;如果你原意，你还可以写成：["Age"]&nbsp;=27</span><span style="COLOR: #008080"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">　　　　　　　　Gender</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">Male&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">&nbsp;如果你原意，你还可以写成：["Gender"]&nbsp;=Male</span><span style="COLOR: #008080"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">　　　　　　},<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>　　　　　　</span><span style="FONT-WEIGHT: bold; COLOR: #800000">20</span><span style="COLOR: #000000">&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">&nbsp;相当于&nbsp;[2]&nbsp;=&nbsp;20</span><span style="COLOR: #008080"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">　　　　}<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<br>　　　　看起来很漂亮，不是吗？我们在写的时候，需要注意三点：<br>　　　　第一，所有元素之间，总是用逗号"，"隔开；<br>　　　　第二，所有索引值都需要用"["和"]"括起来；如果是字符串，还可以去掉引号和中括号；<br>　　　　第三，如果不写索引，则索引就会被认为是数字，并按顺序自动从1往后编；<br><br>　　　　表类型的构造是如此的方便，以致于常常被人用来代替配置文件。是的，不用怀疑，它比ini文件要漂亮，并且强大的多。<br><br>　　F.&nbsp; Function<br>　　　　函数，在Lua中，函数的定义也很简单。典型的定义如下：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">　　　　</span><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">add</span><span style="COLOR: #000000">(a,b)&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">&nbsp;add&nbsp;是函数名字，a和b是参数名字</span><span style="COLOR: #008080"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">　　　　&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;a</span><span style="COLOR: #808080">+</span><span style="COLOR: #000000">b&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">&nbsp;return&nbsp;用来返回函数的运行结果</span><span style="COLOR: #008080"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">　　　　</span><span style="COLOR: #0000ff">end</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<br>　　　　请注意，return语言一定要写在end之前。假如我们非要在中间放上一句return，那么就应该要写成：do return end。<br>　　　　还记得前面说过，函数也是变量类型吗？上面的函数定义，其实相当于：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">　　　　</span><span style="COLOR: #0000ff">add</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000">&nbsp;(a,b)&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;a</span><span style="COLOR: #808080">+</span><span style="COLOR: #000000">b&nbsp;</span><span style="COLOR: #0000ff">end</span></div>
当重新给add赋值时，它就不再表示这个函数了。我们甚至可以赋给add任意数据，包括nil （这样，赋值为nil，将会把该变量清除）。Function是不是很象C语言的函数指针呢？<br><br>　　　　和C语言一样，Lua的函数可以接受可变参数个数，它同样是用"..."来定义的，比如：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">　　　　</span><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #ff00ff">sum</span><span style="COLOR: #000000">&nbsp;(a,b,<img src="http://www.cnblogs.com/Images/dot.gif">)</span></div>
如果想取得...所代表的参数，可以在函数中访问arg局部变量（表类型）得到 (<span style="COLOR: red">lua5.1: 取消arg，并直接用"..."来代表可变参数了，本质还是arg</span>)。<br>　　　　如 sum(1,2,3,4)<br>　　　　则，在函数中，a = 1, b = 2, arg = {3, 4}&nbsp; (<span style="COLOR: red">lua5.1:&nbsp; a = 1, b = 2, ... = {3, 4}</span>)<br>　　　　更可贵的是，它可以同时返回多个结果，比如：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">　　　　</span><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000">&nbsp;s()<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>　　　　　　</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="FONT-WEIGHT: bold; COLOR: #800000">1</span><span style="COLOR: #000000">,</span><span style="FONT-WEIGHT: bold; COLOR: #800000">2</span><span style="COLOR: #000000">,</span><span style="FONT-WEIGHT: bold; COLOR: #800000">3</span><span style="COLOR: #000000">,</span><span style="FONT-WEIGHT: bold; COLOR: #800000">4</span><span style="COLOR: #000000"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>　　　　</span><span style="COLOR: #0000ff">end</span><span style="COLOR: #000000"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>　　　　a,b,c,d&nbsp;</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">&nbsp;s()&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">&nbsp;此时，a&nbsp;=&nbsp;1,&nbsp;b&nbsp;=&nbsp;2,&nbsp;c&nbsp;=&nbsp;3,&nbsp;d&nbsp;=&nbsp;4</span><span style="COLOR: #008080"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<br>　　　　前面说过，表类型可以拥有任意类型的值，包括函数！因此，有一个很强大的特性是，拥有函数的表，哦，我想更恰当的应该说是对象吧。Lua可以使用面向对象编程了。不信？举例如下：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">　　　　t&nbsp;</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>　　　　{<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>　　　　&nbsp;Age&nbsp;</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">&nbsp;</span><span style="FONT-WEIGHT: bold; COLOR: #800000">27</span><span style="COLOR: #000000"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>　　　　&nbsp;</span><span style="COLOR: #0000ff">add</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000">(self,&nbsp;n)&nbsp;self.Age&nbsp;</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">&nbsp;self.Age</span><span style="COLOR: #808080">+</span><span style="COLOR: #000000">n&nbsp;</span><span style="COLOR: #0000ff">end</span><span style="COLOR: #000000"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>　　　　}<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>　　　　</span><span style="COLOR: #0000ff">print</span><span style="COLOR: #000000">(t.Age)&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">&nbsp;27</span><span style="COLOR: #008080"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">　　　　t.</span><span style="COLOR: #0000ff">add</span><span style="COLOR: #000000">(t,&nbsp;</span><span style="FONT-WEIGHT: bold; COLOR: #800000">10</span><span style="COLOR: #000000">)<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>　　　　</span><span style="COLOR: #0000ff">print</span><span style="COLOR: #000000">(t.Age)&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">&nbsp;37</span></div>
<br>　　　　不过，t.add(t,10) 这一句实在是有点土对吧？没关系，在Lua中，我们可以简写成：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">　　　　t:</span><span style="COLOR: #0000ff">add</span><span style="COLOR: #000000">(</span><span style="FONT-WEIGHT: bold; COLOR: #800000">10</span><span style="COLOR: #000000">)&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">&nbsp;相当于&nbsp;t.add(t,10)</span></div>
<br>　　G.&nbsp; Userdata 和 Thread<br>　　　　这两个类型的话题，超出了本文的内容，就不打算细说了。<br><br>VI.&nbsp; 结束语<br>　　就这么结束了吗？当然不是，接下来，我们需要用Lua解释器，来帮助理解和实践了。相信这样会更快的对Lua上手了。<br>　　就象C语言一样，Lua提供了相当多的标准函数来增强语言的功能。使用这些标准函数，可以很方便的操作各种数据类型，并处理输入输出。有关这方面的信息，我们可以参考《Programming in Lua 》一书，也可以在网络上直接观看电子版，网址为：<a href="http://www.lua.org/pil/index.html"><u><font color=#0000ff>http://www.lua.org/pil/index.html</font></u></a><br>　　<br>备注：本文的部份内容摘、译自lua随机文档。<br>相关链接：<br>1. Lua 官方网站： <a href="http://www.lua.org/"><u><font color=#0000ff>http://www.lua.org</font></u></a> <br>2. Lua Wiki网站，你可以在这里找到很多相关的资料，如文档、教程、扩展，以及C/C++的包装等： <a href="http://lua-users.org/wiki/"><u><font color=#0000ff>http://lua-users.org/wiki/</font></u></a><br>3. Lua 打包下载（包括各种平台和编译器的工程文件如vs2003,vs2005）：http://luabinaries.luaforge.net/download.html<br><br>这是我编译好的Lua5.02的解释器：<a href="http://files.cnblogs.com/ly4cn/lua.zip"><u><font color=#0000ff>http://files.cnblogs.com/ly4cn/lua.zip</font></u></a> <script type=text/javascript>
if ($ != jQuery) {
$ = jQuery.noConflict();
}
</script>
<img src ="http://www.cppblog.com/singohgod/aggbug/133676.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/singohgod/" target="_blank">大宝天天见</a> 2010-11-15 17:05 <a href="http://www.cppblog.com/singohgod/archive/2010/11/15/133676.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转载]大型上市游戏公司重要职能架构</title><link>http://www.cppblog.com/singohgod/archive/2010/09/17/126834.html</link><dc:creator>大宝天天见</dc:creator><author>大宝天天见</author><pubDate>Fri, 17 Sep 2010 02:40:00 GMT</pubDate><guid>http://www.cppblog.com/singohgod/archive/2010/09/17/126834.html</guid><wfw:comment>http://www.cppblog.com/singohgod/comments/126834.html</wfw:comment><comments>http://www.cppblog.com/singohgod/archive/2010/09/17/126834.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/singohgod/comments/commentRss/126834.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/singohgod/services/trackbacks/126834.html</trackback:ping><description><![CDATA[<strong>大型上市游戏公司重要职能架构 - 新好<br><br></strong>作者：新好<br>博客：<a href="http://blog.sina.com.cn/u/1054908282?retcode=0" target=_blank><u><font color=#0000ff>http://blog.sina.com.cn/u/1054908282?retcode=0</font></u></a>
<p>&#160;</p>
<p><strong>首席执行官【CEO】</strong></p>
<p>美国人在20世纪60年代进行公司治理结构改革创新时的产物、它的出现在某种意义上代表着将原来董事会手中一些决策权过渡到经营层手中、CEO概念最早出现在一些网络企业。在那里CEO往往是自封的、也很少有人去研究这一称谓对企业到底意味着什么。但是，当&#8220;CEO&#8221;在中国叫得越来越响时候、高层人员称谓改变不是一件小事、设立CEO职位不仅仅是对时尚追赶。事实上，CEO做的事情重点在于&#8220;执行&#8221;。大多数中国公司往往CEO做的事情恰恰不是&#8220;执行&#8221;，更像是&#8220;董事长&#8221;。</p>
<p><br><strong>首席财政官或财务总监【CFO】</strong></p>
<p>现代公司中最重要、最有价值顶尖管理职位之一、掌握着企业神经系统(财务信息)和血液系统(现金资源)灵魂人物。做一名成功CFO需要具备丰富金融理论知识和实务经验。公司理财与金融市场交互、项目估价、风险管理、产品研发、战略规划、企业核心竞争力识别与建立及洞悉信息技术及电子商务对企业冲击等都是CFO职责范围内事。大型公司运作中CFO是穿插在金融市场操作和公司内部财务管理之间角色。担当CFO人才大多是拥有多年在金融市场驰骋经验的人。在美国优秀的CFO常常在华尔街做过成功基金经理人。</p>
<p><br><strong>首席营运官【COO】</strong></p>
<p>负责公司日常营运、辅助CEO工作。一般来讲COO负责公司职能管理组织体系建设、并代表CEO处理企业日常职能事务。如公司未设有总裁职务则COO还要承担整体业务管理职能、主管企业营销与综合业务拓展、负责建立公司整个销售策略与政策、组织生产经营、协助CEO制定公司业务发展计划、对公司经营绩效进行考核。也有把运营总监称呼为COO的。</p>
<p><br><strong>首席市场官【CMO】</strong></p>
<p>指市场总监</p>
<p><br><strong>首席技术官【CTO】</strong></p>
<p>技术总监</p>
<p><br><strong>销售总监【CSO】</strong></p>
<p>渠道销售总监</p>
<p><br><strong>公关总监【CPO】</strong></p>
<p>政府事务、媒体、重要公司与人物公共关系，主要是搞定人。</p>
<p><br><strong>首席信息官【CIO】</strong></p>
<p>大多数公司把这个职位变成了盯人盯票，有点象明朝时候的&#8220;东厂&#8221;，所以说中国是个很神奇的国家。</p>
<p><br><strong>开发总监【CDO】</p>
<p>人事总监 【CHO】</p>
<p>首席品牌官【CBO】</p>
<p>首席文化官【CCO】</p>
<p>首席知识官【CKO】</p>
<p>首席谈判官【CNO】</p>
<p>质量总监【CQO】</p>
<p>评估总监【CVO】</p>
<p><br>首席发言人【CAO】</strong></p>
<p>专门负责解答媒体、债权人和用户等有关问题询问。</p>
<p><br><strong>首席商业计划官【CBO】</strong></p>
<p>首席财务官助理之一、专门针对不同投资人制订相应BP。</p>
<p><br><strong>首席成本控制官【CCO】</strong></p>
<p>凡超过XXXX元以上支出必须由CC0批准。</p>
<p><br><strong>首席域名官【CDO】</strong></p>
<p>负责公司域名注册、网站清盘时域名拍卖、域名法律纠纷等相关问题。</p>
<p><br><strong>首席交换官【CEO】</strong></p>
<p>一般由国际CEO自由联盟随时更换、常设短期职能岗位、类似足球教练。</p>
<p><br><strong>首席方针制订官【CGO】</strong></p>
<p>规划公司宏伟蓝图、一般是5年以后目标。</p>
<p><br><strong>首席协调官【CHO】</strong></p>
<p>调解投资者和经营者之间的冲突、确保公司内部矛盾不要泄露。</p>
<p><br><strong>首席检查官【CIO】</strong></p>
<p>检查公司内部工作状况、监督员工工作态度。</p>
<p><br><strong>首席执法官【CJO】</strong></p>
<p>解决内部劳资纠纷、包括员工对降薪、辞退补偿等所引起问题。</p>
<p><br><strong>网络连接专员【CKO】</strong></p>
<p>最繁忙的岗位之一、当中国电信网络连接中断时及时向员工通报。</p>
<p><br><strong>首席律师【CLO】</strong></p>
<p>负责公司被控侵权时应诉以及各种合同文本审核。主要是灭人的打手。</p>
<p><br><strong>首席媒体官【CMO】</strong></p>
<p>保持和媒体之间友好关<span style="DISPLAY: none; FONT-SIZE: 0px">[来源：GameRes.com]</span>系为公司随时发布新闻做准备，类似首席代表。</p>
<p><br><strong>首席新闻官【CNO】</strong></p>
<p>向媒体披露公司被黑、裁员、被收购等重大新闻。一般由公司市场总监担任，类似政府部门新闻发言人，主要由司长级部门领导担任，公司声音的统一出口。</p>
<p><br><strong>首席隐私官【CPO】</strong></p>
<p>负责公司内部员工Email、ICQ、OICQ等通信内容监控。</p>
<p><br><strong>数量指标编造专家【CQO】</strong></p>
<p>负责注册用户数量、页面浏览、营业收入等指标编造。</p>
<p><br><strong>首席裁员官【CRO】</strong></p>
<p>负责与裁员有关事务、直接向股东大会负责、包括董事长在内都不得干预工作。</p>
<p><br><strong>首席战略官【CSO】</strong></p>
<p>由已经退位公司主要创建人担任，在政府机关一般称为调研员或顾问。</p>
<p><br><strong>首席联盟官【CUO】</strong></p>
<p>以战略联盟名义专门寻找有收购自己意向的公司。</p>
<p><br><strong>投资者关系【CVO】</strong></p>
<p>首席财务官另一重要助理。</p>
<p><br><strong>首席网络写手【CWO】</strong></p>
<p>负责将小事扩大化、通过炒作达到扩大公司名度目的，御用文人，比如给陈天桥，史玉柱编故事，造神。</p>
<p><br><strong>形象代言人【CXO】</strong></p>
<p>（中国特有）一般由学历不高且没有什么网络知识的年轻人担任。</p>
<p><br><strong>公司元老【CYO】</strong></p>
<p>荣誉称号授予在公司工作满X年员工（通常空缺）。<br></p>
<img src ="http://www.cppblog.com/singohgod/aggbug/126834.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/singohgod/" target="_blank">大宝天天见</a> 2010-09-17 10:40 <a href="http://www.cppblog.com/singohgod/archive/2010/09/17/126834.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转载]网游数据解释</title><link>http://www.cppblog.com/singohgod/archive/2010/09/17/126833.html</link><dc:creator>大宝天天见</dc:creator><author>大宝天天见</author><pubDate>Fri, 17 Sep 2010 02:38:00 GMT</pubDate><guid>http://www.cppblog.com/singohgod/archive/2010/09/17/126833.html</guid><wfw:comment>http://www.cppblog.com/singohgod/comments/126833.html</wfw:comment><comments>http://www.cppblog.com/singohgod/archive/2010/09/17/126833.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/singohgod/comments/commentRss/126833.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/singohgod/services/trackbacks/126833.html</trackback:ping><description><![CDATA[<strong>做网游的,当然要懂点这些知识<br><br>网游数据解释<br><br></strong>作者：新好<br>博客：<a href="http://blog.sina.com.cn/u/1054908282?retcode=0" target=_blank><u><font color=#0000ff>http://blog.sina.com.cn/u/1054908282?retcode=0</font></u></a>
<p>&#160;</p>
<p><font color=#ff0000>【用户数量--注册用户】</font>不同项目注册用户质量完全不同，运营商给出不真实数据，那数据调查报告真实性呢？根本没有明白用户质量的意义。<br><br><font color=#ff0000>【在线人数】【最高在线】</font>某个时间能达到的最高在线。<br><br><font color=#ff0000>【活跃人数】</font>具有欺骗性的数字，必须是&#8220;每日活跃用户&#8221;&#8220;每周活跃用户&#8221;&#8220;每月活跃用户&#8221;&#8220;每季活跃用户&#8221;&#8220;最近多少天内活跃用户&#8221;等。在这段时间内进入游戏的人。<br><br><font color=#ff0000>【每个活跃用户平均在线时间】</font>上面说了活跃用户数，如果没有本数据上面那个也没有意义、每个用户都在线2分钟马上就下线，活跃用户价值是多少呢？能和上线就十几个小时在线玩家等值么？</p>
<p><br><font color=#ff0000>【游戏平均在线人数】</font><br>1、24小时内平均在线人数，数据采样时间越密集越精确。</p>
<p>2、不同游戏每个平均在线是由不同数量用户造就的。一个好游戏可以大量粘住玩家长时间舍不得下线。</p>
<p>3、如果活跃用户每次上线平均在线6小时，那么需要4个活跃用户增加1个平均在线，如每次只让用户玩游戏5分钟就走了，哪怕游戏非常好用户每天都上来5分钟，那么必须有60/5*24=288个活跃用户才能达到1个平均在线人数。要根据情况判断推广活跃用户容易，还是增加游戏粘着更容易。</p>
<p><br><font color=#ff0000>【平均在线、总注册用户、活跃人数及最高在线比例】</font><br>曾经有专家说是xxxx是4%，xxxx是8.7%等，他们可能针对某款能接触到的网游数据而来，如果不知道数据是在什么条件下产生的，每款产品都不一样、比例随着不同市场、不同产品、不同渠道、不同服务会导致精确数据和比例完全不一样。哪怕一模一样产品都可能完全不一样数据，别人注册100万用户能有3万在线，不代表你宣传注册100万也有3万。各方面细节太多，资本家很少全面看成功创业者所付出的努力。</p>
<p><br><font color=#ff0000>【Arpu值定义之争】</font><br>1、有人说是每个消费用户的每日花费。<br>2、有人说是每个活跃用户的每月花费。<br>3、上市公司财报数据定义：产品毛收益=平APA/arpu，要么增加APA数量，要么增加ARPU。对于运营商要根据多少平均在线确定服务器、带宽、客户服务、需要多少推广成本才能累计平均在线等运营成本。<br><br><font color=#ff0000>【收费模式固定值】</font><br>很好算：每小时4毛（或点卡定价）*24小时*30天=288元/月，一款百万在线收费网游大致收入是1000000*288，每月2.88亿毛收入（有很多小数字，如免费使用期用户比例导致真实值减少、各种因素导致免费游戏用户比例导致真实收入减少、用户购买点卡很多人没用完导致真实收入增多，渠道压了货最后没有退导致收入增多等）。</p>
<p><br><font color=#ff0000>【免费制动态arpu值】</font><br>1、大多数网游都在学习免费模式，利用收费道具等盈利，arpu值大小关系到生存的重要指标。</p>
<p>2、很多愣头青听见大师宣传免费模式，连免费模式数据都不清楚情况下凭感觉坚定认为免费模式是潮流、趋势。陈天桥不看产品数据，道具收费增加到可替代收费模式，就凭灵光一闪把每季度几亿时间点卡给扔了？看到这两年来盛大从免费模式赚取超过收费模式还是有瑕疵的，至少在线人数没有按盛大想象的大幅度增加。</p>
<p><br><font color=#ff0000>【收费制】</font><br>推广1个收费制游戏在线用户远比推广N个免费游戏在线用户更加困难，免费模式arpu值大于收费模式时，自然免费模式要比收费模式更好。<br><br><font color=#ff0000>【推广成本】</font><br>1、打算花多少钱宣传推广产品。<br>2、除了资金还要考虑人力成本和时间成本。<br>3、仔细计算每个在线用户推广成本，花多少钱才能增加1个平均在线。<br>4、大部分情况下1个平均在线arpu值低于1个平均在线推广成本。如能找到廉价推广方式增加在线，费用低于用户arpu值，别犹豫赶紧推广吧。<br><br><font color=#ff0000>【推广效果】</font><br>1、作为市场人员是掌握每种营销方式效果数据。有多少人能看到广告A，有多少目标用户看到广告、引起多少目标用户记住、让多少目标用户感兴趣、多少用户尝试、剩下是产品本身和客户服务的事。对个市场来说撒谎不是缺点、无法让更多用户来尝试产品才是失败。</p>
<p>2、注意以上部分数据，不要轻易相信广告商瞎吹，自己掌握的数据才是最真实不会欺骗你的。</p>
<p>3、精确掌握各种营销方式效果数据，相信你不会随便乱花钱，拍着脑瓜子就上一些性价比不合适的广告。</p>
<p><br><font color=#ff0000>【市场潜力分级】</font><br>不要定义一个遥不可及的市场目标，例如全世界有多少人，每个人都需要住房，而你是个有房地产想法的年轻人，你告诉别人你的市场目标是多少亿亿全球用户的房产。这样目标是没有意义的。可执行的目标是很重要的，只要是可执行哪怕在旁人眼里看起来很狂妄，也没有什么不可以。</p>
<p><br><font color=#ff0000>【运营网络游戏一定要知道分级】</font><br>1. 可以直接推广到的那些人？手把手，或者通过你的个人媒体（言传身教）<br>2. 能在你所拥有预算内控制哪些媒体，做哪些事情，有多少用户会因为怎样宣传内容而尝试<br>3. 还有哪些资源，哪些朋友支持，帮助，在你所拥的预算内能帮你打开哪些市场。<br>4. 人才，能否找到比你更优秀的人才、专家帮助你宣传、推广扩大市场</p>
<p><br><font color=#ff0000>【用户群分级举例】</font><br>1、非常关注你的产品网游用户最可能成为你的用户<br>2、宣传推广并引起他们注意的网络游戏用户<br>3、到处寻找新游戏的网络游戏用户<br>4、同类网络游戏的用户<br>5、异类网络游戏的用户</p>
<p><br><font color=#ff0000>【所有人】</font>以上分级不一定准确，不一定适合你，对于你很可能每级需要投入成本不一样，没有史玉柱两个亿就不要开始把目标用户定义为所有人而去打全国广告，否则会发现投入成本一定收不回来。</p>
<p><br><font color=#ff0000>【目标市场定义】</font><br>1、每个人都想产品占领最大最多市场，由各方面条件有限必须按对市场分级，分析目前阶段能覆盖目标市场。</p>
<p>2、近两年很火红海和蓝海概念。<br><br>3、准确定位市场、细分市场目的是降低市场推广成本，增加推广有效程度。如果有足够的推广成本，你自然可以多做泛媒体，广大增加知名度，宣传面。</p>
<p><br><font color=#ff0000>【流失率】</font>很容易被遗忘却异常重要，决定游戏生死重要数据，市场推广好不容易拉的玩家留不留得住。<br><font color=#ff0000>【初期流失率】</font>尝试用户转变为成熟活跃用户，所需耗费的时间<br><font color=#ff0000>【自然流失率】</font>成熟活跃用户自然流失率，产品好坏，内涵丰富最大程度决定着自然流失率高低。</p>
<p><br>1、产品本身有很多问题将会带来非常高自然流失率，产品的画面、操作、各方面细节都是关系到产品品质直接开发因素。</p>
<p>2、很多游戏人都分析《梦幻西游》从技术<span style="DISPLAY: none; FONT-SIZE: 0px">[来源：GameRes.com]</span>层面完全没有优势产品为何黏着度那么高，流失率那么低。游戏内涵是最重要的因素，这关系到游戏生命周期。如果玩家把所有内容都全部玩到需要5个月，那么5个月就是网络游戏每个用户生命周期，当玩家感觉没有可玩内容时他自然会离开。有的游戏是可以让玩家玩几年还有新内容，有的游戏虽然好但是生命周期短。现在有越来越多游戏学会利用循环任务，或随即生成任务增加生命周期<br>3、网游开发者不要冲着简单新概念做游戏，不是做噱头，做有内涵的好游戏，充分利用你的技术团队实现效果，而不是盲目专门搞效果搞噱头，让用户乐意留在游戏里面。</p>
<p><br><font color=#ff0000>【客户服务】</font>很重要作用是减少流失率，没有客户服务游戏将不可避免扩大流失率，流失率大神仙也没得救。盛大第一笔收入用来建立客户服务中心为了什么？商业数据上说就是降低流失率。</p>
<p><br><font color=#ff0000>【线上活动】</font>通过活动（可能是新任务、策划活动、客服执行活动）临时性增加拉高在线，减缓或阻止短时间内玩家流失。</p>
<p><br><font color=#ff0000>【用户自然增长率】</font>在推广下增加1个平均在线成本低于【用户arpu值】*【平均每个用户生命周期】。可以不断持续增加用户情况下、新进入玩家大于产品流失率就进入滚雪球效应了。大多数产品一停止大规模推广成本投入流失率都远大于增长率。很多项目在初期炒作后很快用户数量陆续流失，最后不得不倒闭的原因。</p>
<p><br><font color=#ff0000>【收入潜力值】</font>和arpu值矛盾的值，arpu值越低证明潜力越大，arpu值越高反而说明相同用户数量下收入增长潜力小。有些公司（还没找到盈利模式却有较多用户的网站或游戏）把这个作为他们的未来卖点。</p>
<p><br><font color=#ff0000>【更多细节数据】</font>做好游戏不仅仅看结果型数据，更多对于开发策划要看过程走向型数据。</p>
<p><br><font color=#ff0000>【例如】</font><br>1、有些数据可以告诉你在推广过程中哪个环节流失用户最多。<br><br>2、有些数据可以告诉你、玩家喜欢哪些系统，讨厌什么。无论喜爱还是讨厌都比不过【态度失败】漠不关心、死鸭子嘴硬。玩家对精心策划的内容漠不关心，这是最失败的策划。</p>
<p>3、有些数据可以告诉哪些收费是玩家能够接受的（尽管有些收费内容，玩家可能永远会骂，但每天都有大量用户在付费，有些收费看起来没人骂，实际上根本没有人使用，都要通过运营数据分析）。<br><br>4、有些数据可以很清楚告诉你用户在刷钱、在作弊、在利用漏洞、在用外挂、修改封包。如果有自动化数据分析技术几乎可以发现众多玩家作弊。注意只是发现，能否解决还取决于高层重视态度及技术人员能力和速度，要知道而这些问题几乎导致了大量游戏死亡。</p>
<p>5、数据很清楚告诉你游戏经济体制是否稳固，游戏中不断增加的金钱奖励，道具销售是否造成通货膨胀等更多的细节问题。</p>
<img src ="http://www.cppblog.com/singohgod/aggbug/126833.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/singohgod/" target="_blank">大宝天天见</a> 2010-09-17 10:38 <a href="http://www.cppblog.com/singohgod/archive/2010/09/17/126833.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转载]很有参考意义的显卡性能排行榜</title><link>http://www.cppblog.com/singohgod/archive/2010/05/17/115566.html</link><dc:creator>大宝天天见</dc:creator><author>大宝天天见</author><pubDate>Mon, 17 May 2010 02:40:00 GMT</pubDate><guid>http://www.cppblog.com/singohgod/archive/2010/05/17/115566.html</guid><wfw:comment>http://www.cppblog.com/singohgod/comments/115566.html</wfw:comment><comments>http://www.cppblog.com/singohgod/archive/2010/05/17/115566.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/singohgod/comments/commentRss/115566.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/singohgod/services/trackbacks/115566.html</trackback:ping><description><![CDATA[貌似采集于2009年10月左右，还不包括ati5xxx系列<br><br>
<p><font color=#ff6600><font size=3><strong>全部按3DMARK06默认分辨率得分计算.游戏内实际帧数不计算在内(因为NVIDIA和ATI对游戏优化造成得分不公正)</strong></font><font size=3><strong>排名120后的显卡因时间过长无法测试.只按历年来网上评分排名.(所有排名显卡均为官方公板频率测试).</strong></font></font></p>
<p><font color=#ff0000 size=3><strong>001 NVIDIA GTX295<br>002 ATI HD4870X2<br>003 NVIDIA GTX285</strong></font><font color=#ff0000 size=3><strong><br>004 ATI HD4850X2<br>005 NVIDIA GTX280<br>006 ATI HD4870<br>007 NVIDIA GTX260<br>008 ATI HD3870X2<br>009 ATI HD4850<br>010 NVIDIA 9800GTX+=NVIDIA GTX250<br>011 NVIDIA 8800Ultra<br>012 NVIDIA 8800GTX<br>013 NVIDIA 9800GTX<br>014 ATI HD4830<br>015 NVIDIA 8800GT=NVIDIA 9800GT <br>016 NVIDIA 8800GTS<br>017 NVIDIA 8800GS 768M=NVIDIA 9600GSO 768M<br>018 NVIDIA 9600GT 512<br>019 NVIDIA 7950GX2<br>020 ATI HD2900XT<br>021 ATI HD3870<br>022 NVIDIA 8800GS 384M=NVIDIA 9600gso 384M<br>023 ATI X1950XTX <br>024 NVIDIA 7900GTX<br>025 ATI HD3850<br>026 ATI HD4670<br>027 9600GSO 512M<br>028 NVIDIA 9600GT 256<br>029 ATI X1900XTX<br>030 ATI X1950XT <br>031 NVIDIA 7950GT&nbsp;&nbsp;&nbsp;&nbsp; <br>032 ATI 1900XT<br>033 ATI HD3690<br>034 NVIDIA 8600GTS<br>035 NVIDIA 7900GT <br>036 ATI X1800XT <br>037 ATI X1950Pro<br>038 NVIDIA 7800GTX<br>039 NVIDIA 7900GS<br>040 ATI X1950GT <br>041 ATI X1900GT <br>042 ATI X1800XL <br>043 NVIDIA 7800GT <br>044 ATI X850XT/XTPE<br>045 ATI HD3670<br>046 ATI HD4650<br>047 NVIDIA 9500GT<br>048 NVIDIA 8600GT<br>049 ATI HD3650<br>050 ATI X1800GTO <br>051 ATI X800XT/XTPE<br>052 NVIDIA 7600GT&nbsp;&nbsp;&nbsp;&nbsp; <br>053 ATI HD2600XT<br>054 ATI X1650XT<br>055 NVIDIA 6800Ultra<br>056 NVIDIA 6800GT <br>057 NVIDIA 6800GS <br>058 ATI X800XL<br>059 ATI X850Pro <br>060 NVIDIA 6800<br>061 ATI X1650 Pro <br>062 ATI X800pro/GTO <br>063 ATI X1600XT <br>064 NVIDIA 7600GS<br>065 ATI X800SE<br>066 ATI X1300XT<br>067 NVIDIA 8500GT=NVIDIA 9400GT <br>068 ATI X1600Pro&nbsp;&nbsp; <br>069 NVIDIA 7300GT <br>070 NVIDIA 6800XT/LE <br>071 NVIDIA 6600GT <br>072 ATI X700Pro <br>073 ATI 9800XT <br>074 ATI 9800Pro <br>075 ATI 9700Pro <br>076 ATI 9800 <br>077 S3 Chrome S27 <br>078 ATI X700 <br>079 NVIDIA 5950Ultra <br>080 ATI 9700 <br>081 NVIDIA 5900Ultra <br>082 NVIDIA 5800Ultra <br>083 NVIDIA 5900<br>084 NVIDIA 5800 <br>085 ATI X1300Pro <br>086 NVIDIA 8400GS<br>087 ATI HD2400Pro<br>088 NVIDIA 7300GS <br>089 NVIDIA 6600 <br>090 NVIDIA 5900XT <br>091 ATI X1300 <br>092 ATI X600XT <br>093 NVIDIA 7300LE<br>094 NVIDIA TI4800 <br>095 NVIDIA TI4600 <br>096 ATI 9600XT <br>097 NVIDIA TI4800SE <br>098 NVIDIA 5700Ultra <br>099 ATI 9500 256bit <br>100 9800SE 128bit <br>101 ATI X600 <br>102 ATI X550<br>103 ATI 9600Pro <br>104 NVIDIA TI4400 <br>105 ATI 9500Pro<br>106 NVIDIA 6600LE <br>107 ATI X1300SE <br>108 NVIDIA 5700 <br>109 ATI 9600 <br>110 NVIDIA 6200 <br>111 NVIDIA TI4200 <br>112 NVIDIA 5600<br>113 ATI 9550<br>114 NVIDIA 5600XT <br>115 ATI 9600SE <br>116 NVIDIA 5500 <br>117 NVIDIA 7100GS <br>118 ATI X300 <br>119 ATI 9550SE<br>120 NVIDIA 6200A<br>121 ATI 9200Pro <br>122 ATI 9000Pro <br>123 ATI 8500Pro <br>124 NVIDIA GeForce3 TI500 <br>125 ATI 8500 <br>126 ATI 8500LE <br>127 NVIDIA 5200Ultra <br>128 ATI 9200 <br>129 ATI 9250 <br>130 NVIDIA GeForce4 MX460 <br>131 NVIDIA 5200 <br>132 ATI 9000 <br>133 ATI 9200SE <br>134 NVIDIA GeForce3 TI200 <br>135 NVIDIA GeForce3 <br>136 NVIDIA GeForce4 MX 440 <br>137 ATI 7500 <br>138 ATI 7200 <br>139 NVIDIA GeForce2 Ultra <br>140 ATI 7000 <br>141 NVIDIA GeForce2 GTS <br>142 NVIDIA GeForce4 MX 420 <br>143 ATI Radeon <br>144 Voodoo5 5500 <br>145 NVIDIA GeForce2 MX 400 <br>146 NVIDIA GeForce256 <br>147 NVIDIA GeForce2 MX <br>148 Voodoo4 4500 <br>149 NVIDIA TNT2 <br>150 ATI Rage128 Pro <br>151 Voodoo3 <br>152 TNT <br>153 ATI Rage128 <br>154 NVIDIA Riva128 <br>155 ATI Rage3D Pro <br>156 Voodoo Banshee <br>157 Voodoo2 <br>158 NVIDIA Riva <br>159 ATI Rage3D <br>160 Voodoo</strong></font></p>
<img src ="http://www.cppblog.com/singohgod/aggbug/115566.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/singohgod/" target="_blank">大宝天天见</a> 2010-05-17 10:40 <a href="http://www.cppblog.com/singohgod/archive/2010/05/17/115566.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>