﻿<?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++博客-flyonok-随笔分类-linux</title><link>http://www.cppblog.com/flyonok/category/6246.html</link><description /><language>zh-cn</language><lastBuildDate>Sun, 05 Jun 2011 03:54:48 GMT</lastBuildDate><pubDate>Sun, 05 Jun 2011 03:54:48 GMT</pubDate><ttl>60</ttl><item><title>ctags+taglist+cscope</title><link>http://www.cppblog.com/flyonok/archive/2011/06/04/148067.html</link><dc:creator>flyonok</dc:creator><author>flyonok</author><pubDate>Sat, 04 Jun 2011 14:02:00 GMT</pubDate><guid>http://www.cppblog.com/flyonok/archive/2011/06/04/148067.html</guid><wfw:comment>http://www.cppblog.com/flyonok/comments/148067.html</wfw:comment><comments>http://www.cppblog.com/flyonok/archive/2011/06/04/148067.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyonok/comments/commentRss/148067.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyonok/services/trackbacks/148067.html</trackback:ping><description><![CDATA[<div>1.taglist<br />注意：taglist依赖于ctags，所以要先装ctags，否则taglist装了也没法用！<br />（1）将taglist_45.zip解压得到的两个文件夹：doc和plugin 放到 ~/.vim文件夹里面，如果主目录下没有这个隐藏的文件夹，就建一个。<br />（2）<br />plugin/taglist.vim &#8211; taglist插件<br />doc/taglist.txt - taglist帮助文件<br />（3）常用快捷键<br />ctrl＋ww&nbsp;&nbsp;&nbsp; 在列表和源文件中切换<br />ctrl + ] &nbsp;&nbsp;&nbsp; 查看函数定义<br />ctrl + o &nbsp;&nbsp;&nbsp; 返回上一级文件。<br />gf&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 查看头文件<br />gd&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 转到当前光标所指的局部变量的定义处。<br />*&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 转到当前光标所在单词的下一次出现的地方。<br />#&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 转到当前光标所在的单词的上一次出现的地方。<br />&lt;CR&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 跳到光标下tag所定义的位置，用鼠标双击此tag功能也一样&nbsp;&nbsp; <br />o&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在一个新打开的窗口中显示光标下tag&nbsp;&nbsp; <br />&lt;Space&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 显示光标下tag的原型定义&nbsp;&nbsp; <br />u&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 更新taglist窗口中的tag&nbsp;&nbsp; <br />s&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 更改排序方式，在按名字排序和按出现顺序排序间切换&nbsp; <br />x&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; taglist窗口放大和缩小，方便查看较长的tag&nbsp;&nbsp;&nbsp; <br />+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 打开一个折叠，同zoctags常用快捷键ctags常用快捷键&nbsp;&nbsp; <br />-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 将tag折叠起来，同zc&nbsp;&nbsp; <br />*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 打开所有的折叠，同zR&nbsp;&nbsp; <br />=&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 将所有tag折叠起来，同zM&nbsp;&nbsp; <br />[[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 跳到前一个文件&nbsp; <br />]]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 跳到后一个文件 <br />q&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 关闭taglist窗口&nbsp; <br /><br />2.ctags<br />（1）安装ctags ： sudo apt-get install ctags<br />（2）使用<br />ctags -R&nbsp; &nbsp;&nbsp;&nbsp; 对当前目录下的文件递归产生tags文件。<br />ctags file.c<br />（3）在.vimrc文件中添加配置<br />:TlistToggle 或 :Tlist &nbsp;&nbsp;&nbsp; 显示函数列表<br />在.vimrc文件中加上键盘映射<br />map &lt;F8&gt; :Tlist&lt;CR&gt;<br />这样我就可以使用快捷键F8直接进入tlist模式了。这里注意&lt;F8&gt;和 ： 之间有空格的。<br />在.vimrc下加入一下两行<br />set tags=tags;<br />set autochdir<br />这样使用tags时可以首先在当前目录下查找tags文件，如果没有则转到父目录查找。依次向上。<br /><br />查看帮助文件<br />:help helptags<br />:help taglist.txt<br /><br />3.cscope<br />（1）仔细阅读了cscope的手册后发现，原来cscope在产生索引文件时，只搜索类型为 C, lex和yacc的文件(后缀名为.c, .h, .l, .y)，<br />C++的文件根本没有生成索引。不过按照手册上的说明，cscope支持c++和Java语言的文件。<br />于是按照cscope手册上提供的方法，先产生一个文件列表，然后让cscope为这个列表中的每个文件都生成索引。<br />为了方便使用，编写了下面的脚本来更新cscope和ctags的索引文件：<br /><br />&nbsp;#!/bin/sh&nbsp; <br />find&nbsp; . -name "*.h" -o -name "*.c" -o -name "*.cc" &gt; cscope.files&nbsp; <br />cscope&nbsp; -bkq -i cscope.files&nbsp; <br />ctags&nbsp; -R &nbsp;&nbsp;&nbsp; <br />&nbsp;<br />&nbsp;-R : 在生成索引文件时，搜索子目录树中的代码<br />&nbsp;-b : 只生成索引文件，不进入cscope的界面<br />&nbsp;-k : 在生成索引文件时，不搜索 / usr / include目录<br />&nbsp;-q : 生成cscope . in . out和cscope . po . out文件，加快cscope的索引速度<br />将这个脚本保存到/usr/local/bin/cscopes.sh，以后就可以在源代码目录下使用sudo bash cscope.sh命令直接生成索引拉！<br />（2）cscope常用快捷键：<br />先按 ctrl+\ 然后&nbsp; <br />c: 查找该函数被调用的位置&nbsp; <br />d: 查找该函数调用了哪些函数&nbsp; <br />e: 查找指定的正规表达式 f: 查找指定的文件&nbsp; <br />g: 查找指定标识符的定义位置&nbsp; <br />i: 查找该文件在哪些地方被包含&nbsp; <br />s: 查找指定标识符的使用位置&nbsp; <br />t: 查找指定的文本字符串&nbsp; <br /><br />需要上面的快捷键的话，还需要修改/etc/vimrc<br />""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""<br />" CSCOPE settings for vim&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""<br />"<br />" This file contains some boilerplate settings for vim's cscope interface,<br />" plus some keyboard mappings that I've found useful.<br />"<br />" USAGE:<br />" -- vim 6:&nbsp;&nbsp;&nbsp;&nbsp; Stick this file in your ~/.vim/plugin directory (or in a<br />"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'plugin' directory in some other directory that is in your<br />"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'runtimepath'.<br />"<br />" -- vim 5:&nbsp;&nbsp;&nbsp;&nbsp; Stick this file somewhere and 'source cscope.vim' it from<br />"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; your ~/.vimrc file (or cut and paste it into your .vimrc).<br />"<br />" NOTE:<br />" These key maps use multiple keystrokes (2 or 3 keys).&nbsp; If you find that vim<br />" keeps timing you out before you can complete them, try changing your timeout<br />" settings, as explained below.<br />"<br />" Happy cscoping,<br />"<br />" Jason Duell&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jduell@alumni.princeton.edu&nbsp;&nbsp;&nbsp;&nbsp; 2002/3/7<br />""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""<br /><br /><br />" This tests to see if vim was configured with the '--enable-cscope' option<br />" when it was compiled.&nbsp; If it wasn't, time to recompile vim...<br />if has("cscope")<br /><br />&nbsp;&nbsp;&nbsp; """"""""""""" Standard cscope/vim boilerplate<br /><br />&nbsp;&nbsp;&nbsp; " use both cscope and ctag for 'ctrl-]', ':ta', and 'vim -t'<br />&nbsp;&nbsp;&nbsp; set cscopetag<br /><br />&nbsp;&nbsp;&nbsp; " check cscope for definition of a symbol before checking ctags: set to 1<br />&nbsp;&nbsp;&nbsp; " if you want the reverse search order.<br />&nbsp;&nbsp;&nbsp; set csto=0<br /><br />&nbsp;&nbsp;&nbsp; " add any cscope database in current directory<br />&nbsp;&nbsp;&nbsp; if filereadable("cscope.out")<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cs add cscope.out&nbsp; <br />&nbsp;&nbsp;&nbsp; " else add the database pointed to by environment variable<br />&nbsp;&nbsp;&nbsp; elseif $CSCOPE_DB != ""<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cs add $CSCOPE_DB<br />&nbsp;&nbsp;&nbsp; endif<br /><br />&nbsp;&nbsp;&nbsp; " show msg when any other cscope db added<br />&nbsp;&nbsp;&nbsp; set cscopeverbose&nbsp; <br /><br /><br />&nbsp;&nbsp;&nbsp; """"""""""""" My cscope/vim key mappings<br />&nbsp;&nbsp;&nbsp; "<br />&nbsp;&nbsp;&nbsp; " The following maps all invoke one of the following cscope search types:<br />&nbsp;&nbsp;&nbsp; "<br />&nbsp;&nbsp;&nbsp; "&nbsp;&nbsp; 's'&nbsp;&nbsp; symbol: find all references to the token under cursor<br />&nbsp;&nbsp;&nbsp; "&nbsp;&nbsp; 'g'&nbsp;&nbsp; global: find global definition(s) of the token under cursor<br />&nbsp;&nbsp;&nbsp; "&nbsp;&nbsp; 'c'&nbsp;&nbsp; calls:&nbsp; find all calls to the function name under cursor<br />&nbsp;&nbsp;&nbsp; "&nbsp;&nbsp; 't'&nbsp;&nbsp; text:&nbsp;&nbsp; find all instances of the text under cursor<br />&nbsp;&nbsp;&nbsp; "&nbsp;&nbsp; 'e'&nbsp;&nbsp; egrep:&nbsp; egrep search for the word under cursor<br />&nbsp;&nbsp;&nbsp; "&nbsp;&nbsp; 'f'&nbsp;&nbsp; file:&nbsp;&nbsp; open the filename under cursor<br />&nbsp;&nbsp;&nbsp; "&nbsp;&nbsp; 'i'&nbsp;&nbsp; includes: find files that include the filename under cursor<br />&nbsp;&nbsp;&nbsp; "&nbsp;&nbsp; 'd'&nbsp;&nbsp; called: find functions that function under cursor calls<br />&nbsp;&nbsp;&nbsp; "<br />&nbsp;&nbsp;&nbsp; " Below are three sets of the maps: one set that just jumps to your<br />&nbsp;&nbsp;&nbsp; " search result, one that splits the existing vim window horizontally and<br />&nbsp;&nbsp;&nbsp; " diplays your search result in the new window, and one that does the same<br />&nbsp;&nbsp;&nbsp; " thing, but does a vertical split instead (vim 6 only).<br />&nbsp;&nbsp;&nbsp; "<br />&nbsp;&nbsp;&nbsp; " I've used CTRL-\ and CTRL-@ as the starting keys for these maps, as it's<br />&nbsp;&nbsp;&nbsp; " unlikely that you need their default mappings (CTRL-\'s default use is<br />&nbsp;&nbsp;&nbsp; " as part of CTRL-\ CTRL-N typemap, which basically just does the same<br />&nbsp;&nbsp;&nbsp; " thing as hitting 'escape': CTRL-@ doesn't seem to have any default use).<br />&nbsp;&nbsp;&nbsp; " If you don't like using 'CTRL-@' or CTRL-\, , you can change some or all<br />&nbsp;&nbsp;&nbsp; " of these maps to use other keys.&nbsp; One likely candidate is 'CTRL-_'<br />&nbsp;&nbsp;&nbsp; " (which also maps to CTRL-/, which is easier to type).&nbsp; By default it is<br />&nbsp;&nbsp;&nbsp; " used to switch between Hebrew and English keyboard mode.<br />&nbsp;&nbsp;&nbsp; "<br />&nbsp;&nbsp;&nbsp; " All of the maps involving the &lt;cfile&gt; macro use '^&lt;cfile&gt;$': this is so<br />&nbsp;&nbsp;&nbsp; " that searches over '#include &lt;time.h&gt;" return only references to<br />&nbsp;&nbsp;&nbsp; " 'time.h', and not 'sys/time.h', etc. (by default cscope will return all<br />&nbsp;&nbsp;&nbsp; " files that contain 'time.h' as part of their name).<br /><br /><br />&nbsp;&nbsp;&nbsp; " To do the first type of search, hit 'CTRL-\', followed by one of the<br />&nbsp;&nbsp;&nbsp; " cscope search types above (s,g,c,t,e,f,i,d).&nbsp; The result of your cscope<br />&nbsp;&nbsp;&nbsp; " search will be displayed in the current window.&nbsp; You can use CTRL-T to<br />&nbsp;&nbsp;&nbsp; " go back to where you were before the search.&nbsp; <br />&nbsp;&nbsp;&nbsp; "<br /><br />&nbsp;&nbsp;&nbsp; nmap &lt;C-\&gt;s :cs find s &lt;C-R&gt;=expand("&lt;cword&gt;")&lt;CR&gt;&lt;CR&gt;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; nmap &lt;C-\&gt;g :cs find g &lt;C-R&gt;=expand("&lt;cword&gt;")&lt;CR&gt;&lt;CR&gt;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; nmap &lt;C-\&gt;c :cs find c &lt;C-R&gt;=expand("&lt;cword&gt;")&lt;CR&gt;&lt;CR&gt;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; nmap &lt;C-\&gt;t :cs find t &lt;C-R&gt;=expand("&lt;cword&gt;")&lt;CR&gt;&lt;CR&gt;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; nmap &lt;C-\&gt;e :cs find e &lt;C-R&gt;=expand("&lt;cword&gt;")&lt;CR&gt;&lt;CR&gt;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; nmap &lt;C-\&gt;f :cs find f &lt;C-R&gt;=expand("&lt;cfile&gt;")&lt;CR&gt;&lt;CR&gt;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; nmap &lt;C-\&gt;i :cs find i ^&lt;C-R&gt;=expand("&lt;cfile&gt;")&lt;CR&gt;$&lt;CR&gt;<br />&nbsp;&nbsp;&nbsp; nmap &lt;C-\&gt;d :cs find d &lt;C-R&gt;=expand("&lt;cword&gt;")&lt;CR&gt;&lt;CR&gt;&nbsp;&nbsp;&nbsp; <br /><br /><br />&nbsp;&nbsp;&nbsp; " Using 'CTRL-spacebar' (intepreted as CTRL-@ by vim) then a search type<br />&nbsp;&nbsp;&nbsp; " makes the vim window split horizontally, with search result displayed in<br />&nbsp;&nbsp;&nbsp; " the new window.<br />&nbsp;&nbsp;&nbsp; "<br />&nbsp;&nbsp;&nbsp; " (Note: earlier versions of vim may not have the :scs command, but it<br />&nbsp;&nbsp;&nbsp; " can be simulated roughly via:<br />&nbsp;&nbsp;&nbsp; "&nbsp;&nbsp;&nbsp; nmap &lt;C-@&gt;s &lt;C-W&gt;&lt;C-S&gt; :cs find s &lt;C-R&gt;=expand("&lt;cword&gt;")&lt;CR&gt;&lt;CR&gt;&nbsp;&nbsp;&nbsp; <br /><br />&nbsp;&nbsp;&nbsp; nmap &lt;C-@&gt;s :scs find s &lt;C-R&gt;=expand("&lt;cword&gt;")&lt;CR&gt;&lt;CR&gt;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; nmap &lt;C-@&gt;g :scs find g &lt;C-R&gt;=expand("&lt;cword&gt;")&lt;CR&gt;&lt;CR&gt;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; nmap &lt;C-@&gt;c :scs find c &lt;C-R&gt;=expand("&lt;cword&gt;")&lt;CR&gt;&lt;CR&gt;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; nmap &lt;C-@&gt;t :scs find t &lt;C-R&gt;=expand("&lt;cword&gt;")&lt;CR&gt;&lt;CR&gt;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; nmap &lt;C-@&gt;e :scs find e &lt;C-R&gt;=expand("&lt;cword&gt;")&lt;CR&gt;&lt;CR&gt;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; nmap &lt;C-@&gt;f :scs find f &lt;C-R&gt;=expand("&lt;cfile&gt;")&lt;CR&gt;&lt;CR&gt;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; nmap &lt;C-@&gt;i :scs find i ^&lt;C-R&gt;=expand("&lt;cfile&gt;")&lt;CR&gt;$&lt;CR&gt;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; nmap &lt;C-@&gt;d :scs find d &lt;C-R&gt;=expand("&lt;cword&gt;")&lt;CR&gt;&lt;CR&gt;&nbsp;&nbsp;&nbsp; <br /><br /><br />&nbsp;&nbsp;&nbsp; " Hitting CTRL-space *twice* before the search type does a vertical<br />&nbsp;&nbsp;&nbsp; " split instead of a horizontal one (vim 6 and up only)<br />&nbsp;&nbsp;&nbsp; "<br />&nbsp;&nbsp;&nbsp; " (Note: you may wish to put a 'set splitright' in your .vimrc<br />&nbsp;&nbsp;&nbsp; " if you prefer the new window on the right instead of the left<br /><br />&nbsp;&nbsp;&nbsp; nmap &lt;C-@&gt;&lt;C-@&gt;s :vert scs find s &lt;C-R&gt;=expand("&lt;cword&gt;")&lt;CR&gt;&lt;CR&gt;<br />&nbsp;&nbsp;&nbsp; nmap &lt;C-@&gt;&lt;C-@&gt;g :vert scs find g &lt;C-R&gt;=expand("&lt;cword&gt;")&lt;CR&gt;&lt;CR&gt;<br />&nbsp;&nbsp;&nbsp; nmap &lt;C-@&gt;&lt;C-@&gt;c :vert scs find c &lt;C-R&gt;=expand("&lt;cword&gt;")&lt;CR&gt;&lt;CR&gt;<br />&nbsp;&nbsp;&nbsp; nmap &lt;C-@&gt;&lt;C-@&gt;t :vert scs find t &lt;C-R&gt;=expand("&lt;cword&gt;")&lt;CR&gt;&lt;CR&gt;<br />&nbsp;&nbsp;&nbsp; nmap &lt;C-@&gt;&lt;C-@&gt;e :vert scs find e &lt;C-R&gt;=expand("&lt;cword&gt;")&lt;CR&gt;&lt;CR&gt;<br />&nbsp;&nbsp;&nbsp; nmap &lt;C-@&gt;&lt;C-@&gt;f :vert scs find f &lt;C-R&gt;=expand("&lt;cfile&gt;")&lt;CR&gt;&lt;CR&gt;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; nmap &lt;C-@&gt;&lt;C-@&gt;i :vert scs find i ^&lt;C-R&gt;=expand("&lt;cfile&gt;")&lt;CR&gt;$&lt;CR&gt;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; nmap &lt;C-@&gt;&lt;C-@&gt;d :vert scs find d &lt;C-R&gt;=expand("&lt;cword&gt;")&lt;CR&gt;&lt;CR&gt;<br /><br /><br />&nbsp;&nbsp;&nbsp; """"""""""""" key map timeouts<br />&nbsp;&nbsp;&nbsp; "<br />&nbsp;&nbsp;&nbsp; " By default Vim will only wait 1 second for each keystroke in a mapping.<br />&nbsp;&nbsp;&nbsp; " You may find that too short with the above typemaps.&nbsp; If so, you should<br />&nbsp;&nbsp;&nbsp; " either turn off mapping timeouts via 'notimeout'.<br />&nbsp;&nbsp;&nbsp; "<br />&nbsp;&nbsp;&nbsp; "set notimeout<br />&nbsp;&nbsp;&nbsp; "<br />&nbsp;&nbsp;&nbsp; " Or, you can keep timeouts, by uncommenting the timeoutlen line below,<br />&nbsp;&nbsp;&nbsp; " with your own personal favorite value (in milliseconds):<br />&nbsp;&nbsp;&nbsp; "<br />&nbsp;&nbsp;&nbsp; "set timeoutlen=4000<br />&nbsp;&nbsp;&nbsp; "<br />&nbsp;&nbsp;&nbsp; " Either way, since mapping timeout settings by default also set the<br />&nbsp;&nbsp;&nbsp; " timeouts for multicharacter 'keys codes' (like &lt;F1&gt;), you should also<br />&nbsp;&nbsp;&nbsp; " set ttimeout and ttimeoutlen: otherwise, you will experience strange<br />&nbsp;&nbsp;&nbsp; " delays as vim waits for a keystroke after you hit ESC (it will be<br />&nbsp;&nbsp;&nbsp; " waiting to see if the ESC is actually part of a key code like &lt;F1&gt;).<br />&nbsp;&nbsp;&nbsp; "<br />&nbsp;&nbsp;&nbsp; "set ttimeout<br />&nbsp;&nbsp;&nbsp; "<br />&nbsp;&nbsp;&nbsp; " personally, I find a tenth of a second to work well for key code<br />&nbsp;&nbsp;&nbsp; " timeouts. If you experience problems and have a slow terminal or network<br />&nbsp;&nbsp;&nbsp; " connection, set it higher.&nbsp; If you don't set ttimeoutlen, the value for<br />&nbsp;&nbsp;&nbsp; " timeoutlent (default: 1000 = 1 second, which is sluggish) is used.<br />&nbsp;&nbsp;&nbsp; "<br />&nbsp;&nbsp;&nbsp; "set ttimeoutlen=100<br /><br />endif</div><img src ="http://www.cppblog.com/flyonok/aggbug/148067.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyonok/" target="_blank">flyonok</a> 2011-06-04 22:02 <a href="http://www.cppblog.com/flyonok/archive/2011/06/04/148067.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>vim ctags cscope的配合使用阅读源码</title><link>http://www.cppblog.com/flyonok/archive/2011/06/04/148061.html</link><dc:creator>flyonok</dc:creator><author>flyonok</author><pubDate>Sat, 04 Jun 2011 12:58:00 GMT</pubDate><guid>http://www.cppblog.com/flyonok/archive/2011/06/04/148061.html</guid><wfw:comment>http://www.cppblog.com/flyonok/comments/148061.html</wfw:comment><comments>http://www.cppblog.com/flyonok/archive/2011/06/04/148061.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyonok/comments/commentRss/148061.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyonok/services/trackbacks/148061.html</trackback:ping><description><![CDATA[<div>安装：<span style="font-family: AR PL UMing HK,serif;">apt-get install vim&nbsp;&nbsp;&nbsp;&nbsp; <br /> 2.1 </span>基本设置<span style="font-family: AR PL UMing HK,serif;"><br /> &nbsp;&nbsp;&nbsp; * set nocp<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>该命令指定让 <span style="font-family: AR PL UMing HK,serif;">VIM </span>工作在不兼容模式下。 <span style="font-family: AR PL UMing HK,serif;"><br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>而 <span style="font-family: AR PL UMing HK,serif;">VIM </span>里可以使用 <span style="font-family: AR PL UMing HK,serif;">u </span>命令撤消多步操作， &#8220;重复&#8221;使用的快捷键是 <span style="font-family: AR PL UMing HK,serif;">Ctrl + R</span>。<span style="font-family: AR PL UMing HK,serif;"><br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>只有在不兼容模式下， 才能更好地发挥 <span style="font-family: AR PL UMing HK,serif;">VIM </span>自身的特点。 <span style="font-family: AR PL UMing HK,serif;">Bram </span>爷爷强烈推荐大家使用 <span style="font-family: AR PL UMing HK,serif;">VIM </span>的不兼容模式， 滇狐也是这样推荐的。 请务必在你的 <span style="font-family: AR PL UMing HK,serif;">.vimrc </span>中的第一行写上： &#8220;<span style="font-family: AR PL UMing HK,serif;">set nocp&#8221;</span>。<span style="font-family: AR PL UMing HK,serif;"><br /> &nbsp;&nbsp;&nbsp; * set ru<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>该命令打开 <span style="font-family: AR PL UMing HK,serif;">VIM </span>的状态栏标尺。 打开标尺可以给文件的编辑工作带来一定方便。<span style="font-family: AR PL UMing HK,serif;"><br /> &nbsp;&nbsp;&nbsp; * set is<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>搜索时在未完全输入完毕要检索的文本时就开始检索。 <span style="font-family: AR PL UMing HK,serif;"><br /> &nbsp;&nbsp;&nbsp; * syntax on<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>打开关键字上色。 <span style="font-family: AR PL UMing HK,serif;"><br /> &nbsp;&nbsp;&nbsp; * set backspace=indent,eol,start<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>设想这样一个情况： 当前光标前面有若干字母， 我们按下 <span style="font-family: AR PL UMing HK,serif;">i </span>键进入了 <span style="font-family: AR PL UMing HK,serif;">Insert </span>模式， 然后输入了 <span style="font-family: AR PL UMing HK,serif;">3 </span>个字母， 再按 <span style="font-family: AR PL UMing HK,serif;">5 </span>下删除<span style="font-family: AR PL UMing HK,serif;">(Backspace)</span>。 默认情况下， <span style="font-family: AR PL UMing HK,serif;">VIM </span>仅能删除我们新输入的 <span style="font-family: AR PL UMing HK,serif;">3 </span>个字母， 然后喇叭&#8220;嘟嘟&#8221;响两声。 如果我们&#8220;<span style="font-family: AR PL UMing HK,serif;">set backspace=start&#8221;</span>， 则可以在删除了新输入的 <span style="font-family: AR PL UMing HK,serif;">3 </span>个字母之后， 继续向前删除原有的两个字符。<span style="font-family: AR PL UMing HK,serif;"><br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>再设想一个情况：有若干行文字， 我们把光标移到中间某一行的行首， 按 <span style="font-family: AR PL UMing HK,serif;">i </span>键进入 <span style="font-family: AR PL UMing HK,serif;">Insert </span>模式， 然后按一下 <span style="font-family: AR PL UMing HK,serif;">Backspace</span>。默认情况下，喇叭会&#8220;嘟&#8221;一声， 然后没有任何动静。 如果我们&#8220;<span style="font-family: AR PL UMing HK,serif;">set backspace=eol&#8221;</span>， 则可以删除前一行行末的回车，也就是说将两行拼接起来。<span style="font-family: AR PL UMing HK,serif;"><br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>当我们设置了自动缩进后， 如果前一行缩进了一定距离， 按下回车后，下一行也会保持相同的缩进。 默认情况下， 我们不能在 <span style="font-family: AR PL UMing HK,serif;">Insert </span>模式下直接按 <span style="font-family: AR PL UMing HK,serif;">Backspace </span>删除行首的缩进。 如果我们&#8220;<span style="font-family: AR PL UMing HK,serif;">set backspace=indent&#8221;</span>， 则可以开启这一项功能。<span style="font-family: AR PL UMing HK,serif;"><br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>上述三项功能， 你可以根据自己的需要， 选择其中一种或几种， 用逗号分隔各个选项。 建议把这三个选项都选上。<span style="font-family: AR PL UMing HK,serif;"><br /> &nbsp;&nbsp;&nbsp; * set whichwrap=b,s,&lt;,&gt;,[,]<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>默认情况下， 在 <span style="font-family: AR PL UMing HK,serif;">VIM </span>中当光标移到一行最左边的时候， 我们继续按左键， 光标不能回到上一行的最右边。 同样地，光标到了一行最右边的时候，我们不能通过继续按右跳到下一行的最左边。 但是， 通过设置 <span style="font-family: AR PL UMing HK,serif;">whichwrap </span>我们可以对一部分按键开启这项功能。<span style="font-family: AR PL UMing HK,serif;"><br /> &nbsp;&nbsp;&nbsp; <br /> 2 .2</span>文本编辑设置<span style="font-family: AR PL UMing HK,serif;"><br /> <br /> &nbsp;&nbsp;&nbsp; * set sw=4<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>自动缩进的时候， 缩进尺寸为 <span style="font-family: AR PL UMing HK,serif;">4 </span>个空格。<span style="font-family: AR PL UMing HK,serif;"><br /> &nbsp;&nbsp;&nbsp; * set ts=4<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Tab </span>宽度为 <span style="font-family: AR PL UMing HK,serif;">4 </span>个字符。<span style="font-family: AR PL UMing HK,serif;"><br /> &nbsp;&nbsp;&nbsp; <br /> 2.3 </span>断行设置<span style="font-family: AR PL UMing HK,serif;"><br /> <br /> &nbsp;&nbsp;&nbsp; * set lbr<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>不在单词中间断行。 设置了这个选项后， 如果一行文字非常长， 无法在一行内显示完的话， 它会在单词与单词间的空白处断开， 尽量不会把一个单词分成两截放在两个不同的行里。<span style="font-family: AR PL UMing HK,serif;"><br /> &nbsp;&nbsp; <br /> 2.4 C/C++ </span>编码设置<span style="font-family: AR PL UMing HK,serif;"><br /> &nbsp;&nbsp;&nbsp; * set sm<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>显示括号配对情况。 打开这个选项后， 当输入后括号 <span style="font-family: AR PL UMing HK,serif;">(</span>包括小括号、中括号、大括号<span style="font-family: AR PL UMing HK,serif;">) </span>的时候， 光标会跳回前括号片刻， 然后跳回来， 以此显示括号的配对情况。<span style="font-family: AR PL UMing HK,serif;"><br /> &nbsp;&nbsp;&nbsp; * set cin<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>打开 <span style="font-family: AR PL UMing HK,serif;">C/C++ </span>风格的自动缩进。 打开了自动缩进后， 在编码的时候我们可以使用&#8220;<span style="font-family: AR PL UMing HK,serif;">V&#8221;</span>命令选中一段文本后， 按&#8220;<span style="font-family: AR PL UMing HK,serif;">=&#8221;</span>将这段文本重新调整缩进格式， 在一定程度上起到代码美化的作用。<span style="font-family: AR PL UMing HK,serif;"><br /> &nbsp;&nbsp;&nbsp;&nbsp; </span>在粘贴的时候把所有自动缩进都关闭， 粘贴完毕之后再打开。 一个个手工关闭自动缩进未免过于繁琐， <span style="font-family: AR PL UMing HK,serif;">vim </span>为我们提供了一个很好用的命令，只要输入&#8220;<span style="font-family: AR PL UMing HK,serif;">:set paste&#8221;</span>， 就可以关闭所有自动缩进。 粘贴完毕后再输入&#8220;<span style="font-family: AR PL UMing HK,serif;">:set nopaste&#8221;</span>就可以重新打开原有的自动缩进设置了。<span style="font-family: AR PL UMing HK,serif;"><br /> &nbsp;&nbsp;&nbsp; * set cino=:0g0t0(sus<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>设定 <span style="font-family: AR PL UMing HK,serif;">C/C++ </span>风格自动缩进的选项， <span style="font-family: AR PL UMing HK,serif;"><br /> &nbsp; * set ai<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>打开普通文件类型的自动缩进。 该自动缩进不如 <span style="font-family: AR PL UMing HK,serif;">cindent </span>智能， 但它可以为你编辑非 <span style="font-family: AR PL UMing HK,serif;">C/C++ </span>文件提供一定帮助。<span style="font-family: AR PL UMing HK,serif;"><br /> <br /> 2.5 </span>其它设置<span style="font-family: AR PL UMing HK,serif;"><br /> <br /> &nbsp;&nbsp;&nbsp; * set selectmode=<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>不使用 <span style="font-family: AR PL UMing HK,serif;">selectmode</span>。<span style="font-family: AR PL UMing HK,serif;"><br /> &nbsp;&nbsp;&nbsp; * set mousemodel=popup<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>当右键单击窗口的时候， 弹出快捷菜单。<span style="font-family: AR PL UMing HK,serif;"><br /> &nbsp;&nbsp;&nbsp; * set keymodel=<br /> </span>不使用&#8220;<span style="font-family: AR PL UMing HK,serif;">Shift + </span>方向键&#8221;选择文本， &#8220;<span style="font-family: AR PL UMing HK,serif;">Shift + </span>方向键&#8221;代表向指定方向跳一个单词。 如果你喜欢这项功能的话， 可以使用&#8220;<span style="font-family: AR PL UMing HK,serif;">set keymodel=startsel,stopsel&#8221;</span>打开它。<span style="font-family: AR PL UMing HK,serif;"><br /> * set selection=inclusive<br /> </span>指定在选择文本时， 光标所在位置也属于被选中的范围。 如果指定 <span style="font-family: AR PL UMing HK,serif;">selection=exclusive </span>的话， 可能会出现某些文本无法被选中的情况。<span style="font-family: AR PL UMing HK,serif;"><br /> </span><br /> <br />       <br style="clear: both;" />   <div>     <a href="http://oss.lzu.edu.cn/modules/lifetype/index.php?op=ViewArticle&amp;articleId=1014&amp;blogId=1#comments" title="评论">         2 评论    </a> | 		  0 引用 	</div>                  <h2>评论</h2>                   <ol id="commentlist"><li id="comment-578">                 <p>北京臻何沃达机械设备有限公司专业经营<a href="http://www.bjnadella.com/">NADELLA</a>品牌,主要产品包括:<a href="http://www.bjnadella.com/">NADELLA直线导轨</a>,<a href="http://www.bjnadella.com/">NADELLA线性模块</a>,<a href="http://www.bjnadella.com/">NADELLA滚针轴承</a>,<a href="http://www.bjnadella.com/">NADELLA万向接头</a>,<a href="http://www.bjnadella.com/">NADELLA操纵杆</a>,<a href="http://www.bjnadella.com/">NADELLA调节环</a>,<a href="http://www.bjnadella.com/">NADELLA杆头</a>.北京臻何轴承销售有限公司是<a href="http://www.bjnadella.com/">NADELLA轴承</a>在中国华北地区一级经销商,并与欧洲Nadella工厂库存实施共享,及时通过国际物流空运至国内,确保客户在第一时间拿到所需的产品. 电话:010-51288604  传真:010-51288592 网址:www.bjnadella.com</p>                                 	<p><cite>作者                                        <a href="http://www.bjnadella.com/">www.bjnadella.com</a>                     &#8212;                                       21 三月 2011, 04:38                 </cite></p>             </li><li id="comment-256">                 <p>每次都要一条一条复制好麻烦，直接写一个常用，以后配置直接添加就可以了，不要把syntax on前面的"注视掉。</p> <p>set ignorecase		" Do case insensitive matching<br /> "set smartcase		" Do smart case matching<br /> "set incsearch		" Incremental search<br /> "set autowrite		" Automatically save before commands like :next and :make<br /> "set hidden             " Hide buffers when they are abandoned<br /> set mouse=a		" Enable mouse usage (all modes)<br /> set nu<br /> set encoding=utf-8<br /> set fileencoding=chinese<br /> set fileencodings=ucs-bom,utf-8,chinese<br /> set ambiwidth=double<br /> set nocp<br /> set ru<br /> set is<br /> set backspace=indent,eol,start<br /> set whichwrap=b,s,,[,]<br /> set sw=4<br /> set ts=4<br /> set lbr<br /> set sm<br /> set cin<br /> set cino=:0g0t0(sus<br /> set ai<br /> set mousemodel=popup</p></li></ol></div><div><div id="blog_text"><p>在阅读源码的时候一个好的工具能使效率提高很多。在这，关于工具我就不多说了，vim+ctags+cscope,我这里主要想介绍一下，这个组合 工具的一些使用技巧，这里有从网上找到了（在此，谢谢那些前辈们的辛劳），也有自己积累的，总之，记录下来吧。</p> <p>cscope的工作需要 vim、ctags的配合，它们都是基于命令行的。<br /> 下面只是给出了三种工具的常用方法，更多功能可查看man手册，或者官方文档。</p> <p>一、Vim<br /> 参考：<a href="http://oss.lzu.edu.cn/modules/lifetype/index.php?op=ViewArticle&amp;articleId=1014&amp;blogId=1">http://oss.lzu.edu.cn/modules/lifetype/index.php?op=ViewArticle&amp;articleId=1014&amp;blogId=1</a></p> <p> </p> <p>二、Ctags<br /> 安装：</p> <p>aptitude install ctags<br /> 在源代码根目录下执行 ctags -r 命令用来为程序源代码生成标签文件，其-r选项表示递<br /> 归操作，同时为子目录也生成标签文件。vim利用生成的标签文件，可以进行相应检索、并<br /> 在不同的文件C语言元素之间来回切换。</p> <p>在vim中ctags的简单使用<br /> 1) 跳转到指定的函数进入vim后，用 &#8220;:tag func_name&#8220; 跳到函数func_name处。使用tag<br /> 命令时，可以使用TAB键进行匹配查找，继续按TAB键向下切换。<br /> 某个函数有多个定义时</p> <p>:tag<br /> 跳到第一个定义处，优先跳转到当前文件<br /> :tnext<br /> 跳到第一个<br /> :tfirst<br /> 跳到前count个<br /> :[count]tprevious<br /> 跳到后count个<br /> :[count]tnext<br /> 跳到最后一个<br /> :tlast<br /> 你也可以在所有tagname中选择：<br /> :tselect tagname</p> <p>如果想跳到包含block的标识符:&#8220;tag /block&#8221; 然后用TAB键来选择。这里'/'就是告诉vim<br /> 'block'是一个语句块标签。<br /> 2)用&#8220;CTRL + ]&#8220;快捷键，跳转到光标所在函数标识符的定义处。<br /> 3)使用&#8220;CTRL + T&#8221;退回上层。如果想在以write_开头的标识符中选择一下， :tselect /^<br /> write_ 这里，'^'表示开头，同理，'$'表示末尾。多个同名的标识符</p> <p> </p> <p>三、debian默认没有安装cscope</p> <p><br /> 一、安装：atp-get install cscope</p> <p><br /> 运行cscope命令，出现两个面板，上方是一个查找结果的显示面板，下方是一个查找条件<br /> 指定面板。使用TAB键在两个面板间切换，也可使用上下左右方向件和翻页键在同一面板内<br /> 贴换位置。选中显示面板的某个项，回车即可进入该文件，这是调用vim打开文件，这时就<br /> 可以结合ctags使用了。当然也可以直接使用vim打开文件，结合ctags阅读源码。<br /> 使用前，必须现使用&#8220;cscope-indexer -r&#8221;命令递归生成索引信息文件。特殊情况下，还需<br /> 要用户使用find命令，主动生成索引信息文件，并指定给cscope工具。 cscope提供了如下<br /> 九种查询方式：</p> <p>Find this C symbol:<br /> #查找指定的C符号<br /> Find this global definition:<br /> #查找指定的全局定义<br /> Find functions called by this function:<br /> #查找指定函数调用的函数<br /> Find functions calling this function:<br /> #查找调用指定函数的函数<br /> Find this text string:<br /> #查找字符串<br /> Change this text string:<br /> #修改指定字符串<br /> Find this egrep pattern:<br /> #查找匹配字符<br /> Find this file:<br /> #查找指定文件<br /> Find files #including this file:<br /> #指定引用头文件进行查找</p> <p>在对应某一项中输入查找条件，回车即可进行查询，并将结果显示在显示面板。</p> <p>　K跳转到函数的man页</p> <p>　　gg=G 按indent缩进格式化整个文件<br /> ==　格式化整行<br /> =a{格式化当前{}程序块</p> <p>　　gf　查找文件，在.vimrc中用set path=/u/infdev/**/**/** 来设置搜索路径</p> <p>　　/* 折行功能可以将一节浓缩为一行, 只显示其大概. */<br /> zo 打开折行<br /> zc 关闭折叠</p> <p>　　在编辑模式下用ctrl+o可以暂时进行命令模式</p> <p>　　[{ 命令跳转到当前代码块的开头, <br /> ]} 会跳转到当前代码块的末尾.<br /> [[ 向前查找一个函数的开始<br /> ]] 向后查找一个函数的开始<br /> ][ 向前查找一个函数的结尾,<br /> [] 向后查找一个函数的结尾, <br /> {&nbsp;&nbsp;  到前一个空行上<br /> }&nbsp;&nbsp;  到下一个空行上<br /> #&nbsp;&nbsp;  到与当前单词相同的上一个单词上<br /> *&nbsp;&nbsp;  到与当前单词相同的下一个单词上<br /> %&nbsp;&nbsp;  可以让光标从它当前所在的括号跳转到与它相匹配的括号上去,</p> <p>　　CTRL+] 跳转tags定义的地方=&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  ctrl+t返回调用tag的地方</p> <p>　　gD 查询变量，只在本文件中<br /> gd 查询变量, 只在本函数中<br /> <br /> [i&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  查询变量的定义<br /> [&lt;Tab&gt;&nbsp;&nbsp;&nbsp;  跳到变量定义的地方</p> <p>　　set makeprg=nmake　　后面nmake可自己定义，一般不用定义<br /> :make&nbsp;&nbsp;  编译程序<br /> :cnext 跳到下一个编译错误<br /> :cc 　　看完整的错误信息<br /> :clist 看所有错误信息</p> <p>　　:e b&lt;tab&gt;在命令行用tab可以补全　　按ctrl+d列出所有匹配<br /> q: 列出命令窗口<br /> <br /> Vim有一种记录宏的机制。你键入"qa"开始把一段宏记录入寄存器变量`a'中。按下来你可以象平常一样键入你要的操作,  只是这些操作都会被Vim记录进它命名为`a'的宏中, 再次再下"q"键,  就结束了宏`a'的录制。当你要重复执行你刚才记录的那些操作时只要使用"@a"命令。共有26个可用的寄存器供你记录宏。</p> <p> </p> <p> </p> <p> </p> <p><br /> 二为代码生成数据库<br /> 2、首先需要为你的代码生成一个cscope数据库。生成数据库很简单，在你的项目根目录运行下面的命令：<br /> cscope -Rbq</p> <p>如果不是c代码，使用：</p> <p>$ find ./ -name "*.c" -or -name "*.h" -or -name "*.cpp" -or -name  "*.S" | cscope -Rbq<br /> 这个命令会生成三个文件：cscope.out, cscope.in.out,  cscope.po.out。其中cscope.out是基本的符号索引，后两个文件是使用"-q"选项生成的，可以加快cscope的索引速度。<br /> 具体的参数的含义可以通过:man cscope 得到。-R: 在生成索引文件时，搜索子目录树中的代码</p> <p>-b: 只生成索引文件，不进入cscope的界面</p> <p>-q: 生成cscope.in.out和cscope.po.out文件，加快cscope的索引速度</p> <p>-k: 在生成索引文件时，不搜索/usr/include目录</p> <p>-i:  如果保存文件列表的文件名不是cscope.files时，需要加此选项告诉cscope到哪儿去找源文件列表。可以使用&#8220;-&#8221;，表示由标准输入获得文件 列表。</p> <p>-I dir: 在-I选项指出的目录中查找头文件</p> <p>-u: 扫描所有文件，重新生成交叉索引文件</p> <p><br /> 三在VIM中使用cscope<br /> 1 、用vim编辑的时候：<br /> vim FILENAME.c<br /> 2 把生成的cscope文件导入到vim中来<br /> :cs add /路径/cscope.out 代码所在目录<br /> 我习惯现切换到代码所在目录再操作，所以直接使用：<br /> ：cs add cscope.out 就可以了。</p> <p>3 查看是否已经连接到对应数据库<br /> :cs s</p> <p><br /> 4 cs f s xxxx 查找xxxx出现的地方，它能详细列出哪些文件的哪行的哪个函数引用，以及该行的内容.<br /> ，首先调用&#8220;cscope add&#8221;命令添加一个cscope数据库，然后就可以调用&#8220;cscope  find&#8221;命令进行查找了。VIM支持8种cscope的查询功能，如下：例如，我们想在代码中查找调用work()函数的函数，我们可以输入：&#8220;:cs  find c work&#8221;，回车后发现没有找到匹配的功能，可能并没有函数调用work()。我们再输入&#8220;:cs find s  work&#8221;，查找这个符号出现的位置，现在vim列出了这个符号出现的所有位置。我们还可以进行字符串查找，它会双引号或单引号括起来的内容中查找。还可  以输入一个正则表达式，这类似于egrep程序的功能。</p> <p>s: 查找C语言符号，即查找函数名、宏、枚举值等出现的地方</p> <p>g: 查找函数、宏、枚举等定义的位置。 <br /> cs f g main 光标跳到main函数的位置</p> <p>d: 查找本函数调用的函数<br /> cs f d main 列出main函数调用的函数，输入函数所对应的数字，就可以调到相应掉用的函数</p> <p>c: 查找调用本函数的函数<br /> cs f c main 会输出找到没有匹配的结果，因为没有函数调用main函数</p> <p>t: 查找指定的字符串<br /> cs f t STRING</p> <p>f: 查找并打开文件</p> <p> </p> <span style="text-decoration: underline;">还有在.vimrc下面加上了键盘映射<br /> map &lt;F8&gt;  :Tlist&lt;CR&gt;<br /> 这样就可以使用快捷键F8直接进入tlist模式了。这里注意&lt;F8&gt;和 ： 之间有空格的。<br /> <br /> 在.vimrc 下加入一下两行<br /> set tags=tags;<br /> set autochdir<br /> 这样使用tags时可以首先在当前目录下查找tags文 件，如果没有则转到父目录查找。依次向上。</span></div></div><img src ="http://www.cppblog.com/flyonok/aggbug/148061.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyonok/" target="_blank">flyonok</a> 2011-06-04 20:58 <a href="http://www.cppblog.com/flyonok/archive/2011/06/04/148061.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Install Language support in CentOS 5 or Red Hat Enterprise Linux</title><link>http://www.cppblog.com/flyonok/archive/2011/05/28/147465.html</link><dc:creator>flyonok</dc:creator><author>flyonok</author><pubDate>Sat, 28 May 2011 02:48:00 GMT</pubDate><guid>http://www.cppblog.com/flyonok/archive/2011/05/28/147465.html</guid><wfw:comment>http://www.cppblog.com/flyonok/comments/147465.html</wfw:comment><comments>http://www.cppblog.com/flyonok/archive/2011/05/28/147465.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyonok/comments/commentRss/147465.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyonok/services/trackbacks/147465.html</trackback:ping><description><![CDATA[<div><p><strong><span style="color: #ff0000;">Q.</span></strong> How  do I install Languages in Linux  after installation? I don&#8217;t have any  language specific support installed but need to install the same. I&#8217;m  using both RHEL 5 and CentOS 5.</p> <p><strong><span style="color: #009900;">A.</span></strong>  Yellow dog Updater, Modified, a package manager for RPM-compatible Linux  systems such as CentoS 5/Fedora 7 and RHEL 5.  Yum's repository system  is quickly becoming the standard for RPM-based repositories. </p> <p>If the languages were not installed during the installation, the same  can be installed by YUM command. Use following command to install Hindi  and Chinese support. </p> <p># yum groupinstall {LANGUAGE-support}</p> <p><code># yum install "@Hindi Support"<br /> # yum install "@Chinese Support"</code></p> <p>Use <strong>yum grouplist</strong> list available groups and languages.</p></div><img src ="http://www.cppblog.com/flyonok/aggbug/147465.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyonok/" target="_blank">flyonok</a> 2011-05-28 10:48 <a href="http://www.cppblog.com/flyonok/archive/2011/05/28/147465.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux 2.4中netfilter框架实现</title><link>http://www.cppblog.com/flyonok/archive/2011/05/21/146841.html</link><dc:creator>flyonok</dc:creator><author>flyonok</author><pubDate>Fri, 20 May 2011 16:29:00 GMT</pubDate><guid>http://www.cppblog.com/flyonok/archive/2011/05/21/146841.html</guid><wfw:comment>http://www.cppblog.com/flyonok/comments/146841.html</wfw:comment><comments>http://www.cppblog.com/flyonok/archive/2011/05/21/146841.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyonok/comments/commentRss/146841.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyonok/services/trackbacks/146841.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: inux 2.4中netfilter框架实现&nbsp;ideal (linux中文支持站点）1 s2 H5 _* D, UNetfilter是linux2.4内核实现数据包过滤/数据包处理/NAT等的功能框架。该文讨论了linux 2.4内核的netfilter功能框架，还对基于netfilter框架上的包过滤，NAT和数据包处理(packet mangling)进行了讨论。阅读本文需要了解2....&nbsp;&nbsp;<a href='http://www.cppblog.com/flyonok/archive/2011/05/21/146841.html'>阅读全文</a><img src ="http://www.cppblog.com/flyonok/aggbug/146841.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyonok/" target="_blank">flyonok</a> 2011-05-21 00:29 <a href="http://www.cppblog.com/flyonok/archive/2011/05/21/146841.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux Layer 7 Netfilter QOS 實作成功紀錄</title><link>http://www.cppblog.com/flyonok/archive/2011/05/20/146836.html</link><dc:creator>flyonok</dc:creator><author>flyonok</author><pubDate>Fri, 20 May 2011 15:24:00 GMT</pubDate><guid>http://www.cppblog.com/flyonok/archive/2011/05/20/146836.html</guid><wfw:comment>http://www.cppblog.com/flyonok/comments/146836.html</wfw:comment><comments>http://www.cppblog.com/flyonok/archive/2011/05/20/146836.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyonok/comments/commentRss/146836.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyonok/services/trackbacks/146836.html</trackback:ping><description><![CDATA[<a href="http://www.pczone.com.tw/vbb3/thread/29/119007/"><u><font color="#0000ff">http://www.pczone.com.tw/vbb3/thread/29/119007/</font></u></a><img src ="http://www.cppblog.com/flyonok/aggbug/146836.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyonok/" target="_blank">flyonok</a> 2011-05-20 23:24 <a href="http://www.cppblog.com/flyonok/archive/2011/05/20/146836.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>虚拟平台在嵌入式中的应用--转自csdn</title><link>http://www.cppblog.com/flyonok/archive/2011/05/19/146779.html</link><dc:creator>flyonok</dc:creator><author>flyonok</author><pubDate>Thu, 19 May 2011 15:01:00 GMT</pubDate><guid>http://www.cppblog.com/flyonok/archive/2011/05/19/146779.html</guid><wfw:comment>http://www.cppblog.com/flyonok/comments/146779.html</wfw:comment><comments>http://www.cppblog.com/flyonok/archive/2011/05/19/146779.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyonok/comments/commentRss/146779.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyonok/services/trackbacks/146779.html</trackback:ping><description><![CDATA[<div>转自<a href="http://blog.csdn.net/coolbacon/archive/2011/04/11/6316403.aspx"><u><font color="#0000ff">http://blog.csdn.net/coolbacon/archive/2011/04/11/6316403.aspx</font></u></a><br /><br /><span style="widows: 2; text-transform: none; text-indent: 0px; border-collapse: separate; font: medium Simsun; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -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" class="Apple-style-span"><span style="text-align: left; line-height: 21px; font-family: verdana, sans-serif; font-size: 14px" class="Apple-style-span"> 
<p style="padding-bottom: 0px; margin: 1em 0px 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="line-height: 19px; font-size: small">虚拟平台原先就是一些老学究搞出来的东西，为了在一些大型机上，大家都想使用大型机而又相互不干扰。于是提出的虚拟机的概念，这使得每个人独立操作而互不干扰。但当时60、70年代，个人电脑还不足以支撑软件虚拟环境，所以一度被搁置。后来到了90年代后期再度进入人们的实现。<br /><br />90年代SUN公司弄出的Java虚拟机以及 vmware 虚拟机，都是市场的佼佼者。Java是一次编译到处运行，实在是轻松，怪不得Java的标志是一杯咖啡，大家活都很快干完了，去喝咖啡去了&#8230;&#8230;vmware虚拟机，据说发明人发现服务器真实的硬件利用率总是很低，那么通过虚拟化技术将一台计算机变成N台计算机，真是太爽了，不需要多投入一分硬件的钱，却可以得到很多硬件才能实现的功能。通过这种方式提高资源的利用率。同时，这也带来了许多附加的好处，比如说服务器的硬件损坏了，把硬盘抽出来，虚拟机拷贝出来，又可以在别的机器上运行了。虚拟机可以通过交换机与真实的计算机通信，也可以经过地址转换与真实的机器通信。灵活的方式让企业个人随心所欲的定制服务器，达到最佳的效果。<br /><br />以上都是虚拟机在企业级的运用，在嵌入式领域，虚拟机也是大显身手。比如说我喜欢搞RTEMS，但RTEMS的开发环境是GNU的工具链，在windows下，GNU的工具链运转效率明显没有Linux高。平时我使用的大部分工具和沟通工具都是基于windows的，为了解决这个矛盾，装个虚拟机，将linux运行在windows之上，啥问题都解决了。<br /><br />下面我们就来看看嵌入式领域虚拟机的应用。首先在项目的需求收集阶段，客户表述的需求既不专业也不具体，对后续的工作缺乏具体的指导意义。特别是客户可能和做产品的人横跨两个大的行业，沟通非常成问题。这时，我们可以利用一些系统原型和客户沟通，既减少了沟通成本，也降低了后续项目实施的风险。然而，嵌入式系统不像PC系统，往往需要特殊的硬件支撑，没有特殊的硬件，原型从何谈起？虚拟的应用一下子让这种看似不可能的事情变得可能。什么样的项目需要这么做呢？最常见的莫过于操作界面了。然而操作界面大多可以更改API直接在PC系统上跑，可以不用虚拟的。当然，我不反对这样去做，但是，通过虚拟技术，界面更加接近实际，比PC机接近实际。同时这些所作的成果项目实施的中后期也能用到。就看您如何权衡了。<br /><br />在项目的设计阶段，可能需要确认技术解决方案的有效性。如系统的内存和ROM的用量，算法的时间是否满足要求等。通常的做法是采用公板跑测试代码，而公板的价格不菲，且是稀缺资源。把它伺候起来，还需要更加不菲的更加昂贵的调试器帮助。这套弄下来，不说玩起来，资源配置就是个大问题。如果采用虚拟技术，硬件还是那个硬件，在虚拟系统上跑起来后。像算法的时间能准确的给出是多少个系统时钟脉冲，比实际测得的时间可能更具有意义。可帮助系统工程师确认先期的技术解决方案,减少前期的资源投入。<br /><br />在项目的实施阶段，嵌入式最突出的风险就是硬件和软件同时成熟，往往，这两者的平衡我想是许多嵌入式项目经理最头疼的问题。合理的使用虚拟技术，可以大幅度的削弱这个风险，并且提高项目最终交付的质量。在项目实施的初期，只能开发一些高层的应用程序，这些应用程序调用的系统接口和驱动使用桩函数替代。待到中后期，硬件出来以后，系统编码人员将驱动和操作系统调试通过后，应用程序开发人员再移植到具体的硬件平台上。紧接着就是疯狂的加班，然后解决Bug。嵌入式系统的实施人员往往有这种感触，嵌入式项目开发越到后期，加班越是疯狂，丝毫享受不到创造的快乐&#8230;&#8230;如果使用虚拟技术，使得一开始系统编码人员就可以开发硬件的驱动，有这充分的时间调试，应用程序编码人员也不需要用桩函数替代系统或驱动调用。相当部分的工作，软件和硬件能同时工作，相互不依赖。虚化可以很好替代真实的硬件工作，且人手一套，实在是方便。硬件开发往往含有较多的不可并行的过程，如绘制PCB，加工PCB、贴板，调试样机等。这些过程往往都是串行过程，即使添加一倍的人力，也不能将交付期缩短。如果硬件出了问题，对嵌入式整个项目的影响是非常大的。同时也必须看到，虚化技术并不能解决项目中的全部问题，特别是硬件中含有许多特别的不能虚化的硬件，如AD等。对于这种硬件中的问题，大部分还是采取桩函数的办法，能将真实硬件上的80%的代码跑起来，可以说虚化的已经很不错了。<br /></span></p>
<p style="padding-bottom: 0px; margin: 1em 0px 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="line-height: 19px; font-size: small"><br /></span></p>
<p style="padding-bottom: 0px; margin: 1em 0px 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="line-height: 19px; font-size: small">在项目实施阶段，对代码的单元测试也是非常重要的，单元测试的测试用例设计有很多方法，如边界值、临界值等，无论什么办法，有一个硬性的评估指标，那就是代码的覆盖率。只要能到 100%,且测试用例都能通过，那么自然开发人员自然来得有信心。交付的时候也有底气。然而嵌入式系统的单元测试如果在具体的硬件上实现的话，费事费力，效果不好。因为如果看到覆盖率，必然要跟踪代码的执行，需要非常昂贵的调试跟踪设备。代码在跟踪过程中，也很难实现100%的性能，也会使得代码运行不正常。在虚拟平台上这似乎太简单了，如qemu只需要带一个参数，就会将覆盖率导出。基本上没有什么性能的损失，非常方便。在后期的集成测试当中，如果没有足够的样机，可以适当的对虚化做一些扩展，做一些虚拟化的测试。可以大批量的复制，以验证系统的稳定性和可靠性。可与真实的硬件跑出来的效果做对比，更利于问题的准确定位。特别的，在PC机上做虚拟，对于有界面的嵌入式系统，可以使用一些自动化的测试软件在PC机上反复的操作，节省大量的测试人力物力。如果拿实际的硬件，你点击文件菜单1000次，测试系统的行为。这个工作量对任何人来说都是难以想象的。</span></p>
<p style="padding-bottom: 0px; margin: 1em 0px 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="line-height: 19px; font-size: small"><br /></span></p>
<p style="padding-bottom: 0px; margin: 1em 0px 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="line-height: 19px; font-size: small">在项目维护和交付阶段，虚化可以用来训练系统维护人员，特别一些贵重的系统，样机可能公司里也没有，培训售后人员只能是纸上谈兵了；同时系统出了问题，客户反馈来，软件工程师没有样机调试，只能到现场去调试了，那是多么痛苦的事情啊。虚拟系统是最好的救命稻草了，维护人员可以随便捯饬虚拟系统，寻找感觉。软件开发人员可以先在虚拟系统上解决了，然后再到客户那里一次性解决，既增强客户和研发人员的信心，也树立了良好的企业形象。<br /><br />以上我们讨论的是虚化在嵌入式开发的整个过程中的应用。其实虚化在嵌入式市场里也大有作为。现在的智能手机，很多都是两个操作系统够成的。如著名的Android系统，一个是RTOS，一个是linux。两个操作系统必然要两个CPU。对于开发者来讲，这样无疑大幅度的增加了开发成本，因为技术要求高了。虚拟技术的应用，大幅度的减小了这个技术难度。将一个CPU虚拟成两个，一个跑RTOS，一个跑linux，哈，完美。移植只需要移植底层的虚拟系统，rtos和linux都不需要移植了。开发工作者只专注：虚拟系统的移植和UI交互。这个市场是相当广泛的，如OKL4、Hypervisor都是这样的产品。<br /></span></p>
<p style="padding-bottom: 0px; margin: 1em 0px 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="line-height: 19px; font-size: small"><br />本文随便聊聊，旨在推广rickleaf的emboslab项目，这实在是一件利国利民利己的好事。有志者都来参加吧，我们需要优秀的你!</span></p></span></span></div><img src ="http://www.cppblog.com/flyonok/aggbug/146779.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyonok/" target="_blank">flyonok</a> 2011-05-19 23:01 <a href="http://www.cppblog.com/flyonok/archive/2011/05/19/146779.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux 2.4.x 网络协议栈QoS模块(TC)的设计与实现</title><link>http://www.cppblog.com/flyonok/archive/2011/05/03/145544.html</link><dc:creator>flyonok</dc:creator><author>flyonok</author><pubDate>Tue, 03 May 2011 04:05:00 GMT</pubDate><guid>http://www.cppblog.com/flyonok/archive/2011/05/03/145544.html</guid><wfw:comment>http://www.cppblog.com/flyonok/comments/145544.html</wfw:comment><comments>http://www.cppblog.com/flyonok/archive/2011/05/03/145544.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyonok/comments/commentRss/145544.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyonok/services/trackbacks/145544.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Linux 2.4.x 网络协议栈QoS模块(TC)的设计与实现&nbsp;&nbsp;<a href='http://www.cppblog.com/flyonok/archive/2011/05/03/145544.html'>阅读全文</a><img src ="http://www.cppblog.com/flyonok/aggbug/145544.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyonok/" target="_blank">flyonok</a> 2011-05-03 12:05 <a href="http://www.cppblog.com/flyonok/archive/2011/05/03/145544.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Finding Performance Bottlenecks in Linux</title><link>http://www.cppblog.com/flyonok/archive/2011/04/21/144736.html</link><dc:creator>flyonok</dc:creator><author>flyonok</author><pubDate>Thu, 21 Apr 2011 08:44:00 GMT</pubDate><guid>http://www.cppblog.com/flyonok/archive/2011/04/21/144736.html</guid><wfw:comment>http://www.cppblog.com/flyonok/comments/144736.html</wfw:comment><comments>http://www.cppblog.com/flyonok/archive/2011/04/21/144736.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyonok/comments/commentRss/144736.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyonok/services/trackbacks/144736.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Finding Performance Bottlenecks in Linux&nbsp;&nbsp;<a href='http://www.cppblog.com/flyonok/archive/2011/04/21/144736.html'>阅读全文</a><img src ="http://www.cppblog.com/flyonok/aggbug/144736.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyonok/" target="_blank">flyonok</a> 2011-04-21 16:44 <a href="http://www.cppblog.com/flyonok/archive/2011/04/21/144736.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Booting Bare Hardware</title><link>http://www.cppblog.com/flyonok/archive/2011/04/20/144674.html</link><dc:creator>flyonok</dc:creator><author>flyonok</author><pubDate>Wed, 20 Apr 2011 08:41:00 GMT</pubDate><guid>http://www.cppblog.com/flyonok/archive/2011/04/20/144674.html</guid><wfw:comment>http://www.cppblog.com/flyonok/comments/144674.html</wfw:comment><comments>http://www.cppblog.com/flyonok/archive/2011/04/20/144674.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyonok/comments/commentRss/144674.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyonok/services/trackbacks/144674.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Booting Bare Hardware&nbsp;&nbsp;<a href='http://www.cppblog.com/flyonok/archive/2011/04/20/144674.html'>阅读全文</a><img src ="http://www.cppblog.com/flyonok/aggbug/144674.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyonok/" target="_blank">flyonok</a> 2011-04-20 16:41 <a href="http://www.cppblog.com/flyonok/archive/2011/04/20/144674.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linkers and Loaders--page 4 of 4</title><link>http://www.cppblog.com/flyonok/archive/2011/04/20/144655.html</link><dc:creator>flyonok</dc:creator><author>flyonok</author><pubDate>Wed, 20 Apr 2011 05:58:00 GMT</pubDate><guid>http://www.cppblog.com/flyonok/archive/2011/04/20/144655.html</guid><wfw:comment>http://www.cppblog.com/flyonok/comments/144655.html</wfw:comment><comments>http://www.cppblog.com/flyonok/archive/2011/04/20/144655.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyonok/comments/commentRss/144655.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyonok/services/trackbacks/144655.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Linkers and Loaders--page 4 of 4&nbsp;&nbsp;<a href='http://www.cppblog.com/flyonok/archive/2011/04/20/144655.html'>阅读全文</a><img src ="http://www.cppblog.com/flyonok/aggbug/144655.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyonok/" target="_blank">flyonok</a> 2011-04-20 13:58 <a href="http://www.cppblog.com/flyonok/archive/2011/04/20/144655.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linkers and Loaders--page 3 of 4</title><link>http://www.cppblog.com/flyonok/archive/2011/04/20/144643.html</link><dc:creator>flyonok</dc:creator><author>flyonok</author><pubDate>Wed, 20 Apr 2011 04:10:00 GMT</pubDate><guid>http://www.cppblog.com/flyonok/archive/2011/04/20/144643.html</guid><wfw:comment>http://www.cppblog.com/flyonok/comments/144643.html</wfw:comment><comments>http://www.cppblog.com/flyonok/archive/2011/04/20/144643.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyonok/comments/commentRss/144643.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyonok/services/trackbacks/144643.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Linkers and Loaders--page 3 of 4&nbsp;&nbsp;<a href='http://www.cppblog.com/flyonok/archive/2011/04/20/144643.html'>阅读全文</a><img src ="http://www.cppblog.com/flyonok/aggbug/144643.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyonok/" target="_blank">flyonok</a> 2011-04-20 12:10 <a href="http://www.cppblog.com/flyonok/archive/2011/04/20/144643.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linkers and Loaders--page 2 of 4</title><link>http://www.cppblog.com/flyonok/archive/2011/04/20/144635.html</link><dc:creator>flyonok</dc:creator><author>flyonok</author><pubDate>Wed, 20 Apr 2011 03:18:00 GMT</pubDate><guid>http://www.cppblog.com/flyonok/archive/2011/04/20/144635.html</guid><wfw:comment>http://www.cppblog.com/flyonok/comments/144635.html</wfw:comment><comments>http://www.cppblog.com/flyonok/archive/2011/04/20/144635.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyonok/comments/commentRss/144635.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyonok/services/trackbacks/144635.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Linkers and Loaders--page 2 of 4&nbsp;&nbsp;<a href='http://www.cppblog.com/flyonok/archive/2011/04/20/144635.html'>阅读全文</a><img src ="http://www.cppblog.com/flyonok/aggbug/144635.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyonok/" target="_blank">flyonok</a> 2011-04-20 11:18 <a href="http://www.cppblog.com/flyonok/archive/2011/04/20/144635.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linkers and Loaders--page 1 of 4</title><link>http://www.cppblog.com/flyonok/archive/2011/04/20/144629.html</link><dc:creator>flyonok</dc:creator><author>flyonok</author><pubDate>Wed, 20 Apr 2011 02:08:00 GMT</pubDate><guid>http://www.cppblog.com/flyonok/archive/2011/04/20/144629.html</guid><wfw:comment>http://www.cppblog.com/flyonok/comments/144629.html</wfw:comment><comments>http://www.cppblog.com/flyonok/archive/2011/04/20/144629.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyonok/comments/commentRss/144629.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyonok/services/trackbacks/144629.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Linkers and Loaders--page 1 0f 4&nbsp;&nbsp;<a href='http://www.cppblog.com/flyonok/archive/2011/04/20/144629.html'>阅读全文</a><img src ="http://www.cppblog.com/flyonok/aggbug/144629.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyonok/" target="_blank">flyonok</a> 2011-04-20 10:08 <a href="http://www.cppblog.com/flyonok/archive/2011/04/20/144629.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CentOS 5.4下使用ntfs-3g挂载NTFS</title><link>http://www.cppblog.com/flyonok/archive/2011/04/20/144614.html</link><dc:creator>flyonok</dc:creator><author>flyonok</author><pubDate>Tue, 19 Apr 2011 16:55:00 GMT</pubDate><guid>http://www.cppblog.com/flyonok/archive/2011/04/20/144614.html</guid><wfw:comment>http://www.cppblog.com/flyonok/comments/144614.html</wfw:comment><comments>http://www.cppblog.com/flyonok/archive/2011/04/20/144614.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyonok/comments/commentRss/144614.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyonok/services/trackbacks/144614.html</trackback:ping><description><![CDATA[<h1 class="title_txt"><cite class="fav_csdnstylebykimi"> </cite>
</h1>
<div class="blogstory">
<script type="text/javascript">
						document.body.oncopy = function () {
							if (window.clipboardData) {
								setTimeout(function () {
									var text = clipboardData.getData("text");
									if (text && text.length > 300) {
										text = text + "\r\n\n本文来自CSDN博客，转载请标明出处：" + location.href;
										clipboardData.setData("text", text);
									}
								}, 100);
							}
						}
					</script>
<script type="text/javascript">						function StorePage() { d = document; t = d.selection ? (d.selection.type != 'None' ? d.selection.createRange().text : '') : (d.getSelection ? d.getSelection() : ''); void (keyit = window.open('http://www.365key.com/storeit.aspx?t=' + escape(d.title) + '&u=' + escape(d.location.href) + '&c=' + escape(t), 'keyit', 'scrollbars=no,width=475,height=575,left=75,top=20,status=no,resizable=yes')); keyit.focus(); }</script>
<p>CentOS 5.4下使用ntfs-3g挂载NTFS</p>
<p>环境</p>
<p>操作系统:<br># cat /etc/redhat-release <br>CentOS release 5.4 (Final)<br>CPU: <br># cat /proc/cpuinfo<br>若没有出现64字样，则一般为32位CPU</p>
<p>所需软件</p>
<p>(i) <br>fuse-2.7.4-8.el5.i386.rpm(32位机器)<br>或<br>fuse-2.7.4-8.el5.x86_64.rpm(64位机器)</p>
<p>下载地址：<br><a href="http://mirror.centos.org/centos/5/os/i386/CentOS/">http://mirror.centos.org/centos/5/os/i386/CentOS/</a><br>或<br><a href="http://mirror.centos.org/centos/5/os/x86_64/CentOS/">http://mirror.centos.org/centos/5/os/x86_64/CentOS/</a></p>
<p>(ii)<br>fuse-ntfs-3g-2009.4.4-2.el5.rf.i386.rpm (32位)<br>或<br>fuse-ntfs-3g-2009.4.4-2.el5.rf.x86_64.rpm (64位)</p>
<p>下载地址：<br><a href="http://rpmforge.sw.be/redhat/el5/en/i386/rpmforge/RPMS/fuse-ntfs-3g-2009.4.4-2.el5.rf.i386.rpm">http://rpmforge.sw.be/redhat/el5/en/i386/rpmforge/RPMS/fuse-ntfs-3g-2009.4.4-2.el5.rf.i386.rpm</a><br>或<br><a href="http://rpmforge.sw.be/redhat/el5/en/x86_64/rpmforge/RPMS/fuse-ntfs-3g-2009.4.4-2.el5.rf.x86_64.rpm">http://rpmforge.sw.be/redhat/el5/en/x86_64/rpmforge/RPMS/fuse-ntfs-3g-2009.4.4-2.el5.rf.x86_64.rpm</a></p>
<p><br>(1)安装</p>
<p>rpm -ivh fuse-2.7.4-8.el5.i386.rpm<br>rpm -ivh fuse-ntfs-3g-2009.4.4-2.el5.rf.i386.rpm</p>
<p>(2)挂载和卸载HDFS设备</p>
<p>安装以上两个软件包后，就可以挂载ntfs分区了，挂载方法如下：</p>
<p>首先用命令查看电脑上的设备<br># fdisk -l<br>然后挂载某个设备<br>mkdir /mnt/D<br>mount -t ntfs-3g /dev/xxx /mnt/D<br>卸载某个设备<br>umount /mnt/D</p>
<p>～～～～～～～～～～～～～～～～～～～<br>还没安装前挂载HDFS设备会报错<br>～～～～～～～～～～～～～～～～～～～<br># mkdir /mnt/hda1<br># mount /dev/hda1 /mnt/hda1<br>mount: unknown filesystem type &#8216;ntfs&#8217;<br># <br>～～～～～～～～～～～～～～～～～～～</p>
<p>(3)设置位开机启动</p>
<p>如果需要开机自启动挂载，可以在/etc/fstab文件结尾添加需要挂载的NTFS盘，<br>添加命令如下：<br>/dev/sda1&nbsp; /mnt/C&nbsp; ntfs-3g defaults 0 0<br>如果有多个盘挂载，就多加几行，例如:<br>LABEL=/&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; ext3&nbsp;&nbsp;&nbsp; defaults&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1 1<br>tmpfs&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /dev/shm&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tmpfs&nbsp;&nbsp; defaults&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0 0<br>devpts&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /dev/pts&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; devpts gid=5,mode=620 0 0<br>sysfs&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /sys&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sysfs&nbsp;&nbsp; defaults&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0 0<br>proc&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /proc&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; proc&nbsp;&nbsp;&nbsp; defaults&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0 0<br>/dev/sda8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; swap&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; swap&nbsp;&nbsp;&nbsp; defaults&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0 0<br>/dev/sda1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /mnt/C&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ntfs-3g defaults&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0 0<br>/dev/sda5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /mnt/D&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ntfs-3g defaults&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0 0<br>/dev/sda6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /mnt/E&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ntfs-3g defaults&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0 0<br>/dev/sda7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /mnt/F&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ntfs-3g defaults&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0 0 </p>
<p>(4) 参考资料</p>
<p>在Centos 等linux下利用ntfs-3g来挂载并读写NTFS分区（或移动硬盘）<br><a href="http://blog.163.com/szs121@126/blog/static/10905678120102231234142/">http://blog.163.com/szs121@126/blog/static/10905678120102231234142/</a></p>
<p>CentOS等Linux利用ntfs-3g挂载可读写NTFS<br><a href="http://blog.163.com/szs121@126/blog/static/10905678120102231955507/">http://blog.163.com/szs121@126/blog/static/10905678120102231955507/</a></p>
</div><img src ="http://www.cppblog.com/flyonok/aggbug/144614.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyonok/" target="_blank">flyonok</a> 2011-04-20 00:55 <a href="http://www.cppblog.com/flyonok/archive/2011/04/20/144614.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何进行Linux Kernel 开发</title><link>http://www.cppblog.com/flyonok/archive/2011/04/15/144316.html</link><dc:creator>flyonok</dc:creator><author>flyonok</author><pubDate>Fri, 15 Apr 2011 09:09:00 GMT</pubDate><guid>http://www.cppblog.com/flyonok/archive/2011/04/15/144316.html</guid><wfw:comment>http://www.cppblog.com/flyonok/comments/144316.html</wfw:comment><comments>http://www.cppblog.com/flyonok/archive/2011/04/15/144316.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyonok/comments/commentRss/144316.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyonok/services/trackbacks/144316.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 如何进行Linux Kernel 开发&nbsp;&nbsp;<a href='http://www.cppblog.com/flyonok/archive/2011/04/15/144316.html'>阅读全文</a><img src ="http://www.cppblog.com/flyonok/aggbug/144316.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyonok/" target="_blank">flyonok</a> 2011-04-15 17:09 <a href="http://www.cppblog.com/flyonok/archive/2011/04/15/144316.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>IP校验与算法反码求和详解</title><link>http://www.cppblog.com/flyonok/archive/2011/04/15/144311.html</link><dc:creator>flyonok</dc:creator><author>flyonok</author><pubDate>Fri, 15 Apr 2011 07:22:00 GMT</pubDate><guid>http://www.cppblog.com/flyonok/archive/2011/04/15/144311.html</guid><wfw:comment>http://www.cppblog.com/flyonok/comments/144311.html</wfw:comment><comments>http://www.cppblog.com/flyonok/archive/2011/04/15/144311.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyonok/comments/commentRss/144311.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyonok/services/trackbacks/144311.html</trackback:ping><description><![CDATA[<span style="WIDOWS: 2; TEXT-TRANSFORM: none; TEXT-INDENT: 0px; BORDER-COLLAPSE: separate; FONT: medium Simsun; WHITE-SPACE: normal; ORPHANS: 2; LETTER-SPACING: normal; COLOR: rgb(0,0,0); WORD-SPACING: 0px; -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" class=Apple-style-span><span style="LINE-HEIGHT: 23px; FONT-SIZE: 14px" class=Apple-style-span>
<p style="PADDING-BOTTOM: 0px; LINE-HEIGHT: 23px; BORDER-RIGHT-WIDTH: 0px; MARGIN: 15px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; FONT-SIZE: 14px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px">文本Tag： 开源软件开发 IP路由 开源</p>
<p style="PADDING-BOTTOM: 0px; LINE-HEIGHT: 23px; BORDER-RIGHT-WIDTH: 0px; MARGIN: 15px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; FONT-SIZE: 14px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px">　　【<strong>IT168 技术文档</strong>】<strong>一、校验和算法</strong></p>
<p style="PADDING-BOTTOM: 0px; LINE-HEIGHT: 23px; BORDER-RIGHT-WIDTH: 0px; MARGIN: 15px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; FONT-SIZE: 14px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px">　　之前一直只知道IP校验和算法反码求和相关的,但具体细节不清楚,今天了解了下。</p>
<p style="PADDING-BOTTOM: 0px; LINE-HEIGHT: 23px; BORDER-RIGHT-WIDTH: 0px; MARGIN: 15px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; FONT-SIZE: 14px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px">　　IP校验和主要是用来保证数据(IP包头)的完整性的.它用的算法非常简单,就是反码求和校验.需要注意的是反码求和又叫1的补码(one'scomplement),而2的补码就是我们通常说的补码求和了.校验算法具体如下。</p>
<p style="PADDING-BOTTOM: 0px; LINE-HEIGHT: 23px; BORDER-RIGHT-WIDTH: 0px; MARGIN: 15px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; FONT-SIZE: 14px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px">　　<strong>1、发送方</strong></p>
<p style="PADDING-BOTTOM: 0px; LINE-HEIGHT: 23px; BORDER-RIGHT-WIDTH: 0px; MARGIN: 15px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; FONT-SIZE: 14px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px">　　i)将校验和字段置为0,然后将IP包头按16比特分成多个单元,如包头长度不是16比特的倍数,则用0比特填充到16比特的倍数;</p>
<p style="PADDING-BOTTOM: 0px; LINE-HEIGHT: 23px; BORDER-RIGHT-WIDTH: 0px; MARGIN: 15px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; FONT-SIZE: 14px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px">　　ii)对各个单元采用反码加法运算(即高位溢出位会加到低位,通常的补码运算是直接丢掉溢出的高位),将得到的和的反码填入校验和字段;</p>
<p style="PADDING-BOTTOM: 0px; LINE-HEIGHT: 23px; BORDER-RIGHT-WIDTH: 0px; MARGIN: 15px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; FONT-SIZE: 14px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px">　　iii)发送数据包.</p>
<p style="PADDING-BOTTOM: 0px; LINE-HEIGHT: 23px; BORDER-RIGHT-WIDTH: 0px; MARGIN: 15px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; FONT-SIZE: 14px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px">　　<strong>2、接收方</strong></p>
<p style="PADDING-BOTTOM: 0px; LINE-HEIGHT: 23px; BORDER-RIGHT-WIDTH: 0px; MARGIN: 15px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; FONT-SIZE: 14px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px">　　i)将IP包头按16比特分成多个单元,如包头长度不是16比特的倍数,则用0比特填充到16比特的倍数;</p>
<p style="PADDING-BOTTOM: 0px; LINE-HEIGHT: 23px; BORDER-RIGHT-WIDTH: 0px; MARGIN: 15px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; FONT-SIZE: 14px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px">　　ii)对各个单元采用反码加法运算,检查得到的和是否符合是全1(有的实现可能对得到的和会取反码,然后判断最终值是不是全0);</p>
<p style="PADDING-BOTTOM: 0px; LINE-HEIGHT: 23px; BORDER-RIGHT-WIDTH: 0px; MARGIN: 15px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; FONT-SIZE: 14px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px">　　iii)如果是全1则进行下步处理,否则意味着包已变化从而丢弃之.需要强调的是反码和是采用高位溢出加到低位的,如3比特的反码和运算:100b+101b=010b(因为100b+101b=1001b,高位溢出1,其应该加到低位,即001b+1b(高位溢出位)=010b),具体细节请参考文章:http://blog.chinaunix.net/u/20/showart_438418.html</p>
内容导航
<p style="PADDING-BOTTOM: 0px; LINE-HEIGHT: 23px; BORDER-RIGHT-WIDTH: 0px; MARGIN: 15px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; FONT-SIZE: 14px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px">　　<strong>二、校验和源码</strong></p>
<p style="PADDING-BOTTOM: 0px; LINE-HEIGHT: 23px; BORDER-RIGHT-WIDTH: 0px; MARGIN: 15px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; FONT-SIZE: 14px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px">　　网上流传多组实现,常见的有如下两种(如追求效率可改写为汇编代码):</p>
<p style="PADDING-BOTTOM: 0px; LINE-HEIGHT: 23px; BORDER-RIGHT-WIDTH: 0px; MARGIN: 15px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; FONT-SIZE: 14px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px">　　<strong>1、RFC1071源码</strong></p>
<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br><span style="COLOR: rgb(0,0,0)">　　unsigned<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,255)">short</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span>csum(unsigned<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,255)">char</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)">addr,<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span>count)<br><br>　　{<br><br>　　</span><span style="COLOR: rgb(0,128,0)">/*</span><span style="COLOR: rgb(0,128,0)"><span class=Apple-converted-space>&nbsp;</span>Compute Internet Checksum for "count" bytes<br><br>　　* beginning at location "addr".<br><br>　　</span><span style="COLOR: rgb(0,128,0)">*/</span><span style="COLOR: rgb(0,0,0)"><br><br>　　register<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,255)">long</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span>sum<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">0</span><span style="COLOR: rgb(0,0,0)">;<br><br>　　</span><span style="COLOR: rgb(0,0,255)">while</span><span style="COLOR: rgb(0,0,0)">( count<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">&gt;</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">1</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span>)<br><br>　　{<br><br>　　</span><span style="COLOR: rgb(0,128,0)">/*</span><span style="COLOR: rgb(0,128,0)"><span class=Apple-converted-space>&nbsp;</span>This is the inner loop<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,128,0)">*/</span><span style="COLOR: rgb(0,0,0)"><br><br>　　sum<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">+=</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span>(unsigned<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,255)">short</span><span style="COLOR: rgb(0,0,0)">) addr</span><span style="COLOR: rgb(0,0,0)">++</span><span style="COLOR: rgb(0,0,0)">;<br><br>　　count<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">-=</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">2</span><span style="COLOR: rgb(0,0,0)">;<br><br>　　}<br><br>　　</span><span style="COLOR: rgb(0,128,0)">/*</span><span style="COLOR: rgb(0,128,0)"><span class=Apple-converted-space>&nbsp;</span>Add left-over byte, if any<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,128,0)">*/</span><span style="COLOR: rgb(0,0,0)"><br><br>　　</span><span style="COLOR: rgb(0,0,255)">if</span><span style="COLOR: rgb(0,0,0)">( count<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">&gt;</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">0</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span>)<br><br>　　sum<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">+=</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span>(unsigned<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,255)">char</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)">) addr;<br><br>　　</span><span style="COLOR: rgb(0,128,0)">/*</span><span style="COLOR: rgb(0,128,0)"><span class=Apple-converted-space>&nbsp;</span>Fold 32-bit sum to 16 bits<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,128,0)">*/</span><span style="COLOR: rgb(0,0,0)"><br><br>　　</span><span style="COLOR: rgb(0,0,255)">while</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span>(sum</span><span style="COLOR: rgb(0,0,0)">&gt;&gt;</span><span style="COLOR: rgb(0,0,0)">16</span><span style="COLOR: rgb(0,0,0)">)<br><br>　　sum<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span>(sum<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">&amp;</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">0xffff</span><span style="COLOR: rgb(0,0,0)">)<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">+</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span>(sum<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">&gt;&gt;</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">16</span><span style="COLOR: rgb(0,0,0)">);<br><br>　　</span><span style="COLOR: rgb(0,0,255)">return</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">~</span><span style="COLOR: rgb(0,0,0)">sum;<br><br>　　}</span>
<p style="PADDING-BOTTOM: 0px; LINE-HEIGHT: 23px; BORDER-RIGHT-WIDTH: 0px; MARGIN: 15px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; FONT-SIZE: 14px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px">　　第一个while循环是做普通加法(2进制补码加法),因为IP包头和TCP整个报文段比较短(没达到2^17数量级),所以不可能导致4字节的sum溢出(unsigned long 一般至少为4字节)).</p>
<p style="PADDING-BOTTOM: 0px; LINE-HEIGHT: 23px; BORDER-RIGHT-WIDTH: 0px; MARGIN: 15px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; FONT-SIZE: 14px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px">　　紧接着的一个判断语句是为了能处理输入数据是奇数个字节的这种情况.再接着的数据循环是实现反码算法(在前面的普通加法得到的数据的基础上),由反码和的高位溢出加到低位的性质,可得到"32位的数据的高位比特移位16比特,再加上原来的低16比特,不影响最终结果" 这个等价运算,因为sum的最初值(刚开始循环时)可能很大,所以这个等价运算需循环进行,直到sum的高比特(16比特以上)全为0.对于32 位的 sum,事实上这个运算循环至多只有两轮,所以也有程序直接用两条"sum = (sum &amp; 0xffff) + (sum &gt;&gt; 16);"代替了整个循环.最后,对和取反返回.</p>
<p style="PADDING-BOTTOM: 0px; LINE-HEIGHT: 23px; BORDER-RIGHT-WIDTH: 0px; MARGIN: 15px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; FONT-SIZE: 14px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px">　　<strong>2、对数据长度没限制的实现</strong></p>
<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br><span style="COLOR: rgb(0,0,0)">　　unsigned<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,255)">short</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span>cksum (struct ip<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)">ip,<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span>len)<br><br>　　{<br><br>　　</span><span style="COLOR: rgb(0,0,255)">long</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span>sum<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">0</span><span style="COLOR: rgb(0,0,0)">;<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,128,0)">/*</span><span style="COLOR: rgb(0,128,0)"><span class=Apple-converted-space>&nbsp;</span>assume 32 bit long, 16 bit short<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,128,0)">*/</span><span style="COLOR: rgb(0,0,0)"><br><br>　　</span><span style="COLOR: rgb(0,0,255)">while</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span>( len<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">&gt;</span><span style="COLOR: rgb(0,0,0)">1</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span>)<br><br>　　{<br><br>　　sum<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">+=</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)">((unsigned<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,255)">short</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)">) ip)</span><span style="COLOR: rgb(0,0,0)">++</span><span style="COLOR: rgb(0,0,0)">;<br><br>　　</span><span style="COLOR: rgb(0,0,255)">if</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span>(sum<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">&amp;</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span>8x00000000)<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,128,0)">/*</span><span style="COLOR: rgb(0,128,0)"><span class=Apple-converted-space>&nbsp;</span>if high-order bit set, fold<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,128,0)">*/</span><span style="COLOR: rgb(0,0,0)"><br><br>　　sum<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span>(sum<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">&amp;</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">0xFFFF</span><span style="COLOR: rgb(0,0,0)">)<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">+</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span>(sum</span><span style="COLOR: rgb(0,0,0)">&gt;&gt;</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">16</span><span style="COLOR: rgb(0,0,0)">) ;<br><br>　　len<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">-=</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">2</span><span style="COLOR: rgb(0,0,0)">;<br><br>　　}<br><br>　　</span><span style="COLOR: rgb(0,0,255)">if</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span>( len )<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,128,0)">/*</span><span style="COLOR: rgb(0,128,0)"><span class=Apple-converted-space>&nbsp;</span>take care of left over byte<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,128,0)">*/</span><span style="COLOR: rgb(0,0,0)"><br><br>　　sum<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">+=</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span>( unsigned<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,255)">short</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span>)<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span>(unsignedl<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,255)">char</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)">) ip;<br><br>　　</span><span style="COLOR: rgb(0,0,255)">while</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span>( sum<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">&gt;&gt;</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">16</span><span style="COLOR: rgb(0,0,0)">)<br><br>　　sum<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)">(sum<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">&amp;</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">0xFFFF</span><span style="COLOR: rgb(0,0,0)">)<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">+</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span>(sum</span><span style="COLOR: rgb(0,0,0)">&gt;&gt;</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">16</span><span style="COLOR: rgb(0,0,0)">);<br><br>　　</span><span style="COLOR: rgb(0,0,255)">return</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">~</span><span style="COLOR: rgb(0,0,0)">sum;}</span>
<p style="PADDING-BOTTOM: 0px; LINE-HEIGHT: 23px; BORDER-RIGHT-WIDTH: 0px; MARGIN: 15px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; FONT-SIZE: 14px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px">　　这个实现与前面的一个的最大的不同是对数据的长度没什么限制了,因为它在第一个循环的加法运算中实时检测sum的高位的值,一旦发现其有溢出的危险,就及时运用等价运算关系消除了这个危险.</p>
内容导航
<p style="PADDING-BOTTOM: 0px; LINE-HEIGHT: 23px; BORDER-RIGHT-WIDTH: 0px; MARGIN: 15px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; FONT-SIZE: 14px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px">　　<strong>三、几个细节问题</strong></p>
<p style="PADDING-BOTTOM: 0px; LINE-HEIGHT: 23px; BORDER-RIGHT-WIDTH: 0px; MARGIN: 15px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; FONT-SIZE: 14px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px">　　<strong>1、数据部分改变时的重校验</strong></p>
<p style="PADDING-BOTTOM: 0px; LINE-HEIGHT: 23px; BORDER-RIGHT-WIDTH: 0px; MARGIN: 15px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; FONT-SIZE: 14px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px">　　考虑这样的应用场景:路由器转发IP报文时,有可能只更改了IP数据包头的部分内容(如更改了TTL,分片了或SNAT更改了源IP等~~~),却需要重校验的问题.为提高转发效率,要求重校验算法尽可能快,故出现了如下所示的重校验算法(只是一个简单的示例):</p>
<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br><span style="COLOR: rgb(0,0,0)">　　UpdateTTL(struct ip_hdr<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)">ipptr, unsigned<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,255)">char</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span>n)<br><br>　　{<br><br>　　unsigned<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,255)">long</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span>sum;<br><br>　　unsigned<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,255)">short</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span>old;<br><br>　　old<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span>ntohs(</span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)">(unsigned<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,255)">short</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)">)</span><span style="COLOR: rgb(0,0,0)">&amp;</span><span style="COLOR: rgb(0,0,0)">ipptr</span><span style="COLOR: rgb(0,0,0)">-&gt;</span><span style="COLOR: rgb(0,0,0)">ttl);<br><br>　　ipptr</span><span style="COLOR: rgb(0,0,0)">-&gt;</span><span style="COLOR: rgb(0,0,0)">ttl<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">-=</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span>n;<br><br>　　sum<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span>old<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">+</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span>(</span><span style="COLOR: rgb(0,0,0)">~</span><span style="COLOR: rgb(0,0,0)">ntohs(</span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)">(unsigned<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,255)">short</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)">)</span><span style="COLOR: rgb(0,0,0)">&amp;</span><span style="COLOR: rgb(0,0,0)">ipptr</span><span style="COLOR: rgb(0,0,0)">-&gt;</span><span style="COLOR: rgb(0,0,0)">ttl)<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">&amp;</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">0xffff</span><span style="COLOR: rgb(0,0,0)">);<br><br>　　sum<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">+=</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span>ntohs(ipptr</span><span style="COLOR: rgb(0,0,0)">-&gt;</span><span style="COLOR: rgb(0,0,0)">Checksum);<br><br>　　sum<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span>(sum<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">&amp;</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">0xffff</span><span style="COLOR: rgb(0,0,0)">)<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">+</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span>(sum</span><span style="COLOR: rgb(0,0,0)">&gt;&gt;</span><span style="COLOR: rgb(0,0,0)">16</span><span style="COLOR: rgb(0,0,0)">);<br><br>　　ipptr</span><span style="COLOR: rgb(0,0,0)">-&gt;</span><span style="COLOR: rgb(0,0,0)">Checksum<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span>htons(sum<span class=Apple-converted-space>&nbsp;</span></span><span style="COLOR: rgb(0,0,0)">+</span><span style="COLOR: rgb(0,0,0)"><span class=Apple-converted-space>&nbsp;</span>(sum</span><span style="COLOR: rgb(0,0,0)">&gt;&gt;</span><span style="COLOR: rgb(0,0,0)">16</span><span style="COLOR: rgb(0,0,0)">));<br><br>　　}</span>
<p style="PADDING-BOTTOM: 0px; LINE-HEIGHT: 23px; BORDER-RIGHT-WIDTH: 0px; MARGIN: 15px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; FONT-SIZE: 14px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px">　　算法的实现依据是这样的.假设包头原校验和为~C,改变的字段的原始值是m,更改后的值是m',设~C'为重校验和,则有 ~C' = ~(C+(-m)+m') = ~C+(m-m') = ~C+m+~m'等价关系的成立基于反码的运算性质:取反运算满足结合律,按位取反运算与符号取反(及相反数)是等价的(即~C=-C).</p>
<p style="PADDING-BOTTOM: 0px; LINE-HEIGHT: 23px; BORDER-RIGHT-WIDTH: 0px; MARGIN: 15px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; FONT-SIZE: 14px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px">　　如果有多个字段改变，只是上面的公式中的m和m'有多个而已，直接用反码加法搞定即可。</p>
<p style="PADDING-BOTTOM: 0px; LINE-HEIGHT: 23px; BORDER-RIGHT-WIDTH: 0px; MARGIN: 15px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; FONT-SIZE: 14px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px">　　<strong>2、为什么采用反码和运算</strong></p>
<p style="PADDING-BOTTOM: 0px; LINE-HEIGHT: 23px; BORDER-RIGHT-WIDTH: 0px; MARGIN: 15px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; FONT-SIZE: 14px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px">　　IP数据包校验要求速度快,所以只采用了简单的和校验,为什么采用反码和而不是补码和呢?</p>
<p style="PADDING-BOTTOM: 0px; LINE-HEIGHT: 23px; BORDER-RIGHT-WIDTH: 0px; MARGIN: 15px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; FONT-SIZE: 14px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px">　　i)反码和的溢出有后效性(蔓延性)</p>
<p style="PADDING-BOTTOM: 0px; LINE-HEIGHT: 23px; BORDER-RIGHT-WIDTH: 0px; MARGIN: 15px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; FONT-SIZE: 14px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px">　　反码和将高位溢出加到低位,导致这个溢出会对后面操作有永久影响,有后效性;而补码和直接将高位和溢出,导致这个溢出对后面的操作再无影响,因此无后效性</p>
<p style="PADDING-BOTTOM: 0px; LINE-HEIGHT: 23px; BORDER-RIGHT-WIDTH: 0px; MARGIN: 15px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; FONT-SIZE: 14px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px">　　ii)反码校验无需考虑字节序</p>
<p style="PADDING-BOTTOM: 0px; LINE-HEIGHT: 23px; BORDER-RIGHT-WIDTH: 0px; MARGIN: 15px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; FONT-SIZE: 14px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px">　　正因为反码和的溢出有后效性,导致大端字节序(big-endian)和小端字节序(little-endian)对同一数据序列(如两个16比特的序列)产生的校验和也只是字节序相反，而补码和因为将溢出丢掉了,不同字节序之间的校验和大不相同且没什么联系。</p>
<p style="PADDING-BOTTOM: 0px; LINE-HEIGHT: 23px; BORDER-RIGHT-WIDTH: 0px; MARGIN: 15px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; FONT-SIZE: 14px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px">　　基于以上的理由，校验和运算既可选择在数据被转换成网络字节序前，也可选择在之后，只要保证被校验的字段和填写的校验和字段的字节序保持一致就可以了。(这其实可以看作是负负得正，计算校验和与字节序有关，然后写校验和字段与字节序有关，然后直接计算校验和再写校验和字段则与字节序无关。)</p>
<p style="PADDING-BOTTOM: 0px; LINE-HEIGHT: 23px; BORDER-RIGHT-WIDTH: 0px; MARGIN: 15px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; FONT-SIZE: 14px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px">　　<strong>四、参考文章</strong></p>
<p style="PADDING-BOTTOM: 0px; LINE-HEIGHT: 23px; BORDER-RIGHT-WIDTH: 0px; MARGIN: 15px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; FONT-SIZE: 14px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px">　　http://blog.chinaunix.net/u/20/showart_438512.html，关于IP校验和的</p>
<p style="PADDING-BOTTOM: 0px; LINE-HEIGHT: 23px; BORDER-RIGHT-WIDTH: 0px; MARGIN: 15px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; FONT-SIZE: 14px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px">　　http://blog.chinaunix.net/u/12313/showart_176114.html，关于网络校验和的</p>
<p style="PADDING-BOTTOM: 0px; LINE-HEIGHT: 23px; BORDER-RIGHT-WIDTH: 0px; MARGIN: 15px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; FONT-SIZE: 14px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px">　　http://www.wesoho.com/article/Delphi/2143.htm，关于IP校验和的</p>
<p style="PADDING-BOTTOM: 0px; LINE-HEIGHT: 23px; BORDER-RIGHT-WIDTH: 0px; MARGIN: 15px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; FONT-SIZE: 14px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px">　　http://blog.chinaunix.net/u/20/showart_438418.html，关于补码和反码的</p>
</span></span>
<img src ="http://www.cppblog.com/flyonok/aggbug/144311.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyonok/" target="_blank">flyonok</a> 2011-04-15 15:22 <a href="http://www.cppblog.com/flyonok/archive/2011/04/15/144311.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> __THROW是什么东西？</title><link>http://www.cppblog.com/flyonok/archive/2011/04/15/144289.html</link><dc:creator>flyonok</dc:creator><author>flyonok</author><pubDate>Fri, 15 Apr 2011 03:57:00 GMT</pubDate><guid>http://www.cppblog.com/flyonok/archive/2011/04/15/144289.html</guid><wfw:comment>http://www.cppblog.com/flyonok/comments/144289.html</wfw:comment><comments>http://www.cppblog.com/flyonok/archive/2011/04/15/144289.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyonok/comments/commentRss/144289.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyonok/services/trackbacks/144289.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要:  __THROW是什么东西？&nbsp;&nbsp;<a href='http://www.cppblog.com/flyonok/archive/2011/04/15/144289.html'>阅读全文</a><img src ="http://www.cppblog.com/flyonok/aggbug/144289.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyonok/" target="_blank">flyonok</a> 2011-04-15 11:57 <a href="http://www.cppblog.com/flyonok/archive/2011/04/15/144289.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>centos的ADSL（pppoe设置）</title><link>http://www.cppblog.com/flyonok/archive/2011/04/01/143209.html</link><dc:creator>flyonok</dc:creator><author>flyonok</author><pubDate>Fri, 01 Apr 2011 08:09:00 GMT</pubDate><guid>http://www.cppblog.com/flyonok/archive/2011/04/01/143209.html</guid><wfw:comment>http://www.cppblog.com/flyonok/comments/143209.html</wfw:comment><comments>http://www.cppblog.com/flyonok/archive/2011/04/01/143209.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyonok/comments/commentRss/143209.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyonok/services/trackbacks/143209.html</trackback:ping><description><![CDATA[<span style="WIDOWS: 2; TEXT-TRANSFORM: none; TEXT-INDENT: 0px; BORDER-COLLAPSE: separate; FONT: medium Simsun; WHITE-SPACE: normal; ORPHANS: 2; LETTER-SPACING: normal; COLOR: rgb(0,0,0); WORD-SPACING: 0px; -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" class=Apple-style-span><span style="TEXT-ALIGN: left; FONT-FAMILY: 新細明體, 'Times New Roman', serif; FONT-SIZE: 15px" class=Apple-style-span><span style="FONT: bold 13pt 新細明體, serif; COLOR: rgb(0,0,187)" class=text_h2>4.2.3 ADSL 撥接上網 (適用台灣 ADSL 撥接以及光纖到大樓)</span><br>
<div style="TEXT-ALIGN: left; PADDING-BOTTOM: 10px; PADDING-LEFT: 25px; PADDING-RIGHT: 0px; PADDING-TOP: 10px" class=block2>
<p>終於來到台灣最熱門的 ADSL 撥接上網的介紹啦！來談一談如何在 Linux 上撥接上網吧！ 要撥接上網時，可以使用 rp-pppoe 這套軟體來幫忙(<a style="COLOR: blue; TEXT-DECORATION: none" href="http://linux.vbird.org/linux_server/0130internet_connect.php#ps1">註1</a>)，所以，你必須要確認你的 Linux distributions 上面已經存在這個玩意兒了！CentOS 本身就含有 rp-pppoe ，請使用原版光碟，或者是使用 yum 來進行安裝吧！</p>
<table style="BORDER-BOTTOM: rgb(255,204,204) 3px groove; BORDER-LEFT: rgb(255,204,204) 3px groove; BACKGROUND-COLOR: rgb(0,0,0); MARGIN: 10px 0px; WIDTH: 580px; BORDER-TOP: rgb(255,204,204) 3px groove; BORDER-RIGHT: rgb(255,204,204) 3px groove" class=term>
    <tbody>
        <tr>
            <td style="FONT: 10pt 細明體, Fixedsys, serif; COLOR: rgb(255,255,255)" class=term>
            <pre>[root@www ~]# <span style="FONT: bolder 10pt 細明體, Fixedsys, serif; COLOR: yellow" class=term_command>rpm -q rp-pppoe</span>
            rp-pppoe-3.5-32.1    <span style="FONT: 10pt 細明體, Fixedsys, serif; COLOR: rgb(255,102,102)" class=term_say>&lt;==你瞧瞧！確實有安裝喔！理論上，預設都會安裝啦！</span>
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<p>當然，很多 distributions 都已經將撥接這個動作歸類到圖形介面裡面去了，所以可能沒有提供 rp-pppoe 這個咚咚，沒關係，你可以到底下的網站去取得的：</p>
<ul>
    <li><a style="COLOR: blue; TEXT-DECORATION: none" href="http://www.roaringpenguin.com/pppoe/" target=_blank>http://www.roaringpenguin.com/pppoe/</a></li>
    <li><a style="COLOR: blue; TEXT-DECORATION: none" href="http://freshmeat.net/projects/rp-pppoe/" target=_blank>http://freshmeat.net/projects/rp-pppoe/</a></li>
</ul>
<p>然後再自行手動安裝即可。如何安裝的過程鳥哥在這裡就不談了，請自行前往基礎篇的<a style="COLOR: blue; TEXT-DECORATION: none" href="http://linux.vbird.org/linux_basic/0520source_code_and_tarball.php">原始碼與 Tarball 章節</a>查閱相關資料吧。 另外請注意，雖然整個連線是由主機的乙太網路卡連接到 ADSL 數據機上，然後再透過電話線路連線到 ISP 的機房去，最後在主機上以 rp-pppoe 撥接達成連線。但是<span class=Apple-converted-space>&nbsp;</span><span style="FONT: 11pt 新細明體, serif; COLOR: rgb(0,0,136)" class=text_import2>rp-pppoe 使用的是 Point to Point (ppp) over Ethernet 的點對點協定所產生的網路介面，因此當你順利的撥接成功之後， 會多產生一個實體網路介面『 ppp0 』</span>喔！</p>
<p>而由於 ppp0 是架構在乙太網路卡上的，你必須要有乙太網卡，同時，即使撥接成功後，你也不能將沒有用到的 eth0 關閉喔！注意注意！因此，撥接成功後就會有：</p>
<ul style="FONT: 11pt 新細明體, serif; COLOR: rgb(0,0,136)" class=text_import2>
    <li>內部迴圈測試用的 lo 介面；</li>
    <li>網路卡 eth0 這個介面；</li>
    <li>撥接之後產生的經由 ISP 對外連接的 ppp0 介面。</li>
</ul>
<p>雖然 ppp0 是架構在乙太網卡上面的，但<span style="FONT: 11pt 新細明體, serif; COLOR: rgb(0,0,136)" class=text_import2>上頭這三個介面在使用上是完全獨立的，互不相干</span>， 所以關於 eth0 的使用上，你就可以這樣思考：</p>
<ul style="PADDING-LEFT: 20px">
    <li><span style="FONT: bold 11pt 新細明體, serif; COLOR: rgb(0,0,136)" class=text_import1>這張網路卡 (假設是 eth0) 有接內部網路(LAN)</span>：<br><br>舉例來說，如果你的區域網路如同第三章的<a style="COLOR: blue; TEXT-DECORATION: none" href="http://linux.vbird.org/linux_server/0120intranet.php#fig3.1-1">圖3.1-1</a><span class=Apple-converted-space>&nbsp;</span>所示，也就是說，你的 ppp0 可以連上 Internet ，但是內網則使用 eth0 來跟其他內部主機連線時， 那麼你的 IP 設定參數： /etc/sysconfig/network-scripts/ifcfg-eth0 應該要給予一個私有 IP 以使內部的 LAN 也可以透過 eth0 來進行連線啊！所以我會這樣設定：<br>
    <table style="BORDER-BOTTOM: rgb(255,204,204) 3px groove; BORDER-LEFT: rgb(255,204,204) 3px groove; BACKGROUND-COLOR: rgb(0,0,0); MARGIN: 10px 0px; WIDTH: 580px; BORDER-TOP: rgb(255,204,204) 3px groove; BORDER-RIGHT: rgb(255,204,204) 3px groove" class=term>
        <tbody>
            <tr>
                <td style="FONT: 10pt 細明體, Fixedsys, serif; COLOR: rgb(255,255,255)" class=term>
                <pre>[root@www ~]# <span style="FONT: bolder 10pt 細明體, Fixedsys, serif; COLOR: yellow" class=term_command>vim /etc/sysconfig/network-scripts/ifcfg-eth0</span>
                <span style="FONT: 10pt 細明體, Fixedsys, serif; COLOR: yellow" class=term_write>DEVICE=eth0
                BOOTPROTO=none
                BROADCAST=192.168.1.255
                IPADDR=192.168.1.11
                NETMASK=255.255.255.0
                ONBOOT=yes</span>
                </pre>
                </td>
            </tr>
        </tbody>
    </table>
    並請記得一件事情，那就是：『<span style="FONT: 11pt 新細明體, serif; COLOR: rgb(0,0,136)" class=text_import2>千萬不要有 GATEWAY 的設定！</span>』， 因為 ppp0 撥接成功後， ISP 會主動的給予 ppp0 介面一個可以連上 Internet 的 default gateway ， 如果你又設定另一個 default gateway ，兩個閘道器可能會造成你的網路不通喔！<br><br></li>
    <li><span style="FONT: bold 11pt 新細明體, serif; COLOR: rgb(0,0,136)" class=text_import1>這部主機僅有連接 ADSL 數據機，並沒有內部網域</span>：<br><br>如果這部 Linux 主機是直接連接到 ADSL 數據機上頭，並沒有任何內部主機與其連線，也就是說，你的 eth0 有沒有 IP 都沒有關係時，那麼上面的設定當中的那個『 ONBOOT=yes 』直接改成『 ONBOOT=no 』就好了！那撥接不會有問題嗎？ 沒關係啊，因為你撥接啟動 ppp0 時，系統會主動的喚醒 eth0 ，只是 eth0 不會有 IP 資訊就是了。</li>
</ul>
<p>至於其他的檔案請參考<a style="COLOR: blue; TEXT-DECORATION: none" href="http://linux.vbird.org/linux_server/0130internet_connect.php#connect_fix_IP">手動設定 IP 的連線方法</a>來處理即可。 當然啦，撥接之前，請確認你的 ADSL 數據機 (小烏龜) 已經與主機連線妥當，也取得帳號與密碼，也安裝好了 rp-pppoe ，然後就來處理吧！</p>
<ol style="PADDING-LEFT: 20px">
    <li><span style="FONT: bold 11pt 新細明體, serif; COLOR: rgb(0,0,136)" class=text_import1>設定連接到 ADSL 數據機那張網卡 (暫訂為 eth0)</span><br><br>說實在的，鳥哥比較建議將內外網域分的清清楚楚比較好，所以，通常我都是主機上面接兩塊網路卡， 一張對內一張對外，對外的那張網卡預設是不啟動的 (ONBOOT=no)。考慮到你可能僅有一張網卡，那麼鳥哥也會給你建議， 直接給 eth0 一個私有 IP 介面吧！設定就如同本節稍早提到的那樣囉！<br><br></li>
    <li><span style="FONT: bold 11pt 新細明體, serif; COLOR: rgb(0,0,136)" class=text_import1>設定撥接的帳號與密碼</span><br><br>好了，那麼開始來設定你的帳號與密碼吧！這個動作只要在第一次建立帳號/密碼時處理即可，未來除非帳號密碼改變了， 否則這個動作都不需要重新處理啦！<br>
    <table style="BORDER-BOTTOM: rgb(255,204,204) 3px groove; BORDER-LEFT: rgb(255,204,204) 3px groove; BACKGROUND-COLOR: rgb(0,0,0); MARGIN: 10px 0px; WIDTH: 580px; BORDER-TOP: rgb(255,204,204) 3px groove; BORDER-RIGHT: rgb(255,204,204) 3px groove" class=term>
        <tbody>
            <tr>
                <td style="FONT: 10pt 細明體, Fixedsys, serif; COLOR: rgb(255,255,255)" class=term>
                <pre>[root@www ~]# <span style="FONT: bolder 10pt 細明體, Fixedsys, serif; COLOR: yellow" class=term_command>adsl-setup</span>
                Welcome to the ADSL client setup.  First, I will run some checks on
                your system to make sure the PPPoE client is installed properly...
                LOGIN NAME
                Enter your Login Name (default root): <span style="FONT: bolder 10pt 細明體, Fixedsys, serif; COLOR: yellow" class=term_command>T1234567</span>
                <span style="FONT: 10pt 細明體, Fixedsys, serif; COLOR: rgb(255,102,102)" class=term_say># 注意啊！這個帳號名稱是 ISP 給的，其中如果是 SeedNet ，輸入如上，
                # 如果是 Hinet 的話，就得要輸入 username@hinet.com.tw ，後面的主機名也要寫。</span>
                INTERFACE
                Enter the Ethernet interface connected to the ADSL modem
                For Solaris, this is likely to be something like /dev/hme0.
                For Linux, it will be ethX, where 'X' is a number.
                (default eth0): <span style="FONT: bolder 10pt 細明體, Fixedsys, serif; COLOR: yellow" class=term_command>eth0</span>
                <span style="FONT: 10pt 細明體, Fixedsys, serif; COLOR: rgb(255,102,102)" class=term_say># 就是連接到 ADSL 數據機的那張網卡代號</span>
                Do you want the link to come up on demand, or stay up continuously?
                If you want it to come up on demand, enter the idle time in seconds
                after which the link should be dropped.  If you want the link to
                stay up permanently, enter 'no' (two letters, lower-case.)
                NOTE: Demand-activated links do not interact well with dynamic IP
                addresses.  You may have some problems with demand-activated links.
                Enter the demand value (default no): <span style="FONT: 10pt 細明體, Fixedsys, serif; COLOR: yellow" class=term_write>&lt;==這裡按 Enter 確定不要即可</span>
                DNS
                Enter the DNS information here: <span style="FONT: bolder 10pt 細明體, Fixedsys, serif; COLOR: yellow" class=term_command>168.95.1.1</span>
                Enter the secondary DNS server address here: <span style="FONT: bolder 10pt 細明體, Fixedsys, serif; COLOR: yellow" class=term_command>139.175.10.20</span>
                <span style="FONT: 10pt 細明體, Fixedsys, serif; COLOR: rgb(255,102,102)" class=term_say># 這兩個設定會影響 /etc/resolv.conf 的內容喔！</span>
                PASSWORD
                Please enter your Password: <span style="FONT: 10pt 細明體, Fixedsys, serif; COLOR: yellow" class=term_write>&lt;==這裡則是輸入你 ISP 給的密碼</span>
                Please re-enter your Password: <span style="FONT: 10pt 細明體, Fixedsys, serif; COLOR: yellow" class=term_write>&lt;==再一次密碼</span>
                USERCTRL
                Please enter 'yes' (two letters, lower-case.) if you want to allow
                normal user to start or stop DSL connection (default yes): <span style="FONT: bolder 10pt 細明體, Fixedsys, serif; COLOR: yellow" class=term_command>no</span>
                <span style="FONT: 10pt 細明體, Fixedsys, serif; COLOR: rgb(255,102,102)" class=term_say># 不讓使用者可以啟動或關閉 ADSL 的設定比較好吧！</span>
                The firewall choices are:
                0 - NONE: This script will not set any firewall rules.  You are responsible
                for ensuring the security of your machine.  You are STRONGLY
                recommended to use some kind of firewall rules.
                1 - STANDALONE: Appropriate for a basic stand-alone web-surfing workstation
                2 - MASQUERADE: Appropriate for a machine acting as an Internet gateway
                for a LAN
                Choose a type of firewall (0-2): <span style="FONT: bolder 10pt 細明體, Fixedsys, serif; COLOR: yellow" class=term_command>0</span>
                <span style="FONT: 10pt 細明體, Fixedsys, serif; COLOR: rgb(255,102,102)" class=term_say># 先不要 ppp 的防火牆！後面我們會使用 Linux 本機的防火牆！</span>
                Start this connection at boot time
                Do you want to start this connection at boot time?
                Please enter no or yes (default no):<span style="FONT: bolder 10pt 細明體, Fixedsys, serif; COLOR: yellow" class=term_command>yes</span>
                <span style="FONT: 10pt 細明體, Fixedsys, serif; COLOR: rgb(255,102,102)" class=term_say># 是否要開機的時候就撥接？如果你的數據機是一直開著的，這裡使用 yes 較佳</span>
                Ethernet Interface: eth0
                User name:          T1234567
                Activate-on-demand: No
                Primary DNS:        168.95.1.1
                Secondary DNS:      139.175.10.20
                Firewalling:        NONE
                User Control:       no
                Accept these settings and adjust configuration files (y/n)? <span style="FONT: bolder 10pt 細明體, Fixedsys, serif; COLOR: yellow" class=term_command>y</span>
                <span style="FONT: 10pt 細明體, Fixedsys, serif; COLOR: rgb(255,102,102)" class=term_say># 如果沒有問題就按下 y 開始寫入設定檔吧！</span>
                Adjusting /etc/sysconfig/network-scripts/<span style="FONT: 10pt 細明體, Fixedsys, serif; COLOR: yellow" class=term_write>ifcfg-ppp0</span>
                Adjusting /etc/<span style="FONT: 10pt 細明體, Fixedsys, serif; COLOR: yellow" class=term_write>resolv.conf</span>
                (But first backing it up to /etc/resolv.conf.bak)
                Adjusting /etc/ppp/<span style="FONT: 10pt 細明體, Fixedsys, serif; COLOR: yellow" class=term_write>chap-secrets</span> and <span style="FONT: 10pt 細明體, Fixedsys, serif; COLOR: yellow" class=term_write>/etc/ppp/pap-secrets</span>
                (But first backing it up to /etc/ppp/chap-secrets.bak)
                (But first backing it up to /etc/ppp/pap-secrets.bak)
                <span style="FONT: 10pt 細明體, Fixedsys, serif; COLOR: rgb(255,102,102)" class=term_say># 上面具有特殊字體的檔案主要功能是：
                # ifcfg-ppp0  ：亦即是 ppp0 這個網路介面的設定檔案；
                # resolv.conf ：這個檔案會被備份後，然後以剛剛我們上面輸入的 DNS 資料取代；
                # pap-secrets, chap-secrets：我們輸入的密碼就放在這裡！</span>
                </pre>
                </td>
            </tr>
        </tbody>
    </table>
    這樣設定就成功啦！很簡單吧！唯一需要注意的是在上面的 username 那個地方，千萬注意， 因為 hinet 與 seednet 的設定是不一樣的！千萬小心呢！否則會無法連上線呦！此外， 由於我們在未來還會有 firewall 的建置，所以這裡不太需要使用到防火牆啦！否則也可能無法連上 Internet 呦！另外，注意一下，一般撥接需要的身份認證機制透過的是 chap 與 pap(<a style="COLOR: blue; TEXT-DECORATION: none" href="http://linux.vbird.org/linux_server/0130internet_connect.php#ps2">註2</a>)， 在 rp-pppoe 這套軟體中，就將兩種認證機制所需的資料通通記錄下來啦！那就是 chap-secrets, pap-secrets， 你可以分別察看兩個檔案的內容，就知道那是啥咚咚了！<br><br></li>
    <li><span style="FONT: bold 11pt 新細明體, serif; COLOR: rgb(0,0,136)" class=text_import1>透過 adsl-start, adsl-connect 或 network restart 開始撥接上網</span><br><br>啟動 ADSL 的方法很多，通常鳥哥都是使用 /etc/init.d/network restart 即可處理！不過，如果發生一些不明的錯誤， 也可以使用 adsl-stop 關閉後再以 adsl-start 立即啟動撥接試看看。一切順利的話，會如同下面的畫面：<br>
    <table style="BORDER-BOTTOM: rgb(255,204,204) 3px groove; BORDER-LEFT: rgb(255,204,204) 3px groove; BACKGROUND-COLOR: rgb(0,0,0); MARGIN: 10px 0px; WIDTH: 580px; BORDER-TOP: rgb(255,204,204) 3px groove; BORDER-RIGHT: rgb(255,204,204) 3px groove" class=term>
        <tbody>
            <tr>
                <td style="FONT: 10pt 細明體, Fixedsys, serif; COLOR: rgb(255,255,255)" class=term>
                <pre>[root@www ~]# <span style="FONT: bolder 10pt 細明體, Fixedsys, serif; COLOR: yellow" class=term_command>adsl-start</span>
                ....Connect!
                </pre>
                </td>
            </tr>
        </tbody>
    </table>
    這樣就是顯示連上 Internet 啦！通常比較容易出問題的地方在於硬體的連線情況，請先確認所有的硬體連線沒有問題喔！ 通常，如果你使用小烏龜 (ATU-R) 時，請使用跳線連接網路卡與 ATU-R。另外一個容易出錯的地方在於輸入的帳號與密碼， 帳號與密碼都是你的 ISP 給你的，並且注意大小寫(可以到 /etc/ppp/{chap,pap}-secrets 察看一下是否設定錯誤？)<br><br></li>
    <li><span style="FONT: bold 11pt 新細明體, serif; COLOR: rgb(0,0,136)" class=text_import1>開始檢查的步驟：</span><br><br>上面的步驟搞定就可以連上 Internet 了。如果擔心設定方面有問題，可以透過手動設定 IP 的那個小節的五個步驟去檢查看看， 指令分別是：<br>
    <table style="BORDER-BOTTOM: rgb(255,204,204) 3px groove; BORDER-LEFT: rgb(255,204,204) 3px groove; BACKGROUND-COLOR: rgb(0,0,0); MARGIN: 10px 0px; WIDTH: 580px; BORDER-TOP: rgb(255,204,204) 3px groove; BORDER-RIGHT: rgb(255,204,204) 3px groove" class=term>
        <tbody>
            <tr>
                <td style="FONT: 10pt 細明體, Fixedsys, serif; COLOR: rgb(255,255,255)" class=term>
                <pre>[root@www ~]# <span style="FONT: bolder 10pt 細明體, Fixedsys, serif; COLOR: yellow" class=term_command>ifconfig</span>
                [root@www ~]# <span style="FONT: bolder 10pt 細明體, Fixedsys, serif; COLOR: yellow" class=term_command>route -n</span>
                [root@www ~]# <span style="FONT: bolder 10pt 細明體, Fixedsys, serif; COLOR: yellow" class=term_command>ping GW的IP</span>
                [root@www ~]# <span style="FONT: bolder 10pt 細明體, Fixedsys, serif; COLOR: yellow" class=term_command>dig www.google.com</span>
                [root@www ~]# <span style="FONT: bolder 10pt 細明體, Fixedsys, serif; COLOR: yellow" class=term_command>hostname</span>
                </pre>
                </td>
            </tr>
        </tbody>
    </table>
    比較特殊的是，因為 ADSL 撥接是透過點對點 (ppp) 協定，所謂的點對點，就是你的 ppp0 直接連接到 ISP 的某個點 (IP) ， 所以，理論上，ppp0 是個獨立的 IP ，並沒有子網路！因此，當你察看 ppp0 的網路參數時，他會變成這樣：<br>
    <table style="BORDER-BOTTOM: rgb(255,204,204) 3px groove; BORDER-LEFT: rgb(255,204,204) 3px groove; BACKGROUND-COLOR: rgb(0,0,0); MARGIN: 10px 0px; WIDTH: 580px; BORDER-TOP: rgb(255,204,204) 3px groove; BORDER-RIGHT: rgb(255,204,204) 3px groove" class=term>
        <tbody>
            <tr>
                <td style="FONT: 10pt 細明體, Fixedsys, serif; COLOR: rgb(255,255,255)" class=term>
                <pre>[root@www ~]# <span style="FONT: bolder 10pt 細明體, Fixedsys, serif; COLOR: yellow" class=term_command>ifconfig ppp0</span>
                ppp0      Link encap:Point-to-Point Protocol
                <span style="FONT: 10pt 細明體, Fixedsys, serif; COLOR: yellow" class=term_write>inet addr:114.33.149.35  P-t-P:168.95.88.254  Mask:255.255.255.255</span>
                UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1492  Metric:1
                RX packets:216541 errors:0 dropped:0 overruns:0 frame:0
                TX packets:125009 errors:0 dropped:0 overruns:0 carrier:0
                collisions:0 txqueuelen:3
                RX bytes:283114899 (269.9 MiB)  TX bytes:11393717 (10.8 MiB)
                </pre>
                </td>
            </tr>
        </tbody>
    </table>
    如上所示，那個 inet addr 就是你的 IP ，而 P-t-P 就是 Gateway 的意思啦！你也會看到， Mask 是 255.255.255.255 哩！ 沒有子網路呦！要仔細看清楚哩！<br></li>
</ol>
</div>
</span></span>
<img src ="http://www.cppblog.com/flyonok/aggbug/143209.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyonok/" target="_blank">flyonok</a> 2011-04-01 16:09 <a href="http://www.cppblog.com/flyonok/archive/2011/04/01/143209.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Debian 下 PPPOE拨号设置</title><link>http://www.cppblog.com/flyonok/archive/2011/04/01/143208.html</link><dc:creator>flyonok</dc:creator><author>flyonok</author><pubDate>Fri, 01 Apr 2011 08:06:00 GMT</pubDate><guid>http://www.cppblog.com/flyonok/archive/2011/04/01/143208.html</guid><wfw:comment>http://www.cppblog.com/flyonok/comments/143208.html</wfw:comment><comments>http://www.cppblog.com/flyonok/archive/2011/04/01/143208.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyonok/comments/commentRss/143208.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyonok/services/trackbacks/143208.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Debian 下 PPPOE拨号设置&nbsp;&nbsp;<a href='http://www.cppblog.com/flyonok/archive/2011/04/01/143208.html'>阅读全文</a><img src ="http://www.cppblog.com/flyonok/aggbug/143208.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyonok/" target="_blank">flyonok</a> 2011-04-01 16:06 <a href="http://www.cppblog.com/flyonok/archive/2011/04/01/143208.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>linux的模块</title><link>http://www.cppblog.com/flyonok/archive/2011/04/01/143201.html</link><dc:creator>flyonok</dc:creator><author>flyonok</author><pubDate>Fri, 01 Apr 2011 07:19:00 GMT</pubDate><guid>http://www.cppblog.com/flyonok/archive/2011/04/01/143201.html</guid><wfw:comment>http://www.cppblog.com/flyonok/comments/143201.html</wfw:comment><comments>http://www.cppblog.com/flyonok/archive/2011/04/01/143201.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyonok/comments/commentRss/143201.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyonok/services/trackbacks/143201.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: linux模块&nbsp;&nbsp;<a href='http://www.cppblog.com/flyonok/archive/2011/04/01/143201.html'>阅读全文</a><img src ="http://www.cppblog.com/flyonok/aggbug/143201.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyonok/" target="_blank">flyonok</a> 2011-04-01 15:19 <a href="http://www.cppblog.com/flyonok/archive/2011/04/01/143201.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Netfilter</title><link>http://www.cppblog.com/flyonok/archive/2011/03/28/142846.html</link><dc:creator>flyonok</dc:creator><author>flyonok</author><pubDate>Mon, 28 Mar 2011 06:01:00 GMT</pubDate><guid>http://www.cppblog.com/flyonok/archive/2011/03/28/142846.html</guid><wfw:comment>http://www.cppblog.com/flyonok/comments/142846.html</wfw:comment><comments>http://www.cppblog.com/flyonok/archive/2011/03/28/142846.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyonok/comments/commentRss/142846.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyonok/services/trackbacks/142846.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: netfilter 说明&nbsp;&nbsp;<a href='http://www.cppblog.com/flyonok/archive/2011/03/28/142846.html'>阅读全文</a><img src ="http://www.cppblog.com/flyonok/aggbug/142846.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyonok/" target="_blank">flyonok</a> 2011-03-28 14:01 <a href="http://www.cppblog.com/flyonok/archive/2011/03/28/142846.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>linux服务</title><link>http://www.cppblog.com/flyonok/archive/2011/03/25/142716.html</link><dc:creator>flyonok</dc:creator><author>flyonok</author><pubDate>Fri, 25 Mar 2011 07:59:00 GMT</pubDate><guid>http://www.cppblog.com/flyonok/archive/2011/03/25/142716.html</guid><wfw:comment>http://www.cppblog.com/flyonok/comments/142716.html</wfw:comment><comments>http://www.cppblog.com/flyonok/archive/2011/03/25/142716.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyonok/comments/commentRss/142716.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyonok/services/trackbacks/142716.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: linux 服务配置&nbsp;&nbsp;<a href='http://www.cppblog.com/flyonok/archive/2011/03/25/142716.html'>阅读全文</a><img src ="http://www.cppblog.com/flyonok/aggbug/142716.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyonok/" target="_blank">flyonok</a> 2011-03-25 15:59 <a href="http://www.cppblog.com/flyonok/archive/2011/03/25/142716.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux+bridge做透明网桥</title><link>http://www.cppblog.com/flyonok/archive/2011/03/24/142642.html</link><dc:creator>flyonok</dc:creator><author>flyonok</author><pubDate>Thu, 24 Mar 2011 05:18:00 GMT</pubDate><guid>http://www.cppblog.com/flyonok/archive/2011/03/24/142642.html</guid><wfw:comment>http://www.cppblog.com/flyonok/comments/142642.html</wfw:comment><comments>http://www.cppblog.com/flyonok/archive/2011/03/24/142642.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyonok/comments/commentRss/142642.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyonok/services/trackbacks/142642.html</trackback:ping><description><![CDATA[<span style="WIDOWS: 2; TEXT-TRANSFORM: none; TEXT-INDENT: 0px; BORDER-COLLAPSE: separate; FONT: medium Simsun; WHITE-SPACE: normal; ORPHANS: 2; LETTER-SPACING: normal; COLOR: rgb(0,0,0); WORD-SPACING: 0px; -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" class=Apple-style-span><span style="TEXT-ALIGN: left; BORDER-COLLAPSE: collapse; FONT-FAMILY: Verdana, Helvetica, Arial, sans-serif; COLOR: rgb(68,68,68); FONT-SIZE: 12px" class=Apple-style-span>
<table style="LINE-HEIGHT: normal; WIDTH: 1151px; BORDER-COLLAPSE: collapse; WORD-WRAP: break-word; EMPTY-CELLS: show; TABLE-LAYOUT: fixed; MARGIN-LEFT: 1px" cellSpacing=0 cellPadding=0>
    <tbody style="LINE-HEIGHT: normal; WORD-WRAP: break-word">
        <tr style="LINE-HEIGHT: normal; WORD-WRAP: break-word">
            <td style="FONT: 14px/1.6em Verdana, Helvetica, Arial, sans-serif; WORD-WRAP: break-word; COLOR: rgb(68,68,68)" id=postmessage_13500 class=t_msgfont>作者:小飞龙<br style="LINE-HEIGHT: normal; WORD-WRAP: break-word">Linux2.6.0<span style="BORDER-BOTTOM: rgb(255,0,0) 1px solid; LINE-HEIGHT: normal; WORD-WRAP: break-word; WHITE-SPACE: nowrap; CURSOR: pointer" class=t_tag onclick=tagshow(event) href="tag.php?name=%C4%DA%BA%CB">内核</span><br style="LINE-HEIGHT: normal; WORD-WRAP: break-word">　　首先重新编译<span style="BORDER-BOTTOM: rgb(255,0,0) 1px solid; LINE-HEIGHT: normal; WORD-WRAP: break-word; WHITE-SPACE: nowrap; CURSOR: pointer" class=t_tag onclick=tagshow(event) href="tag.php?name=kernel">kernel</span>，<span style="BORDER-BOTTOM: rgb(255,0,0) 1px solid; LINE-HEIGHT: normal; WORD-WRAP: break-word; WHITE-SPACE: nowrap; CURSOR: pointer" class=t_tag onclick=tagshow(event) href="tag.php?name=make">make</span><span class=Apple-converted-space>&nbsp;</span>menuconfig.....<span class=Apple-converted-space>&nbsp;（注一般2.6以上的都默认支持</span>）注意，除了要把该编译进去的驱动编进去（象NIC什么的）还要把最重要的<span style="BORDER-BOTTOM: rgb(255,0,0) 1px solid; LINE-HEIGHT: normal; WORD-WRAP: break-word; WHITE-SPACE: nowrap; CURSOR: pointer" class=t_tag onclick=tagshow(event) href="tag.php?name=iptables">iptables</span>给enable起来，进入NetworkOptions，选中Network Packet filtering (replaces ipchains)，这样就会打开IP:Netfilter Configur<span style="BORDER-BOTTOM: rgb(255,0,0) 1px solid; LINE-HEIGHT: normal; WORD-WRAP: break-word; WHITE-SPACE: nowrap; CURSOR: pointer" class=t_tag onclick=tagshow(event) href="tag.php?name=ati">ati</span>on --&gt;; 子菜单，进入，选中里面所有的选项，然后回到NetworkOptions菜单，选中&#8220;802.1d Ethernet Bridging&#8221; 和 &#8220;netfilter (firewalling)support&#8221;两个选项（一看就知道很重要。） 退出，开编。<span class=Apple-converted-space>&nbsp;</span><br style="LINE-HEIGHT: normal; WORD-WRAP: break-word"><br style="LINE-HEIGHT: normal; WORD-WRAP: break-word"><font style="LINE-HEIGHT: normal; WORD-WRAP: break-word" color=teal>make<br style="LINE-HEIGHT: normal; WORD-WRAP: break-word">make modules_install<span class=Apple-converted-space>&nbsp;</span><br style="LINE-HEIGHT: normal; WORD-WRAP: break-word">make install</font><br style="LINE-HEIGHT: normal; WORD-WRAP: break-word"><br style="LINE-HEIGHT: normal; WORD-WRAP: break-word">　　重起，如果正常，开始下一步，tar &#8211;xzvf bridge-utils-1.1.0.tar.gz.&nbsp;&nbsp;<br style="LINE-HEIGHT: normal; WORD-WRAP: break-word"><font style="LINE-HEIGHT: normal; WORD-WRAP: break-word" color=teal>cd ./bridge-utils-1.1.0<br style="LINE-HEIGHT: normal; WORD-WRAP: break-word">make&nbsp;&nbsp;<br style="LINE-HEIGHT: normal; WORD-WRAP: break-word">make install</font>（编译bridge并安装,具体的安装目录可在make<span style="BORDER-BOTTOM: rgb(255,0,0) 1px solid; LINE-HEIGHT: normal; WORD-WRAP: break-word; WHITE-SPACE: nowrap; CURSOR: pointer" class=t_tag onclick=tagshow(event) href="tag.php?name=%CE%C4%BC%FE">文件</span>生成时指定。）<span class=Apple-converted-space>&nbsp;</span><br style="LINE-HEIGHT: normal; WORD-WRAP: break-word">完毕后可以先试试bridge的基本<span style="BORDER-BOTTOM: rgb(255,0,0) 1px solid; LINE-HEIGHT: normal; WORD-WRAP: break-word; WHITE-SPACE: nowrap; CURSOR: pointer" class=t_tag onclick=tagshow(event) href="tag.php?name=%C3%FC%C1%EE">命令</span>：<br style="LINE-HEIGHT: normal; WORD-WRAP: break-word"><font style="LINE-HEIGHT: normal; WORD-WRAP: break-word" color=teal>brctl addbr mybridge<span class=Apple-converted-space>&nbsp;</span></font>（创建bridge mybridge，然后用ifconfig查看会发现多了一个mybridge端口）<span class=Apple-converted-space>&nbsp;</span><br style="LINE-HEIGHT: normal; WORD-WRAP: break-word"><font style="LINE-HEIGHT: normal; WORD-WRAP: break-word" color=teal>brctl addif mybridge eth0&nbsp;&nbsp;<br style="LINE-HEIGHT: normal; WORD-WRAP: break-word">brctl addif mybridge eth1</font><span class=Apple-converted-space>&nbsp;</span>（把eth0和eth1包含到mybridge中）<span class=Apple-converted-space>&nbsp;</span><br style="LINE-HEIGHT: normal; WORD-WRAP: break-word"><br style="LINE-HEIGHT: normal; WORD-WRAP: break-word">然后需要对各端口做以下动作<span class=Apple-converted-space>&nbsp;</span><br style="LINE-HEIGHT: normal; WORD-WRAP: break-word"><font style="LINE-HEIGHT: normal; WORD-WRAP: break-word" color=teal>ifconfig eth0 0.0.0.0 promisc&nbsp;&nbsp;<br style="LINE-HEIGHT: normal; WORD-WRAP: break-word">ifconfig eth1 0.0.0.0 promisc</font>（打开混杂模式）<br style="LINE-HEIGHT: normal; WORD-WRAP: break-word"><font style="LINE-HEIGHT: normal; WORD-WRAP: break-word" color=teal>ifconfig mybridge up</font>(启动网桥)<span class=Apple-converted-space>&nbsp;</span><br style="LINE-HEIGHT: normal; WORD-WRAP: break-word">这时桥接即已成功，从router和局域网转发过来的消息开始通过机器，这时你会发觉满屏的tcp/ip转发消息让你无法下手，<span style="BORDER-BOTTOM: rgb(255,0,0) 1px solid; LINE-HEIGHT: normal; WORD-WRAP: break-word; WHITE-SPACE: nowrap; CURSOR: pointer" class=t_tag onclick=tagshow(event) href="tag.php?name=%D3%B2%C5%CC">硬盘</span>也狂转，这是syslogd和klogd做的怪，log的priviledge设得太低，改掉它。telnet进入机器（这时你只能telnet，console上已经泛滥成灾。）kill掉syslogd和klogd，在/etc/syslog.conf中屏蔽掉*.info至/var/log/messages的rules，并修改/etc/init.d/syslog,在daemon klogd 一项后加上-2 -c4（提高klogd的消息转发级别），重起syslogd，哈哈，整个世界清净了！！！<span class=Apple-converted-space>&nbsp;</span><br style="LINE-HEIGHT: normal; WORD-WRAP: break-word">可以用以下语句为桥接配ip<br style="LINE-HEIGHT: normal; WORD-WRAP: break-word"><font style="LINE-HEIGHT: normal; WORD-WRAP: break-word" color=teal>ifconfig mybridge 192.168.1.10 netmask 255.255.255.0</font></td>
        </tr>
    </tbody>
</table>
</span></span>
<img src ="http://www.cppblog.com/flyonok/aggbug/142642.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyonok/" target="_blank">flyonok</a> 2011-03-24 13:18 <a href="http://www.cppblog.com/flyonok/archive/2011/03/24/142642.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>linux下的curl的使用</title><link>http://www.cppblog.com/flyonok/archive/2010/10/28/131609.html</link><dc:creator>flyonok</dc:creator><author>flyonok</author><pubDate>Thu, 28 Oct 2010 03:46:00 GMT</pubDate><guid>http://www.cppblog.com/flyonok/archive/2010/10/28/131609.html</guid><wfw:comment>http://www.cppblog.com/flyonok/comments/131609.html</wfw:comment><comments>http://www.cppblog.com/flyonok/archive/2010/10/28/131609.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyonok/comments/commentRss/131609.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyonok/services/trackbacks/131609.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: linux curl&nbsp;&nbsp;<a href='http://www.cppblog.com/flyonok/archive/2010/10/28/131609.html'>阅读全文</a><img src ="http://www.cppblog.com/flyonok/aggbug/131609.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyonok/" target="_blank">flyonok</a> 2010-10-28 11:46 <a href="http://www.cppblog.com/flyonok/archive/2010/10/28/131609.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>linux下nc的使用</title><link>http://www.cppblog.com/flyonok/archive/2010/10/28/131596.html</link><dc:creator>flyonok</dc:creator><author>flyonok</author><pubDate>Thu, 28 Oct 2010 02:03:00 GMT</pubDate><guid>http://www.cppblog.com/flyonok/archive/2010/10/28/131596.html</guid><wfw:comment>http://www.cppblog.com/flyonok/comments/131596.html</wfw:comment><comments>http://www.cppblog.com/flyonok/archive/2010/10/28/131596.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyonok/comments/commentRss/131596.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyonok/services/trackbacks/131596.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: linux下nc的使用&nbsp;&nbsp;<a href='http://www.cppblog.com/flyonok/archive/2010/10/28/131596.html'>阅读全文</a><img src ="http://www.cppblog.com/flyonok/aggbug/131596.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyonok/" target="_blank">flyonok</a> 2010-10-28 10:03 <a href="http://www.cppblog.com/flyonok/archive/2010/10/28/131596.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转载IBM--不可不知的 Linux 十项重大发展</title><link>http://www.cppblog.com/flyonok/archive/2010/10/19/130473.html</link><dc:creator>flyonok</dc:creator><author>flyonok</author><pubDate>Tue, 19 Oct 2010 09:40:00 GMT</pubDate><guid>http://www.cppblog.com/flyonok/archive/2010/10/19/130473.html</guid><wfw:comment>http://www.cppblog.com/flyonok/comments/130473.html</wfw:comment><comments>http://www.cppblog.com/flyonok/archive/2010/10/19/130473.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyonok/comments/commentRss/130473.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyonok/services/trackbacks/130473.html</trackback:ping><description><![CDATA[<a title="不可不知的 Linux 十项重大发展" href="http://www.ibm.com/developerworks/cn/linux/l-linux-10th-anniversary/?S_TACT=105AGX52&amp;S_CMP=tec-csdn" target=_blank>不可不知的 Linux 十项重大发展</a>
<img src ="http://www.cppblog.com/flyonok/aggbug/130473.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyonok/" target="_blank">flyonok</a> 2010-10-19 17:40 <a href="http://www.cppblog.com/flyonok/archive/2010/10/19/130473.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Sys/queue.h-howto（转载）</title><link>http://www.cppblog.com/flyonok/archive/2010/09/11/126370.html</link><dc:creator>flyonok</dc:creator><author>flyonok</author><pubDate>Fri, 10 Sep 2010 16:23:00 GMT</pubDate><guid>http://www.cppblog.com/flyonok/archive/2010/09/11/126370.html</guid><wfw:comment>http://www.cppblog.com/flyonok/comments/126370.html</wfw:comment><comments>http://www.cppblog.com/flyonok/archive/2010/09/11/126370.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyonok/comments/commentRss/126370.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyonok/services/trackbacks/126370.html</trackback:ping><description><![CDATA[<h2><span class=mw-headline>引言 </span></h2>
<p>链表是最常用的数据结构，而且具有多种变种，比较常见的包括：单链表，双向链表，双向循环俩表，队列。在使用 C 语言编程的时候，一般会使用第三方的函数库提供的链表实现，而使用 C++ 和 Java 等语言的时候则使用标准的函数库提供的链表。 </p>
<p>单向与双向链表之间的最大差别是删除元素操作的性能，在单向链表中删除一个元素需要遍历链表，复杂度为 O(n)，而在双向链表中则只需要直接删除，复杂度为 O(1)。但是，这只是理论上的结果，实际使用中能否达到 O(1) 性能依赖于链表的实现方法以及使用链表的方法。例如，在 GLib 的双向链表实现中，就提供了两种从链表中删除一个元素的方法： </p>
<div dir=ltr>
<div style="FONT-FAMILY: monospace" class="cpp source-cpp">
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">typedef&nbsp;</span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000">&nbsp;{<br>gpointer&nbsp;data;<br>GList&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">next;<br>GList&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">prev;<br>}&nbsp;GList;<br>&nbsp;<br>GList</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g_list_remove&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(GList&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">list,<br>gconstpointer&nbsp;data);<br>GList</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g_list_remove_link&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(GList&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">list,<br>GList&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">llink);<br></span></div>
</div>
</div>
<p>第一个函数从链表中删除包含 data 这个指针的链表元素，这个操作需要首先遍历链表，找到包含这个指针的元素，然后删除，因此依然需要 O(n) 时间；第二个函数直接删除一个链表元素，因此只需要 O(1) 时间。在多数情况下，链表的用户只会保存 data 指针，而不保存链表元素指针，所以多数情况下第一个函数会被使用，这样就降低了删除的效率。 </p>
<p>其实操作系统已经为我们提供了优化的链表实现，它避免了上述的性能问题，不过使用起来稍微复杂一点，这些数据结构是作为宏是现在 sys/queue.h 头文件的。 </p>
<a id=sys.2Fqueue.h_.E7.9A.84.E5.AE.9E.E7.8E.B0.E4.B8.8E.E5.BA.94.E7.94.A8 name=sys.2Fqueue.h_.E7.9A.84.E5.AE.9E.E7.8E.B0.E4.B8.8E.E5.BA.94.E7.94.A8></a>
<h2><span class=mw-headline>sys/queue.h 的实现与应用 </span></h2>
<p>由于 sys/queue.h 提供的链表实现与一般课本上的不同，所以先了解它的实现会更容易理解如何去使用它。这个头文件提供了单链表，双向链表，单向队列，双向队列和双向循环队列，下面只以双向链表为例，其他的从原理上讲都是一样的。 </p>
<p>双向链表的实现如下： </p>
<div dir=ltr>
<div style="FONT-FAMILY: monospace" class="c source-c">
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #008000">/*</span><span style="COLOR: #008000"><br>*&nbsp;List&nbsp;definitions.<br></span><span style="COLOR: #008000">*/</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;LIST_HEAD(name,&nbsp;type)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000">&nbsp;name&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;\<br></span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000">&nbsp;type&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">lh_first;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">&nbsp;first&nbsp;element&nbsp;</span><span style="COLOR: #008000">*/</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br>}<br>&nbsp;<br></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;LIST_HEAD_INITIALIZER(head)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\</span><span style="COLOR: #000000"><br>{&nbsp;NULL&nbsp;}<br>&nbsp;<br></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;LIST_ENTRY(type)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000">&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br></span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000">&nbsp;type&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">le_next;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">&nbsp;next&nbsp;element&nbsp;</span><span style="COLOR: #008000">*/</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br></span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000">&nbsp;type&nbsp;</span><span style="COLOR: #000000">**</span><span style="COLOR: #000000">le_prev;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">&nbsp;address&nbsp;of&nbsp;previous&nbsp;next&nbsp;element&nbsp;</span><span style="COLOR: #008000">*/</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;\<br>}<br>&nbsp;<br></span><span style="COLOR: #008000">/*</span><span style="COLOR: #008000"><br>*&nbsp;List&nbsp;functions.<br></span><span style="COLOR: #008000">*/</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;LIST_INIT(head)&nbsp;do&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\</span><span style="COLOR: #000000"><br>(head)</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">lh_first&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;NULL;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br>}&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">CONSTCOND</span><span style="COLOR: #008000">*/</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)<br>&nbsp;<br></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;LIST_INSERT_AFTER(listelm,&nbsp;elm,&nbsp;field)&nbsp;do&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(((elm)</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">field.le_next&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(listelm)</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">field.le_next)&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;NULL)&nbsp;&nbsp;&nbsp;&nbsp;\<br>(listelm)</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">field.le_next</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">field.le_prev&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br></span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">(elm)</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">field.le_next;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br>(listelm)</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">field.le_next&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(elm);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br>(elm)</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">field.le_prev&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">(listelm)</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">field.le_next;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br>}&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">CONSTCOND</span><span style="COLOR: #008000">*/</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)<br>&nbsp;<br></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;LIST_INSERT_BEFORE(listelm,&nbsp;elm,&nbsp;field)&nbsp;do&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\</span><span style="COLOR: #000000"><br>(elm)</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">field.le_prev&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(listelm)</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">field.le_prev;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br>(elm)</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">field.le_next&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(listelm);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br></span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">(listelm)</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">field.le_prev&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(elm);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br>(listelm)</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">field.le_prev&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">(elm)</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">field.le_next;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br>}&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">CONSTCOND</span><span style="COLOR: #008000">*/</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)<br>&nbsp;<br></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;LIST_INSERT_HEAD(head,&nbsp;elm,&nbsp;field)&nbsp;do&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(((elm)</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">field.le_next&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(head)</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">lh_first)&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;NULL)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br>(head)</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">lh_first</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">field.le_prev&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">(elm)</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">field.le_next;\<br>(head)</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">lh_first&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(elm);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br>(elm)</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">field.le_prev&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">(head)</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">lh_first;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br>}&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">CONSTCOND</span><span style="COLOR: #008000">*/</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)<br>&nbsp;<br></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;LIST_REMOVE(elm,&nbsp;field)&nbsp;do&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;((elm)</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">field.le_next&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;NULL)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br>(elm)</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">field.le_next</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">field.le_prev&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br>(elm)</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">field.le_prev;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br></span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">(elm)</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">field.le_prev&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(elm)</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">field.le_next;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br>}&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">CONSTCOND</span><span style="COLOR: #008000">*/</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)<br>&nbsp;<br></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;LIST_FOREACH(var,&nbsp;head,&nbsp;field)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">&nbsp;((var)&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;((head)</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">lh_first);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br>(var);&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;\<br>(var)&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;((var)</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">field.le_next))<br>&nbsp;<br></span><span style="COLOR: #008000">/*</span><span style="COLOR: #008000"><br>*&nbsp;List&nbsp;access&nbsp;methods.<br></span><span style="COLOR: #008000">*/</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;LIST_EMPTY(head)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((head)-&gt;lh_first&nbsp;==&nbsp;NULL)</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;LIST_FIRST(head)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((head)-&gt;lh_first)</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;LIST_NEXT(elm,&nbsp;field)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((elm)-&gt;field.le_next)</span><span style="COLOR: #000000"><br></span></div>
</div>
</div>
<p>这种链表实现与上面 GList 的实现的根本区别在于，queue.h 的链表是用户数据结构里面包含链表元素，而 GList 是链表元素包含用户数据结构。也就是说，为了使用 queue.h 提供的链表，用户数据结构 data 必须定义成 </p>
<div dir=ltr>
<div style="FONT-FAMILY: monospace" class="c source-c">
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000">&nbsp;data&nbsp;{<br><img src="http://www.cppblog.com/Images/dot.gif"><img src="http://www.cppblog.com/Images/dot.gif"><br>LIST_ENTRY&nbsp;(data)&nbsp;list_entry;<br><img src="http://www.cppblog.com/Images/dot.gif"><img src="http://www.cppblog.com/Images/dot.gif"><br>};<br></span></div>
</div>
</div>
<p>经过宏展开之后，就变成 </p>
<div dir=ltr>
<div style="FONT-FAMILY: monospace" class="c source-c">
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000">&nbsp;data&nbsp;{<br><img src="http://www.cppblog.com/Images/dot.gif"><img src="http://www.cppblog.com/Images/dot.gif"><br></span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000">&nbsp;{<br></span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000">&nbsp;data&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">le_next;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">&nbsp;next&nbsp;element&nbsp;</span><span style="COLOR: #008000">*/</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000">&nbsp;data&nbsp;</span><span style="COLOR: #000000">**</span><span style="COLOR: #000000">le_prev;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">&nbsp;address&nbsp;of&nbsp;previous&nbsp;next&nbsp;element&nbsp;</span><span style="COLOR: #008000">*/</span><span style="COLOR: #000000"><br>}&nbsp;list_entry;<br><img src="http://www.cppblog.com/Images/dot.gif"><img src="http://www.cppblog.com/Images/dot.gif"><br>};<br></span></div>
</div>
</div>
<div class="thumb tright"><img border=0 alt="" src="http://www.cppblog.com/images/cppblog_com/flyonok/Queue.png" width=329 height=122></div>
<p>通过仔细分析 queue.h 中的源代码，可以发现链表中相邻的两个用户数据之间形成了右图所示的关系。需要特别注意的是，le_prev 指针指向的是前一个元素的 le_next 指针，而不是前一个元素，所以链表各种操作的实现与我们在课本上学到的也有所不同。 </p>
<p>下面简要说明一下各个宏的含义： </p>
<ul>
    <li>LIST_HEAD 宏定义一个链表头结构，里面包含一个指向第一个链表元素的指针，name 是头结构的名字，type 是用户数据结构的类型名。在使用这个链表之前，需要 LIST_INIT 宏初始化链表头，注意参数是到链表头结构的指针。
    <li>各种链表操作都以到用户数据的指针为参数，还需要提供用户数据结构中链表元素域的名字，例如在上面的例子中，data 结构里面链表元素域为 list_entry。 </li>
</ul>
<p>正是因为链表元素是包含在用户数据结构中的，所以用户只需要提供用户数据的指针就能以 O(1) 的复杂度删除一个元素了，如果一个用户数据结构同时在多个链表中，就需要在用户数据结构里面定义多个链表元素域。事实上，Linux 内核中的链表就是用类似的方法定义的。 </p>
<p>下面是一个使用 sys/queue.h 中双向链表的简单例子（修改自 man 文档） <br></p>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">LIST_HEAD(listhead,&nbsp;data)&nbsp;head;<br></span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000">&nbsp;data&nbsp;{<br><img src="http://www.cppblog.com/Images/dot.gif"><br>LIST_ENTRY(data)&nbsp;list_entry;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">&nbsp;List.&nbsp;</span><span style="COLOR: #008000">*/</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/dot.gif"><br>}&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">n1,&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">n2,&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">np;<br>&nbsp;<br>LIST_INIT(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">head);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">&nbsp;Initialize&nbsp;the&nbsp;list.&nbsp;</span><span style="COLOR: #008000">*/</span><span style="COLOR: #000000"><br>&nbsp;<br>n1&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;malloc(</span><span style="COLOR: #0000ff">sizeof</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000">&nbsp;data));&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">&nbsp;Insert&nbsp;at&nbsp;the&nbsp;head.&nbsp;</span><span style="COLOR: #008000">*/</span><span style="COLOR: #000000"><br>LIST_INSERT_HEAD(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">head,&nbsp;n1,&nbsp;list_entry);<br>&nbsp;<br>n2&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;malloc(</span><span style="COLOR: #0000ff">sizeof</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000">&nbsp;data));&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">&nbsp;Insert&nbsp;after.&nbsp;</span><span style="COLOR: #008000">*/</span><span style="COLOR: #000000"><br>LIST_INSERT_AFTER(n1,&nbsp;n2,&nbsp;list_entry);<br></span><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">&nbsp;Forward&nbsp;traversal.&nbsp;</span><span style="COLOR: #008000">*/</span><span style="COLOR: #000000"><br>LIST_FOREACH(np,&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">head,&nbsp;list_entry)<br>np</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">&nbsp;<img src="http://www.cppblog.com/Images/dot.gif"><br>&nbsp;<br></span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">&nbsp;(head.lh_first&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;NULL)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">&nbsp;Delete.&nbsp;</span><span style="COLOR: #008000">*/</span><span style="COLOR: #000000"><br>LIST_REMOVE(head.lh_first,&nbsp;list_entry);</span></div>
<img src ="http://www.cppblog.com/flyonok/aggbug/126370.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyonok/" target="_blank">flyonok</a> 2010-09-11 00:23 <a href="http://www.cppblog.com/flyonok/archive/2010/09/11/126370.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>信号量(semaphore) 入门--from csdn</title><link>http://www.cppblog.com/flyonok/archive/2010/09/09/126255.html</link><dc:creator>flyonok</dc:creator><author>flyonok</author><pubDate>Thu, 09 Sep 2010 10:15:00 GMT</pubDate><guid>http://www.cppblog.com/flyonok/archive/2010/09/09/126255.html</guid><wfw:comment>http://www.cppblog.com/flyonok/comments/126255.html</wfw:comment><comments>http://www.cppblog.com/flyonok/archive/2010/09/09/126255.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyonok/comments/commentRss/126255.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyonok/services/trackbacks/126255.html</trackback:ping><description><![CDATA[<p>国内的计算机类教材太垃圾了，大多数都是把国外的帮助文档拿来翻译一下就拿去卖钱了，可谓适应知识经济的发展，呵呵。计算机类的书籍不像文学类的书籍，只要识字就能看懂，所以这些教材编得不好，也没有多少人能看得出来( 背后N 个人在@!%@#%&amp;* ）。对于很多计算机知识，入门最好的方法还是从简 单的开始理解，然后那些复杂的东西就会迎刃而解。 </p>
<p>&nbsp; </p>
<p>-------------------------------------------------------------------------------- </p>
<p>&nbsp;&nbsp;&nbsp; 今天我来说说Linux/Unix 下信号量使用的入门吧。信号量是什么？就是设置在内核当中用户解决资源冲突东东。举个简单的例子，一张凳子一个人已经坐了，第二个人就不能坐，但如果第二个人不知道这张凳子已经给人坐了，还坐上去，就会出现问题，所以如果我们约定凳子被占了就登记到一个本子上，每个人想坐 这张凳子之前都先看看这个本子有没写下东西，就不会出现上述情况了。我说的这些，只要上过操作系统的同学都知道（除非经常逃课，期末考试碰巧又混过去了:P ），但是在实际编程当中，新手根本不知道Linux/Unix 的信号量怎么使用。信号量从哪里来，怎么用呢？查那些教材又让人一头雾水，FT ！ </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 所以我用自己实验的例子来说说，Linux/Unix 下怎么使用信号量。 </p>
<p>要使用信号量当然就要创建啦，怎么弄？ </p>
<p>用semid=semget(KEY,3,0777 | IPC_CREAT);<br>其中KEY 就是给信号量的键，系统会根据信号量的键分配一 个信号量ID ，一个键一个信号量ID ，所以如果你想不同程序都使用同一个信号量的话，只要这个KEY 的值相等就行了。第二个是信号量元素的数量，其实我们 创建的是信号量集，里面有包含着元素，我的例子当中是3 个元素，0777 是信号量的权限，这是一个8 进制数字，为什么使用它？因为权限刚好分为写、读、执 行三种，用1 、2 、4 代表刚好，方便快捷。0777 就是，根用户、用户组、一般用户都有读、写、执行的权力，IPC_CREAT 是FLAG ，表示创建这个 信号量，当然，如果KEY 对应的信号量已经创建，则会返回已创建信号量的ID. 其他的FLAG 可以参考man semget. （不要告诉我你不知道man semget 是什么哦，FT ！就是Linux 下的帮助文档啊，man 就是manual 的简写，记住哦。）。 </p>
<p>好了，创建好信号量( 我们用semid ，一个整型变量保存信号量ID) 后又怎么样呢？哦！还没有给这三个信号量元素赋初值！那要怎么做？ </p>
<p>用semctl(semid,0,SETALL,semun_init) </p>
<p>semid 不用说了吧，第二个参数是从第几个元素开始赋值，这里是0 ，即从第一个元素开始，SETALL 是FLAG ，这里的意思是：对所有的元素赋 值，最后一个参数是union semun 类型，里面包含每个元素应赋的值，要使用union semun 类型，记得在你的程序里面要加上： </p>
<p>&nbsp;#if defined(__GNU_LIBRARY__) &amp;&amp; !defined(_SEM_SEMUN_UNDEFINED)<br>&nbsp;/* union semun is defined by including */<br>&nbsp;#else<br>&nbsp;/* according to X/OPEN we have to define it ourselves */<br>&nbsp;union semun {<br>&nbsp; int val;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* value for SETVAL */<br>&nbsp; struct semid_ds *buf;&nbsp;&nbsp;&nbsp;&nbsp; /* buffer for IPC_STAT, IPC_SET */<br>&nbsp; unsigned short *array;&nbsp;&nbsp;&nbsp; /* array for GETALL, SETALL */<br>&nbsp;&nbsp;&nbsp;&nbsp; /* Linux specific part: */<br>&nbsp; struct seminfo *__buf;&nbsp;&nbsp;&nbsp; /* buffer for IPC_INFO */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #endif </p>
<p>注释上说了，根据X/OPEN ，即有些系统下我们要自己定义union semun 。 </p>
<p>有了的定义之后，我们就可以定义变量semun_init </p>
<p>union semun semun_init; </p>
<p>因为我们的信号量有3 个元素，所以我们会使用semun_init 里面的unsigned short *array 。如果只有一个元素，就使用int val 。 </p>
<p>再定义一个变量数组 </p>
<p>unsigned short val[3]={1,1,1};//3 个元素的值均为1 </p>
<p>然后： </p>
<p>semun_init.array = val; </p>
<p>好了，准备好后就可以调用刚才的semctl(semid,0,SETALL,semun_init) ，信号量初始化完毕。 </p>
<p>将程序拼在一起: </p>
<p>int semid;<br>semid=semget(KEY,3,0777 | IPC_CREAT);<br>union semun semun_init;<br>unsigned short val[3]={1,1,1};<br>semun_init.array = val;<br>semctl(semid,0,SETALL,semun_init);<br>semctl(semid,0,IPC_RMID);// 最后不要忘了删除信号量哦。 </p>
<p>还有一些零碎的东西，如返回值的处理啊等等，有了上面的基础，大家可以参看信号量的文档就很容易理解了。按我以上的例子，我简单举例说明一下： </p>
<p>int a = semctl(semid,2,GETVAL); 获取第三个元素的值到变量a 中，元素需要从0 开始，刚好2 就是第三个元素。 </p>
<p>struct sembuf op_down={0,-1,IPC_NOWAIT};// 设置信号量操作的结构体变量<br>semop(semid,&amp;op_down,1);// 注意！第二个参数是指针，第三个参数表示该指针指向多少个这种结构体。用这种方法我们可以一次性对几个元素进行操作。<br>就是将第一个元素进行-1 操作，IPC_NIWAIT 明显是FLAG 啦，表示如果操作不成功程序不等待，而直接返回。 </p>
<p>怎样简单否？ </p>
<p>国内和国外的学术最大的不同就是，国外把很难的东西变得很简单，国内则把很简单的东西变得很难，以显示作者的高深。呵呵，好在，我这篇东西与学术是一个地一个天，没法比！^_^ </p>
<p><a href="http://blog.csdn.net/sparkliang/archive/2009/12/23/5061957.aspx"></a>&nbsp;</p>
<img src ="http://www.cppblog.com/flyonok/aggbug/126255.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyonok/" target="_blank">flyonok</a> 2010-09-09 18:15 <a href="http://www.cppblog.com/flyonok/archive/2010/09/09/126255.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux程序设计——用getopt处理命令行参数</title><link>http://www.cppblog.com/flyonok/archive/2010/09/04/125884.html</link><dc:creator>flyonok</dc:creator><author>flyonok</author><pubDate>Sat, 04 Sep 2010 09:58:00 GMT</pubDate><guid>http://www.cppblog.com/flyonok/archive/2010/09/04/125884.html</guid><wfw:comment>http://www.cppblog.com/flyonok/comments/125884.html</wfw:comment><comments>http://www.cppblog.com/flyonok/archive/2010/09/04/125884.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyonok/comments/commentRss/125884.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyonok/services/trackbacks/125884.html</trackback:ping><description><![CDATA[<meta http-equiv="content-type" content="text/html; charset="utf-8""><span class="Apple-style-span" style="border-collapse: separate; color: #000000; font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;"><span class="Apple-style-span" style="border-collapse: collapse; font-family: song,Verdana; font-size: 12px;">Linux下很多程序甚至那些具有图形用户界面（graphical user interface，GUI）的程序，都能接受和处理命令行选项。对于某些程序，这是与用户进行交互的主要手段。具有可靠的复杂命令行参数处理机制，会使得您的应用程序更好、更有用。<code><font face="新宋体">getopt()</font></code>是一个专门设计来减轻命令行处理负担的库函数。
<h2 style="font-family: 宋体;"><font size="4">1、命令行参数</font></h2>
<div style="font-family: 宋体;">命令行程序设计的首要任务是解析命令行参数，GUI派的程序员很少关心这个。这里，对参数采用了一种比较通俗的定义：命令行上除命令名之外的字符串。参数由多项构成，项与项之间用空白符彼此隔开。</div>
<div style="font-family: 宋体;">参数进一步分为<font color="#0000ff">选项</font>和<font color="#0000ff">操作数</font>。选项用于修改程序的默认行为或为程序提供信息，比较老的约定是以短划线开头。选项后可以跟随一些参数，称为选项参数。剩下的就是操作数了。</div>
<h2 style="font-family: 宋体;"><font size="4">2、POSIX约定</font></h2>
<table style="border: 1px solid #999999; font-size: 12px; width: 494px; font-family: 宋体;" align="center">
    <tbody>
        <tr style="font: 12px song,Verdana;">
            <td style="font: 12px song,Verdana; background-color: #c7c7c7;">POSIX表示可移植操作系统接口： Portable Operating System Interface，电气和电子工程师协会（Institute of Electrical and Electronics Engineers，IEEE）最初开发 POSIX 标准，是为了提高 UNIX 环境下应用程序的可移植性。然而，POSIX 并不局限于 UNIX。许多其它的操作系统，例如 DEC OpenVMS 和 Microsoft Windows NT，都支持 POSIX 标准。<br style="font: 12px song,Verdana;"></td>
        </tr>
    </tbody>
</table>
<p style="font: 12px 宋体;">下面是POSIX标准中关于程序名、参数的约定：</p>
<ul style="font-family: 宋体;">
    <li>程序名不宜少于2个字符且不多于9个字符；</li>
    <li>程序名应只包含小写字母和阿拉伯数字；</li>
    <li>选项名应该是单字符活单数字，且以短横&#8216;-&#8216;为前綴；</li>
    <li>多个不需要选项参数的选项，可以合并。（譬如：foo -a -b -c ----&gt;foo -abc）</li>
    <li>选项与其参数之间用空白符隔开；</li>
    <li>选项参数不可选。</li>
    <li>若选项参数有多值，要将其并为一个字串传进来。譬如：myprog -u "arnold,joe,jane"。这种情况下，需要自己解决这些参数的分离问题。</li>
    <li>选项应该在操作数出现之前出现。</li>
    <li>特殊参数&#8216;--'指明所有参数都结束了，其后任何参数都认为是操作数。</li>
    <li>选项如何排列没有什么关系，但对互相排斥的选项，如果一个选项的操作结果覆盖其他选项的操作结果时，最后一个选项起作用；如果选项重复，则顺序处理。</li>
    <li>允许操作数的顺序影响程序行为，但需要作文档说明。</li>
    <li>读写指定文件的程序应该将单个参数'-'作为有意义的标准输入或输出来对待。</li>
</ul>
<h2 style="font-family: 宋体;"><font size="4">3、GNU长选项</font></h2>
<span style="font-family: 宋体;">GNU鼓励程序员使用--help、--verbose等形式的长选项。这些选项不仅不与POSIX约定冲突，而且容易记忆，另外也提供了在所有GNU工具之间保持一致性的机会。GNU长选项有自己的约定：</span><br style="font: 12px 宋体;">
<ul style="font-family: 宋体;">
    <li>对于已经遵循POSIX约定的GNU程序，每个短选项都有一个对应的长选项。</li>
    <li>额外针对GNU的长选项不需要对应的短选项，仅仅推荐要有。</li>
    <li>长选项可以缩写成保持惟一性的最短的字串。</li>
    <li>选项参数与长选项之间或通过空白字符活通过一个'='来分隔。</li>
    <li>选项参数是可选的（只对短选项有效）。</li>
    <li>长选项允许以一个短横线为前缀。<br style="font: 12px song,Verdana;"></li>
</ul>
<h2 style="font-family: 宋体;"><font size="4">4、基本的命令行处理技术</font></h2>
<p style="font: 12px 宋体;">C程序通过argc和argv参数访问它的命令行参数。argc是整型数，表示参数的个数（包括命令名）。main()函数的定义方式有两种，区别仅在于argv如何定义：</p>
<table style="border: 1px solid #999999; font-size: 12px; width: 494px;" align="center">
    <tbody>
        <tr style="font: 12px song,Verdana;">
            <td style="font: 12px song,Verdana; vertical-align: top; background-color: #cccc66;">int main(int argc, char *argv[])<br style="font: 12px song,Verdana;">{<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &#8230;&#8230;<br style="font: 12px song,Verdana;">}</td>
            <td style="font: 12px song,Verdana; vertical-align: top; background-color: #9999cc;">int main(int argc, char **argv)<br style="font: 12px song,Verdana;">{<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &#8230;&#8230;<br style="font: 12px song,Verdana;">}</td>
        </tr>
    </tbody>
</table>
<br style="font: 12px song,Verdana;">
<p style="font: 12px 宋体;">当 C 运行时库的程序启动代码调用<span class="Apple-converted-space">&nbsp;</span><code><font face="新宋体">main()</font></code><span class="Apple-converted-space">&nbsp;</span>时，已经对命令行进行了处理。<code><font face="新宋体">argc</font></code><span class="Apple-converted-space">&nbsp;</span>参数包含参数的计数值，而<span class="Apple-converted-space">&nbsp;</span><code><font face="新宋体">argv</font></code><span class="Apple-converted-space">&nbsp;</span>包含指向这些参数的指针数组。argv[0]是程序名。</p>
<p style="font: 12px 宋体;">一个很简单的命令行处理技术的例子是echo程序，它可以将参数输出到标准设备上，用空格符隔开，最后换行。若命令行第一个参数为-n，那么就不会换行。</p>
<h3 style="font-family: 宋体;"><font size="3">清单1：</font><br style="font: 12px song,Verdana;"></h3>
<table style="border: 1px solid #999999; font-size: 12px; width: 494px; font-family: 宋体;" align="center">
    <tbody>
        <tr style="font: 12px song,Verdana;">
            <td style="font: 12px song,Verdana; background-color: #c7c7c7;">#include &lt;stdio.h&gt;<br style="font: 12px song,Verdana;"><br style="font: 12px song,Verdana;">int main(int argc, char **argv)<br style="font: 12px song,Verdana;">{<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; int i, nflg;<br style="font: 12px song,Verdana;"><br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; nflg = 0;<br style="font: 12px song,Verdana;"><span style="color: #ff0102;">&nbsp;&nbsp;&nbsp; if(argc &gt; 1 &amp;&amp; argv[1][0] == '-' &amp;&amp; argv[1][1] == 'n'){</span><br style="font: 12px song,Verdana; color: #ff0102;"><span style="color: #ff0102;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nflg++;</span><br style="font: 12px song,Verdana; color: #ff0102;"><span style="color: #ff0102;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; argc--;</span><br style="font: 12px song,Verdana; color: #ff0102;"><span style="color: #ff0102;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; argv++;</span><br style="font: 12px song,Verdana; color: #ff0102;"><span style="color: #ff0102;">&nbsp;&nbsp;&nbsp; }</span><br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; for(i=1; i&lt;argc; i++){<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fputs(argv[i], stdout);<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(i &lt; argc-1)<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; putchar(' ');<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; }<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; if(nflg == 0)<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; putchar('\n');<br style="font: 12px song,Verdana;"><br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; return 0;<br style="font: 12px song,Verdana;">}<br style="font: 12px song,Verdana;"></td>
        </tr>
    </tbody>
</table>
<p style="font: 12px 宋体;">echo程序中，对于命令行参数的解析是手动实现的。很久以前，Unix支持小组为了简化对于命令行参数的解析，开发了<font color="#0000ff"><strong>getopt()函数</strong></font>，同时提供了几个外部变量，使得编写遵守POSIX的代码变得更加容易了。</p>
<h2 style="font-family: 宋体;"><font size="4">5、命令行参数解析函数 —— getopt()</font></h2>
<p style="font: 12px 宋体;">getopt()函数声明如下：</p>
<table style="border: 1px solid #999999; font-size: 12px; width: 494px; font-family: 宋体;" align="center">
    <tbody>
        <tr style="font: 12px song,Verdana;">
            <td style="font: 12px song,Verdana; background-color: #c7c7c7;">#include &lt;unistd.h&gt;<br style="font: 12px song,Verdana;"><br style="font: 12px song,Verdana;">int getopt(int argc, char * const argv[], const char *optstring);<br style="font: 12px song,Verdana;"><br style="font: 12px song,Verdana;">extern char *optarg;<br style="font: 12px song,Verdana;">extern int optind, opterr, optopt;<br style="font: 12px song,Verdana;"></td>
        </tr>
    </tbody>
</table>
<p style="font: 12px 宋体;">该函数的argc和argv参数通常直接从main()的参数直接传递而来。optstring是选项字母组成的字串。如果该字串里的任一字符后面有冒号，那么这个选项就要求有选项参数。</p>
<p style="font: 12px 宋体;">当给定getopt()命令参数的数量 (<code><font face="新宋体">argc</font></code>)、指向这些参数的数组 (<code><font face="新宋体">argv</font></code>) 和选项字串 (<code><font face="新宋体">optstring</font></code>) 后，<code><font face="新宋体">getopt()</font></code><span class="Apple-converted-space">&nbsp;</span>将返回第一个选项，并设置一些全局变量。使用相同的参数再次调用该函数时，它将返回下一个选项，并设置相应的全局变量。如果不再有可识别的选项，将返回<span class="Apple-converted-space">&nbsp;</span><code><font face="新宋体">-1</font></code>，此任务就完成了。</p>
<p style="font: 12px 宋体;"><code><font face="新宋体">getopt()</font></code><span class="Apple-converted-space">&nbsp;</span>所设置的全局变量包括：</p>
<ul style="font-family: 宋体;">
    <li><code><font face="新宋体">char *optarg</font></code>——当前选项参数字串（如果有）。</li>
    <li><code><font face="新宋体">int optind</font></code>——argv的当前索引值。当getopt()在while循环中使用时，循环结束后，剩下的字串视为操作数，在argv[optind]至argv[argc-1]中可以找到。</li>
    <li>int opterr——这个变量非零时，getopt()函数为&#8220;无效选项&#8221;和&#8220;缺少参数选项，并输出其错误信息。<br style="font: 12px song,Verdana;"></li>
    <li><code><font face="新宋体">int optopt</font></code>——当发现无效选项字符之时，getopt()函数或返回'?'字符，或返回':'字符，并且optopt包含了所发现的无效选项字符。</li>
</ul>
<p style="font: 12px song,Verdana;">以下面的程序为例：<br style="font: 12px song,Verdana;">选项：</p>
<ul>
    <li>-n —— 显示&#8220;我的名字&#8221;。</li>
    <li>-g —— 显示&#8220;我女朋友的名字&#8221;。</li>
    <li>-l —— 带参数的选项.</li>
</ul>
<h3 style="font-family: 宋体;"><font size="3">清单2：</font></h3>
<table style="border: 1px solid #999999; font-size: 12px; width: 494px; font-family: 宋体;" align="center">
    <tbody>
        <tr style="font: 12px song,Verdana;">
            <td style="font: 12px song,Verdana; vertical-align: top; background-color: #c7c7c7;">#include &lt;stdio.h&gt;<br style="font: 12px song,Verdana;">#include &lt;unistd.h&gt;<br style="font: 12px song,Verdana;"><br style="font: 12px song,Verdana;">int main (int argc, char **argv)<br style="font: 12px song,Verdana;">{<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; int oc;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*选项字符 */<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; char *b_opt_arg;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*选项参数字串 */<br style="font: 12px song,Verdana;"><br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; while((oc = getopt(argc, argv, "ngl:")) != -1)<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; {<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; switch(oc)<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case 'n':<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf("My name is Lyong.\n");<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case 'g':<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf("Her name is Xxiong.\n");<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case 'l':<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; b_opt_arg = optarg;<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf("Our love is %s\n", optarg);<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; }<br style="font: 12px song,Verdana;">&nbsp;&nbsp; return 0;<br style="font: 12px song,Verdana;">}<br style="font: 12px song,Verdana;"></td>
        </tr>
    </tbody>
</table>
<p style="font: 12px 宋体;">运行结果：</p>
<table style="border: 1px solid #999999; font-size: 12px; width: 494px; font-family: 宋体;" align="center">
    <tbody>
        <tr style="font: 12px song,Verdana;">
            <td style="font: 12px song,Verdana; background-color: #c7c7c7;"><span style="color: #006666;">$ ./opt_parse_demo -n</span><br style="font: 12px song,Verdana;">My name is Lyong.<br style="font: 12px song,Verdana;"><span style="color: #006666;">$ ./opt_parse_demo -g</span><br style="font: 12px song,Verdana;">Her name is Xxiong.<br style="font: 12px song,Verdana;"><span style="color: #006666;">$ ./opt_parse_demo -l forever</span><br style="font: 12px song,Verdana;">Our love is forever<br style="font: 12px song,Verdana;"><span style="color: #006666;">$ ./opt_parse_demo -ngl forever</span><br style="font: 12px song,Verdana;">My name is Lyong.<br style="font: 12px song,Verdana;">Her name is Xxiong.<br style="font: 12px song,Verdana;">Our love is forever<br style="font: 12px song,Verdana;"></td>
        </tr>
    </tbody>
</table>
<h2 style="font-family: 宋体;"><font size="4">6、改变getopt()对错误命令行参数信息的输出行为</font></h2>
<p style="font: 12px 宋体;">不正确的调用程序在所难免，这种错误要么是命令行选项无效，要么是缺少选项参数。正常情况下，getopt()会为这两种情况输出自己的出错信息，并且返回'?'。为了验证此事，可以修改一下上面的清单2中的代码。</p>
<h3 style="font-family: 宋体;"><font size="3">清单3：<br style="font: 12px song,Verdana;"></font></h3>
<table style="border: 1px solid #999999; font-size: 12px; width: 494px; font-family: 宋体;" align="center">
    <tbody>
        <tr style="font: 12px song,Verdana;">
            <td style="font: 12px song,Verdana; background-color: #c7c7c7;">#include &lt;stdio.h&gt;<br style="font: 12px song,Verdana;">#include &lt;unistd.h&gt;<br style="font: 12px song,Verdana;"><br style="font: 12px song,Verdana;">int main (int argc, char **argv)<br style="font: 12px song,Verdana;">{<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; int oc;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*选项字符 */<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; char *b_opt_arg;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*选项参数字串 */<br style="font: 12px song,Verdana;"><br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; while((oc = getopt(argc, argv, "ngl:")) != -1)<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; {<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; switch(oc)<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case 'n':<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf("My name is Lyong.\n");<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case 'g':<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf("Her name is Xxiong.\n");<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case 'l':<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; b_opt_arg = optarg;<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf("Our love is %s\n", optarg);<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case '?':<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf("arguments error!\n");<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; }<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; return 0;<br style="font: 12px song,Verdana;">}<br style="font: 12px song,Verdana;"></td>
        </tr>
    </tbody>
</table>
<p style="font: 12px 宋体;">输入一个错误的命令行，结果如下：</p>
<table style="border: 1px solid #999999; font-size: 12px; width: 494px; font-family: 宋体;" align="center">
    <tbody>
        <tr style="font: 12px song,Verdana;">
            <td style="font: 12px song,Verdana; background-color: #c7c7c7;"><span style="color: #006666;">$ ./opt_parse_demo -l</span><br style="font: 12px song,Verdana;">./opt_parse_demo: option requires an argument -- l<br style="font: 12px song,Verdana;">arguments error!<br style="font: 12px song,Verdana;"></td>
        </tr>
    </tbody>
</table>
<p style="font: 12px 宋体;">如果不希望输出任何错误信息，或更希望输出自定义的错误信息。可以采用以下两种方法来更改getopt()函数的出错信息输出行为：<br style="font: 12px song,Verdana;"></p>
<ol style="font-family: 宋体;">
    <li>在调用getopt()之前，将opterr设置为0，这样就可以在getopt()函数发现错误的时候强制它不输出任何消息。</li>
    <li>如果optstring参数的第一个字符是冒号，那么getopt()函数就会保持沉默，并根据错误情况返回不同字符，如下：
    <ul>
        <li>&#8220;无效选项&#8221; —— getopt()返回'?'，并且optopt包含了无效选项字符（这是正常的行为）。</li>
        <li>&#8220;缺少选项参数&#8221; —— getopt()返回':'，如果optstring的第一个字符不是冒号，那么getopt()返回'?'，这会使得这种情况不能与无效选项的情况区分开。</li>
    </ul>
    </li>
</ol>
<span style="font-family: 宋体;"></span>
<h3 style="font-family: 宋体;"><font size="3">清单4：</font></h3>
<table style="border: 1px solid #999999; font-size: 12px; width: 494px; font-family: 宋体;" align="center">
    <tbody>
        <tr style="font: 12px song,Verdana;">
            <td style="font: 12px song,Verdana; background-color: #c7c7c7;">#include &lt;stdio.h&gt;<br style="font: 12px song,Verdana;">#include &lt;unistd.h&gt;<br style="font: 12px song,Verdana;"><br style="font: 12px song,Verdana;">int main (int argc, char **argv)<br style="font: 12px song,Verdana;">{<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;int oc;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*选项字符 */<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;char ec;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; /*无效的选项字符*/<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;char *b_opt_arg;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*选项参数字串 */<br style="font: 12px song,Verdana;"><br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;while((oc = getopt(argc, argv, ":ngl:")) != -1)<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;{<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;switch(oc)<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;{<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;case 'n':<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;printf("My name is Lyong.\n");<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;break;<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;case 'g':<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;printf("Her name is Xxiong.\n");<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;break;<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;case 'l':<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;b_opt_arg = optarg;<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;printf("Our love is %s\n", optarg);<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;break;<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;case '?':<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;ec = (char)optopt;<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;printf("无效的选项字符 \' %c \'!\n", ec);<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;break;<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;case ':':<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;printf("缺少选项参数！\n");<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;break;<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;}<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;return 0;<br style="font: 12px song,Verdana;">}</td>
        </tr>
    </tbody>
</table>
<p style="font: 12px 宋体;">测试结果：</p>
<table style="border: 1px solid #999999; font-size: 12px; width: 494px; font-family: 宋体;" align="center">
    <tbody>
        <tr style="font: 12px song,Verdana;">
            <td style="font: 12px song,Verdana; background-color: #c7c7c7;"><span style="color: #006666;">$ ./opt_parse_demo -a</span><br style="font: 12px song,Verdana;">无效的选项字符 ' a '!<br style="font: 12px song,Verdana;"><span style="color: #006666;">$ ./opt_parse_demo -l</span><br style="font: 12px song,Verdana;">缺少选项参数！</td>
        </tr>
    </tbody>
</table>
<h2 style="font-family: 宋体;"><font size="4">7、GNU提供的getopt()函数的特点</font></h2>
<p style="font: 12px 宋体;">上面所设计的getopt()函数是UNIX支持小组提供的，其执行时一碰到不以'-'开始的 命令行参数就停止寻找选项。而GNU提供的getopt()函数与之不同，它会扫描整个命令行来寻找选项。当调用GNU getopt()函数并处理命令行参数的时候，它重新排列argv中的元素，这样当重排结束时，所有选项都被移动到前面并且那些继续检查argv [optind]至argv[argc-1]中剩余参数的代码仍正常工作，但在任何情况下，碰到特殊参数'--'就结束对选项的扫描。</p>
<p style="font: 12px 宋体;">可以输入一个乱序的命令行，查看opt_parse_demo的输出：</p>
<table style="border: 1px solid #999999; font-size: 12px; width: 494px; font-family: 宋体;" align="center">
    <tbody>
        <tr style="font: 12px song,Verdana;">
            <td style="font: 12px song,Verdana; background-color: #c7c7c7;"><span style="color: #006666;">$ ./opt_parse_demo -l forever a b c d -g -n</span><br style="font: 12px song,Verdana;">Our love is forever<br style="font: 12px song,Verdana;">Her name is Xxiong.<br style="font: 12px song,Verdana;">My name is Lyong.<br style="font: 12px song,Verdana;"></td>
        </tr>
    </tbody>
</table>
<p style="font: 12px 宋体;">GNU getopt()第二个特点是可以在optstring中使用特殊的首字符改变getopt()的默认行为：</p>
<ul style="font-family: 宋体;">
    <li>optstring[0] = '+'，这样就与UNIX支持小组提供的getopt()很相近了。</li>
    <li>optstring[0] = '-'，会在optarg中得到命令行中的每个参数。</li>
    <li>以上两种情况下，':'可以作为第二个字符使用。</li>
</ul>
<span style="font-family: 宋体;">GNU getopt()第三个特点是optstring中的选项字符后面接两个冒号，就允许该选项有可选的选项参数。在选项参数不存在的情况下，GNU getopt()返回选项字符并将optarg设置为NULL。</span><br style="font: 12px 宋体;">
<h2 style="font-family: 宋体;"><font size="4">8、GNU长选项命令行解析</font></h2>
<p style="font: 12px 宋体;">20 世纪 90 年代，UNIX 应用程序开始支持长选项，即一对短横线、一个描述性选项名称，还可以包含一个使用等号连接到选项的参数。</p>
<p style="font: 12px 宋体;">GNU提供了getopt-long()和getopt-long-only()函数支持长选项的命令行解析，其中，后者的长选项字串是以一个短横线开始的，而非一对短横线。<br style="font: 12px song,Verdana;"></p>
<p style="font: 12px 宋体;"><code><font face="新宋体">getopt_long()</font></code><span class="Apple-converted-space">&nbsp;</span>是同时支持长选项和短选项的<span class="Apple-converted-space">&nbsp;</span><code><font face="新宋体">getopt()</font></code><span class="Apple-converted-space">&nbsp;</span>版本。下面是它们的声明：</p>
<table style="border: 1px solid #999999; font-size: 12px; width: 494px; font-family: 宋体;" align="center">
    <tbody>
        <tr style="font: 12px song,Verdana;">
            <td style="font: 12px song,Verdana; background-color: #c7c7c7;">#include &lt;getopt.h&gt;<br style="font: 12px song,Verdana;"><br style="font: 12px song,Verdana;">int getopt_long(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex);<br style="font: 12px song,Verdana;"><br style="font: 12px song,Verdana;">int getopt_long_only(int argc, char * const argv[],const char *optstring,const struct option *longopts, int *longindex);<br style="font: 12px song,Verdana;"><br style="font: 12px song,Verdana;"></td>
        </tr>
    </tbody>
</table>
<p style="font: 12px 宋体;"><code><font face="新宋体">getopt_long()的前三个参数与上 面的getopt()相同，第4个参数是指向option结构的数组，option结构被称为&#8220;长选项表&#8221;。longindex参数如果没有设置为 NULL，那么它就指向一个变量，这个变量会被赋值为寻找到的长选项在longopts中的索引值，这可以用于错误诊断。</font></code></p>
<p style="font: 12px 宋体;"><code><font face="新宋体">option结构在getopt.h中的声明如下：</font></code></p>
<table style="border: 1px solid #999999; font-size: 12px; width: 494px; font-family: 宋体;" align="center">
    <tbody>
        <tr style="font: 12px song,Verdana;">
            <td style="font: 12px song,Verdana; background-color: #c7c7c7;">struct option{<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; const char *name;<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; int has_arg;<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; int *flag;<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; int val;<br style="font: 12px song,Verdana;">};<br style="font: 12px song,Verdana;"></td>
        </tr>
    </tbody>
</table>
<p style="font: 12px 宋体;">对结构中的各元素解释如下：</p>
<h3 style="margin-left: 40px; font-family: 宋体;"><font size="3">const char *name</font></h3>
<div style="margin-left: 40px; font-family: 宋体;">这是选项名，前面没有短横线。譬如"help"、"verbose"之类。<br style="font: 12px song,Verdana;"></div>
<h3 style="margin-left: 40px; font-family: 宋体;"><font size="3">int has_arg</font></h3>
<div style="margin-left: 40px; font-family: 宋体;">描述了选项是否有选项参数。如果有，是哪种类型的参数，此时，它的值一定是下表中的一个。<br style="font: 12px song,Verdana;"></div>
<div style="margin-left: 40px; font-family: 宋体;">
<table style="width: 334px; height: 121px;" border="1" cellpadding="1" cellspacing="1">
    <tbody>
        <tr style="font: 12px song,Verdana;">
            <td style="font: 12px song,Verdana; background-color: #c7c7c7; text-align: center;">符号常量&nbsp;</td>
            <td style="font: 12px song,Verdana; background-color: #c7c7c7; text-align: center;">数值&nbsp;</td>
            <td style="font: 12px song,Verdana; background-color: #c7c7c7; text-align: center;">含义&nbsp;</td>
        </tr>
        <tr style="font: 12px song,Verdana;">
            <td style="font: 12px song,Verdana; background-color: #c7c7c7; text-align: center;">no_argument&nbsp;</td>
            <td style="font: 12px song,Verdana; background-color: #c7c7c7; text-align: center;">0</td>
            <td style="font: 12px song,Verdana; background-color: #c7c7c7; text-align: center;">选项没有参数&nbsp;</td>
        </tr>
        <tr style="font: 12px song,Verdana;">
            <td style="font: 12px song,Verdana; background-color: #c7c7c7; text-align: center;">required_argument</td>
            <td style="font: 12px song,Verdana; background-color: #c7c7c7; text-align: center;">1</td>
            <td style="font: 12px song,Verdana; background-color: #c7c7c7; text-align: center;">选项需要参数<span class="Apple-converted-space">&nbsp;</span><br style="font: 12px song,Verdana;"></td>
        </tr>
        <tr style="font: 12px song,Verdana;">
            <td style="font: 12px song,Verdana; background-color: #c7c7c7; text-align: center;">optional_argument</td>
            <td style="font: 12px song,Verdana; background-color: #c7c7c7; text-align: center;">2</td>
            <td style="font: 12px song,Verdana; background-color: #c7c7c7; text-align: center;">选项参数可选&nbsp;</td>
        </tr>
    </tbody>
</table>
</div>
<h3 style="margin-left: 40px; font-family: 宋体;"><font size="3">int *flag</font></h3>
<div style="margin-left: 40px; font-family: 宋体;">如果这个指针为NULL，那么 getopt_long()返回该结构val字段中的数值。如果该指针不为NULL，getopt_long()会使得它所指向的变量中填入val字段中 的数值，并且getopt_long()返回0。如果flag不是NULL，但未发现长选项，那么它所指向的变量的数值不变。<br style="font: 12px song,Verdana;"></div>
<h3 style="margin-left: 40px; font-family: 宋体;"><font size="3">int val</font></h3>
<div style="margin-left: 40px; font-family: 宋体;">这个值是发现了长选项时的返回值，或者flag不 是NULL时载入*flag中的值。典型情况下，若flag不是NULL，那么val是个真／假值，譬如1或0；另一方面，如果flag是NULL，那么 val通常是字符常量，若长选项与短选项一致，那么该字符常量应该与optstring中出现的这个选项的参数相同。<br style="font: 12px song,Verdana;"></div>
<p style="font: 12px 宋体;">每个长选项在长选项表中都有一个单独条目，该条目里需要填入正确的数值。数组中最后的元素的值应该全是0。数组不需要排序，getopt_long()会进行线性搜索。但是，根据长名字来排序会使程序员读起来更容易。</p>
<p style="font: 12px 宋体;">以上所说的flag和val的用法看上去有点混乱，但它们很有实用价值，因此有必要搞透彻了。</p>
<p style="font: 12px 宋体;">大部分时候，程序员会根据getopt_long()发现的选项，在选项处理过程中要设置一些标记变量，譬如在使用getopt()时，经常做出如下的程序格式：</p>
<table style="border: 1px solid #999999; font-size: 12px; width: 494px;" align="center">
    <tbody>
        <tr style="font: 12px song,Verdana;">
            <td style="font: 12px song,Verdana; background-color: #c7c7c7;">int do_name, do_gf_name, do_love; /*标记变量*/<br style="font: 12px song,Verdana;">char *b_opt_arg;<br style="font: 12px song,Verdana;"><br style="font: 12px song,Verdana;">while((c = getopt(argc, argv, ":ngl:")) != -1)<br style="font: 12px song,Verdana;">{<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; switch (c){<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; case 'n':<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; do_name = 1;<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; case 'g':<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; do_gf_name = 1;<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; case 'l':<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b_opt_arg = optarg;<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; &#8230;&#8230;<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; }<br style="font: 12px song,Verdana;">}<br style="font: 12px song,Verdana;"></td>
        </tr>
    </tbody>
</table>
<p style="font: 12px song,Verdana;">当flag不为NULL时，getopt_long*()会为你设置标记变量。也就是说上面的代码中，关于选项'n'、'l'的处理，只是设置一些 标记，如果flag不为NULL,时，getopt_long()可以自动为各选项所对应的标记变量设置标记，这样就能够将上面的switch语句中的两 种种情况减少到了一种。下面给出一个长选项表以及相应处理代码的例子。</p>
<h3><font size="3">清单5：</font></h3>
<br style="font: 12px song,Verdana;">
<table style="border: 1px solid #999999; font-size: 12px; width: 494px;" align="center">
    <tbody>
        <tr style="font: 12px song,Verdana;">
            <td style="font: 12px song,Verdana; background-color: #c7c7c7;">#include &lt;stdio.h&gt;<br style="font: 12px song,Verdana;">#include &lt;getopt.h&gt;<br style="font: 12px song,Verdana;"><br style="font: 12px song,Verdana;">int do_name, do_gf_name;<br style="font: 12px song,Verdana;">char *l_opt_arg;<br style="font: 12px song,Verdana;"><br style="font: 12px song,Verdana;">struct option longopts[] = {<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; { "name",&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; no_argument,&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &amp;do_name,&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp; },<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; { "gf_name",&nbsp;&nbsp;&nbsp; no_argument,&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &amp;do_gf_name,&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp; },<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; { "love",&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; required_argument,&nbsp;&nbsp;&nbsp; NULL,&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 'l'&nbsp;&nbsp;&nbsp; },<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; { &nbsp;&nbsp;&nbsp; 0,&nbsp;&nbsp;&nbsp; 0,&nbsp;&nbsp;&nbsp; 0,&nbsp;&nbsp;&nbsp; 0},<br style="font: 12px song,Verdana;">};<br style="font: 12px song,Verdana;"><br style="font: 12px song,Verdana;">int main(int argc, char *argv[])<br style="font: 12px song,Verdana;">{<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; int c;<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp;<span class="Apple-converted-space">&nbsp;</span><br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; while((c = getopt_long(argc, argv, ":l:", longopts, NULL)) != -1){<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; switch (c){<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case 'l':<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; l_opt_arg = optarg;<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf("Our love is %s!\n", l_opt_arg);<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case 0:<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf("getopt_long()设置变量 : do_name = %d\n", do_name);<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf("getopt_long()设置变量 : do_gf_name = %d\n", do_gf_name);<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; }<br style="font: 12px song,Verdana;">&nbsp;&nbsp;&nbsp; return 0;<br style="font: 12px song,Verdana;">}<br style="font: 12px song,Verdana;"></td>
        </tr>
    </tbody>
</table>
<p style="font: 12px song,Verdana;">在进行测试之前，再来回顾一下有关option结构中的指针flag的说明吧。</p>
<table style="border: 1px solid #999999; font-size: 12px; width: 494px;" align="center">
    <tbody>
        <tr style="font: 12px song,Verdana;">
            <td style="font: 12px song,Verdana; background-color: #c7c7c7;">如果这个指针为NULL，那么 getopt_long()返回该结构val字段中的数值。如果该指针不为NULL，getopt_long()会使得它所指向的变量中填入val字段中 的数值，并且getopt_long()返回0。如果flag不是NULL，但未发现长选项，那么它所指向的变量的数值不变。</td>
        </tr>
    </tbody>
</table>
<p style="font: 12px song,Verdana;">下面测试一下：</p>
<table style="border: 1px solid #999999; font-size: 12px; width: 494px;" align="center">
    <tbody>
        <tr style="font: 12px song,Verdana;">
            <td style="font: 12px song,Verdana; background-color: #c7c7c7;"><span style="color: #006666;">$ ./long_opt_demo --name</span><br style="font: 12px song,Verdana;">getopt_long()设置变量 : do_name = 1<br style="font: 12px song,Verdana;">getopt_long()设置变量 : do_gf_name = 0<br style="font: 12px song,Verdana;"><br style="font: 12px song,Verdana;"><span style="color: #006666;">$ ./long_opt_demo --gf_name</span><br style="font: 12px song,Verdana;">getopt_long()设置变量 : do_name = 0<br style="font: 12px song,Verdana;">getopt_long()设置变量 : do_gf_name = 1<br style="font: 12px song,Verdana;"><br style="font: 12px song,Verdana;"><span style="color: #006666;">$ ./long_opt_demo --love forever</span><br style="font: 12px song,Verdana;">Our love is forever!<br style="font: 12px song,Verdana;"><br style="font: 12px song,Verdana;"><span style="color: #006666;">$ ./long_opt_demo -l forever</span><br style="font: 12px song,Verdana;">Our love is forever!<br style="font: 12px song,Verdana;"><br style="font: 12px song,Verdana;"></td>
        </tr>
    </tbody>
</table>
<p style="font: 12px song,Verdana;">测试过后，应该有所感触了。关于flag和val的讨论到此为止。下面总结一下get_long()的各种返回值的含义：</p>
<table style="border: 1px solid #999999; font-size: 12px; width: 494px;" align="center">
    <tbody>
        <tr style="font: 12px song,Verdana;">
            <td style="font: 12px song,Verdana; text-align: left;">返回值&nbsp;&nbsp;&nbsp;<span class="Apple-converted-space">&nbsp;</span><br style="font: 12px song,Verdana;"></td>
            <td style="font: 12px song,Verdana; vertical-align: top; text-align: left;">含 义<br style="font: 12px song,Verdana;"></td>
        </tr>
        <tr style="font: 12px song,Verdana;">
            <td style="font: 12px song,Verdana; vertical-align: top; text-align: left;">0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="Apple-converted-space">&nbsp;</span><br style="font: 12px song,Verdana;"></td>
            <td style="font: 12px song,Verdana; vertical-align: top;">getopt_long()设置一个标志，它的值与option结构中的val字段的值一样<br style="font: 12px song,Verdana;"></td>
        </tr>
        <tr style="font: 12px song,Verdana;">
            <td style="font: 12px song,Verdana; vertical-align: top;">1<br style="font: 12px song,Verdana;"></td>
            <td style="font: 12px song,Verdana; vertical-align: top;">每碰到一个命令行参数，optarg都会记录它<br style="font: 12px song,Verdana;"></td>
        </tr>
        <tr style="font: 12px song,Verdana;">
            <td style="font: 12px song,Verdana; vertical-align: top;">'?'<br style="font: 12px song,Verdana;"></td>
            <td style="font: 12px song,Verdana; vertical-align: top;">无效选项<br style="font: 12px song,Verdana;"></td>
        </tr>
        <tr style="font: 12px song,Verdana;">
            <td style="font: 12px song,Verdana; vertical-align: top;">':'<br style="font: 12px song,Verdana;"></td>
            <td style="font: 12px song,Verdana; vertical-align: top;">缺少选项参数<br style="font: 12px song,Verdana;"></td>
        </tr>
        <tr style="font: 12px song,Verdana;">
            <td style="font: 12px song,Verdana; vertical-align: top;">'x'<br style="font: 12px song,Verdana;"></td>
            <td style="font: 12px song,Verdana; vertical-align: top;">选项字符'x'<br style="font: 12px song,Verdana;"></td>
        </tr>
        <tr style="font: 12px song,Verdana;">
            <td style="font: 12px song,Verdana; vertical-align: top;">-1<br style="font: 12px song,Verdana;"></td>
            <td style="font: 12px song,Verdana; vertical-align: top;">选项解析结束<br style="font: 12px song,Verdana;"></td>
        </tr>
    </tbody>
</table>
<p style="font: 12px song,Verdana;">从实用的角度来说，我们更期望每个长选项都对应一个短选项，这种情况下，在option结构中，只要将flag设置为NULL，并将val设置为长选项所对应的短选项字符即可。譬如上面清单5中的程序，修改如下。</p>
<h3><font size="3">清单6：</font></h3>
<table style="border: 1px solid #999999; font-size: 12px; width: 494px;" align="center">
    <tbody>
        <tr style="font: 12px song,Verdana;">
            <td style="font: 12px song,Verdana; background-color: #c7c7c7;">#include &lt;stdio.h&gt;<br style="font: 12px song,Verdana;">#include &lt;getopt.h&gt;<br style="font: 12px song,Verdana;"><br style="font: 12px song,Verdana;">int do_name, do_gf_name;<br style="font: 12px song,Verdana;">char *l_opt_arg;<br style="font: 12px song,Verdana;"><br style="font: 12px song,Verdana;">struct option longopts[] = {<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;{ "name",&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;no_argument,&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;NULL,&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;'n'&nbsp;&nbsp; &nbsp;},<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;{ "gf_name",&nbsp;&nbsp; &nbsp;no_argument,&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;NULL,&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;'g'&nbsp;&nbsp; &nbsp;},<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;{ "love",&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;required_argument,&nbsp;&nbsp; &nbsp;NULL,&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;'l'&nbsp;&nbsp; &nbsp;},<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;{ &nbsp;&nbsp; &nbsp;0,&nbsp;&nbsp; &nbsp;0,&nbsp;&nbsp; &nbsp;0,&nbsp;&nbsp; &nbsp;0},<br style="font: 12px song,Verdana;">};<br style="font: 12px song,Verdana;"><br style="font: 12px song,Verdana;">int main(int argc, char *argv[])<br style="font: 12px song,Verdana;">{<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;int c;<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;while((c = getopt_long(argc, argv, ":l:", longopts, NULL)) != -1){<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;switch (c){<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;case 'n':<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;printf("My name is LYR.\n");<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;break;<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;case 'g':<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;printf("Her name is BX.\n");<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;break;<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;case 'l':<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;l_opt_arg = optarg;<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;printf("Our love is %s!\n", l_opt_arg);<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;break;<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;}<br style="font: 12px song,Verdana;">&nbsp;&nbsp; &nbsp;return 0;<br style="font: 12px song,Verdana;">}</td>
        </tr>
    </tbody>
</table>
<p style="font: 12px song,Verdana;">测试结果如下：<br style="font: 12px song,Verdana;"></p>
<table style="border: 1px solid #999999; font-size: 12px; width: 494px;" align="center">
    <tbody>
        <tr style="font: 12px song,Verdana;">
            <td style="font: 12px song,Verdana; background-color: #c7c7c7;"><span style="color: #006666;">$ ./long_opt_demo --name --gf_name --love</span><span class="Apple-converted-space">&nbsp;</span>forever<br style="font: 12px song,Verdana;">My name is LYR.<br style="font: 12px song,Verdana;">Her name is BX.<br style="font: 12px song,Verdana;">Our love is forever!<br style="font: 12px song,Verdana;"><br style="font: 12px song,Verdana;"><span style="color: #006666;">$ ./long_opt_demo -ng -l forever</span><br style="font: 12px song,Verdana;">My name is LYR.<br style="font: 12px song,Verdana;">Her name is BX.<br style="font: 12px song,Verdana;">Our love is forever!<br style="font: 12px song,Verdana;"></td>
        </tr>
    </tbody>
</table>
<h2><font size="4">9、在LINUX之外的系统平台上使用GNU getopt()或getopt_long()</font></h2>
只 要从GNU程序或GNU C Library(GLIBC)的CVS档案文件中copy源文件即可（http://sourceware.org/glibc/）。所需源文件是 getopt.h、getopt.c和getoptl.c，将这些文件包含在你的项目中。另外，你的项目中最好也将COPYING.LIB文件包含进去， 因为<font size="-1">GNU LGPL（GNU 程序库公共许可证）的内容全部包括在命名为<font color="#cc0033">COPYING.LIB</font><span class="Apple-converted-space">&nbsp;</span>的文件中。</font>
<p style="font: 12px song,Verdana;"><font size="3"><strong>10、结论</strong></font></p>
程序需要能够快速处理各个选项和参数，且要求 不会浪费开发人员的太多时间。在这一点上，无论是GUI(图形用户交互）程序还是CUI（命令行交互）程序，都是其首要任务，其区别仅在于实现方式的不 同。GUI通过菜单、对话框之类的图形控件来完成交互，而CUI使用了纯文本的交互方式。在程序开发中，许多测试程序用CUI来完成是首选方案。<br style="font: 12px song,Verdana;">
<p style="font: 12px song,Verdana;"><code><font face="新宋体">getopt()</font></code><span class="Apple-converted-space">&nbsp;</span>函数是一个标准库调用，可允许您使用直接的 while/switch 语句方便地逐个处理命令行参数和检测选项（带或不带附加的参数）。与其类似的<span class="Apple-converted-space">&nbsp;</span><code><font face="新宋体">getopt_long()</font></code><span class="Apple-converted-space">&nbsp;</span>允许在几乎不进行额外工作的情况下处理更具描述性的长选项，这非常受开发人员的欢迎。</p>
</span></span><img src ="http://www.cppblog.com/flyonok/aggbug/125884.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyonok/" target="_blank">flyonok</a> 2010-09-04 17:58 <a href="http://www.cppblog.com/flyonok/archive/2010/09/04/125884.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>linux signal --1(from chinaunix.net)</title><link>http://www.cppblog.com/flyonok/archive/2010/08/31/125369.html</link><dc:creator>flyonok</dc:creator><author>flyonok</author><pubDate>Tue, 31 Aug 2010 02:58:00 GMT</pubDate><guid>http://www.cppblog.com/flyonok/archive/2010/08/31/125369.html</guid><wfw:comment>http://www.cppblog.com/flyonok/comments/125369.html</wfw:comment><comments>http://www.cppblog.com/flyonok/archive/2010/08/31/125369.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyonok/comments/commentRss/125369.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyonok/services/trackbacks/125369.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: linux signal description&nbsp;&nbsp;<a href='http://www.cppblog.com/flyonok/archive/2010/08/31/125369.html'>阅读全文</a><img src ="http://www.cppblog.com/flyonok/aggbug/125369.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyonok/" target="_blank">flyonok</a> 2010-08-31 10:58 <a href="http://www.cppblog.com/flyonok/archive/2010/08/31/125369.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>