<?xml version="1.0" encoding="gb2312"?>
<rss version="2.0">
<channel>
<title><![CDATA[冷枫叶]]></title>
        <image>
        <title>http://hi.baidu.com</title>
        <link>http://hi.baidu.com</link>
        <url>http://img.baidu.com/img/logo-hi.gif</url>
        </image>
<description><![CDATA[-- Linux Kernel Research, and Enjoy Life]]></description>
<link>http://hi.baidu.com/rwen2012</link>
<language>zh-cn</language>
<generator>www.baidu.com</generator>
<ttl>5</ttl>


<item>
        <title><![CDATA[io模拟i2c程序(zt)]]></title>
        <link><![CDATA[http://hi.baidu.com/rwen2012/blog/item/1da3bfdcab2c30abcd1166b1.html]]></link>
        <description><![CDATA[
		
		<div class="cnt">
<p>本程序是在周立功网上的程序的基础上修改的，原例里的ACK时序有点问题</p>
<p>/*******************************************************************************************************************<br>
此程序是I2C操作平台（主方式的软件平台）的底层的C子程序,如发送数据<br>
及接收数据,应答位发送,并提供了几个直接面对器件的操作函数，它很方便的与用<br>
户程序连接并扩展。<br>
注意:函数是采用软件延时的方法产生SCL脉冲,对高晶振频率要作一定的修改<br>
(本例是3us机器周期,如果系统对时间要求不是很重要的话,最好在每个单元读写结束时加个延时，<br>
测试有子地址器件函数，未测试无地址的器件，适合器件地址和子地址小于256的器件， <br>
大于256的单元的器件可以自己改写)。<br>
*********************************************************************************************************************/<br>
#include &lt;reg52.h&gt;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  /*头文件的包含*/<br>
#include &lt;intrins.h&gt;<br>
#define uchar unsigned char /*宏定义*/<br>
#define uint unsigned int</p>
<p>/*端口位定义*/<br>
sbit BELL_OUT=P3^5;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  <br>
sbit SCL=&quot;P1&quot;^3;/*模拟I2C数据传送位*/<br>
sbit SDA=&quot;P1&quot;^4;/*模拟I2C时钟控制位*/&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  <br>
<br>
bit ack;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  /*应答标志位*/</p>
<p>/**************************************************************************************************************************<br>
起动总线函数&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  <br>
函数原型: void Start_I2c(); <br>
功能:启动I2C总线,即发送I2C起始条件 <br>
**************************************************************************************************************************/<br>
void Start_I2c()<br>
{<br>
SDA=&quot;1&quot;;&#160;&#160;  /*发送起始条件的数据信号*/<br>
_nop_();<br>
SCL=&quot;1&quot;;&#160;&#160;  /*起始条件建立时间大于4.7us,延时*/ <br>
_nop_();&#160;&#160;&#160;&#160;  <br>
SDA=&quot;0&quot;;&#160;&#160;  /*发送起始信号*/<br>
_nop_(); /* 起始条件锁定时间大于4μs*/&#160;&#160;&#160;&#160;  <br>
SCL=&quot;0&quot;;&#160;&#160;  /*钳住I2C总线，准备发送或接收数据 */<br>
_nop_();<br>
}</p>
<p>/************************************************************************************************************************<br>
结束总线函数&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  <br>
函数原型: void Stop_I2c();<br>
功能:结束I2C总线,即发送I2C结束条件 <br>
************************************************************************************************************************/<br>
void Stop_I2c()<br>
{</p>
<p>SDA=&quot;0&quot;; /*发送结束条件的数据信号*/<br>
_nop_(); /*发送结束条件的时钟信号*/<br>
SCL=&quot;1&quot;; /*结束条件建立时间大于4μs*/<br>
_nop_();<br>
SDA=&quot;1&quot;; /*发送I2C总线结束信号*/<br>
_nop_();<br>
}</p>
<p>/*************************************************************************************************************************<br>
字节数据传送函数&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  <br>
函数原型: void SendByte(uchar c);<br>
功能:将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对此状<br>
态位进行操作(不应答或非应答都使ack=0 假) 。发送数据正常，ack=1; <br>
ack=0表示被控器无应答或损坏。<br>
**************************************************************************************************************************/<br>
void SendByte(uchar c)<br>
{<br>
uchar BitCnt;<br>
<br>
for(BitCnt=0;BitCnt&lt;8;BitCnt++) /*要传送的数据长度为8位*/<br>
{ <br>
SCL=&quot;0&quot;; <br>
if((c&lt;&lt;BitCnt)&amp;0x80) SDA=&quot;1&quot;;&#160;&#160;  /*判断发送位*/<br>
else SDA=&quot;0&quot;;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  <br>
SCL=&quot;1&quot;;&#160;&#160;&#160;&#160;&#160;&#160;  /*置时钟线为高，通知被控器开始接收数据位*/<br>
_nop_();&#160;&#160;&#160;&#160;  /*保证时钟高电平周期大于4μs*/&#160;&#160;&#160;&#160;&#160;&#160;&#160;  <br>
}<br>
<br>
//从机应答,可以用应答和非应答信号代替 <br>
_nop_();<br>
SCL=&quot;0&quot;;<br>
_nop_();<br>
SDA=&quot;1&quot;;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  //<br>
_nop_(); <br>
SCL=&quot;1&quot;;<br>
_nop_();<br>
<br>
if(SDA==1){ack=0;} /*判断是否接收到应答信号*/&#160;&#160;&#160;  <br>
else ack=&quot;1&quot;;<br>
<br>
SCL=&quot;0&quot;;<br>
_nop_();</p>
<p>}</p>
<p>/**************************************************************************************************************************<br>
字节数据传送函数&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  <br>
函数原型: uchar RcvByte();<br>
功能:用来接收从器件传来的数据,并判断总线错误(不发应答信号)，<br>
发完后请用应答函数。 <br>
***************************************************************************************************************************/ <br>
uchar RcvByte()<br>
{<br>
uchar retc;<br>
uchar BitCnt;<br>
<br>
retc=&quot;0&quot;; <br>
<br>
for(BitCnt=0;BitCnt&lt;8;BitCnt++)<br>
{&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  <br>
SCL=&quot;1&quot;;&#160;&#160;&#160;&#160;&#160;&#160;  /*置时钟线为高使数据线上数据有效*/<br>
_nop_();<br>
retc=&quot;retc&quot;&lt;&lt;1;<br>
if(SDA==1) retc=&quot;retc&quot;+1; /*读数据位,接收的数据位放入retc中 */<br>
SCL=&quot;0&quot;;<br>
}<br>
return(retc);<br>
}</p>
<p>/***************************************************************************************************************************<br>
应答子函数<br>
原型: void Ack_I2c();<br>
功能:主控器进行应答信号<br>
***************************************************************************************************************************/<br>
void Ack_I2c()<br>
{<br>
SDA=&quot;0&quot;;&#160;&#160;&#160;&#160;  /*在此发出应答信号 */<br>
_nop_();<br>
SCL=&quot;0&quot;;<br>
_nop_();&#160;&#160;&#160;&#160;&#160;  <br>
SCL=&quot;1&quot;;<br>
_nop_();<br>
SCL=&quot;0&quot;;&#160;&#160;&#160;&#160;  /*清时钟线，钳住I2C总线以便继续接收*/<br>
_nop_(); <br>
SDA=&quot;1&quot;;<br>
_nop_();<br>
}</p>
<p>/*************************************************************************************************************************<br>
非应答子函数<br>
原型: void NoAck_I2c();<br>
功能:主控器进行非应答信号<br>
**************************************************************************************************************************/<br>
void NoAck_I2c()<br>
{<br>
SDA=&quot;1&quot;; /*在此发出非应答信号 */<br>
_nop_();&#160;&#160;&#160;&#160;&#160;  <br>
SCL=&quot;1&quot;;<br>
_nop_();<br>
SCL=&quot;0&quot;; /*清时钟线，钳住I2C总线以便继续接收*/<br>
}</p>
<p>/**************************************************************************************************************************<br>
向无子地址器件发送字节数据函数&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  <br>
函数原型: bit ISendByte(uchar sla,ucahr c); <br>
功能:从启动总线到发送地址，数据，结束总线的全过程,从器件地址sla。如果<br>
返回1表示操作成功，否则操作有误。<br>
**************************************************************************************************************************/<br>
bit ISendByte(uchar sla,uchar c)<br>
{<br>
Start_I2c();&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  /*启动总线*/<br>
SendByte(sla);&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  /*发送器件地址*/<br>
if(ack==0)return(0);</p>
<p>SendByte(c);&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  /*发送数据*/<br>
if(ack==0)return(0);</p>
<p>Stop_I2c();&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  /*结束总线*/ <br>
return(1);<br>
}</p>
<p>/**************************************************************************************************************************<br>
向有子地址器件发送多字节数据函数&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  <br>
函数原型: bit ISendStr(uchar sla,uchar suba,ucahr *s,uchar no); <br>
功能:从启动总线到发送地址，子地址,数据，结束总线的全过程,从器件地址sla，<br>
子地址suba，发送内容是s指向的内容，发送no个字节。如果返回1表示<br>
操作成功，否则操作有误。<br>
***************************************************************************************************************************/<br>
bit ISendStr(uchar sla,uchar suba,uchar *s,uchar no)<br>
{<br>
uchar i;</p>
<p>Start_I2c();&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  /*启动总线*/<br>
SendByte(sla);&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  /*发送器件地址*/<br>
if(ack==0)return(0);</p>
<p>SendByte(suba);&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  /*发送器件子地址*/<br>
if(ack==0)return(0);</p>
<p>for(i=0;i&lt;no;i++)<br>
{&#160;&#160;  <br>
SendByte(*s);&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  /*发送数据*/<br>
if(ack==0)return(0);<br>
s++;<br>
} <br>
Stop_I2c();&#160;&#160;  /*结束总线*/ <br>
//delayMs(1);&#160;&#160;&#160;&#160;&#160;  //&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  <br>
return(1);<br>
}</p>
<p>/*************************************************************************************************************************<br>
向无子地址器件读字节数据函数&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  <br>
函数原型: bit IRcvByte(uchar sla,ucahr *c); <br>
功能:从启动总线到发送地址，读数据，结束总线的全过程,从器件地址sla，返<br>
回值在c。如果返回1表示操作成功，否则操作有误。<br>
*************************************************************************************************************************/<br>
bit IRcvByte(uchar sla,uchar *c)<br>
{<br>
Start_I2c();&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  /*启动总线*/<br>
SendByte(sla+1);&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  /*发送器件地址*/<br>
if(ack==0)return(0);<br>
<br>
*c=RcvByte();&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  /*读取数据*/<br>
NoAck_I2c();&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  /*发送非就答位*/<br>
Stop_I2c();&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  /*结束总线*/ <br>
return(1);<br>
}</p>
<p>/**************************************************************************************************************************<br>
向有子地址器件读取多字节数据函数&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  <br>
函数原型: bit ISendStr(uchar sla,uchar suba,ucahr *s,uchar no); <br>
功能:从启动总线到发送地址，子地址,读数据，结束总线的全过程,从器件地址sla，<br>
子地址suba，读出的内容放入s指向的存储区，读no个字节。如果返回1<br>
表示操作成功，否则操作有误。<br>
**************************************************************************************************************************/<br>
bit IRcvStr(uchar sla,uchar suba,uchar *s,uchar no)<br>
{<br>
Start_I2c();&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  /*启动总线*/<br>
SendByte(sla);&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  /*发送器件地址*/<br>
if(ack==0)return(0);<br>
<br>
SendByte(suba);&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  /*发送器件子地址*/<br>
if(ack==0)return(0);</p>
<p>Start_I2c();<br>
SendByte(sla+1);<br>
if(ack==0)return(0);</p>
<p>while(no!=1)<br>
{<br>
*s=RcvByte();/*发送数据*/<br>
Ack_I2c();&#160;&#160;  /*发送就答位*/&#160;&#160;  <br>
s++; <br>
no--;<br>
}<br>
*s=RcvByte();<br>
NoAck_I2c();&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  /*发送非应位*/<br>
Stop_I2c();&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  /*结束总线*/ <br>
return(1);<br>
}</p>
</div> <a href="http://hi.baidu.com/rwen2012/blog/item/1da3bfdcab2c30abcd1166b1.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/rwen2012/blog/category/%C7%B6%C8%EB%CA%BD%CA%B5%BC%F9">嵌入式实践</a>&nbsp;<a href="http://hi.baidu.com/rwen2012/blog/item/1da3bfdcab2c30abcd1166b1.html#comment">查看评论</a>]]></description>
        <pubDate>2009-11-02  10:08</pubDate>
        <category><![CDATA[嵌入式实践]]></category>
        <author><![CDATA[Rwen2012]]></author>
		<guid>http://hi.baidu.com/rwen2012/blog/item/1da3bfdcab2c30abcd1166b1.html</guid>
</item>

<item>
        <title><![CDATA[CodingStyle/Linux内核代码风格]]></title>
        <link><![CDATA[http://hi.baidu.com/rwen2012/blog/item/308fd413897ca48a6538dbcf.html]]></link>
        <description><![CDATA[
		
		<br>
这是一个简短的文档，描述了linux内核的首选代码风格。代码风格是因人而异的，而且我<br>
不愿意把我的观点强加给任何人，不过这里所讲述的是我必须要维护的代码所遵守的风格，<br>
并且我也希望绝大多数其他代码也能遵守这个风格。请在写代码时至少考虑一下本文所述的<br>
风格。<br>
<br>
首先，我建议你打印一份GNU代码规范，然后不要读它。烧了它，这是一个具有重大象征性<br>
意义的动作。<br>
<br>
不管怎样，现在我们开始：<br>
<br>
<br>
第一章：缩进<br>
<br>
制表符是8个字符，所以缩进也是8个字符。有些异端运动试图将缩进变为4（乃至2）个字符<br>
深，这几乎相当于尝试将圆周率的值定义为3。<br>
<br>
理由：缩进的全部意义就在于清楚的定义一个控制块起止于何处。尤其是当你盯着你的屏幕<br>
连续看了20小时之后，你将会发现大一点的缩进会使你更容易分辨缩进。<br>
<br>
现在，有些人会抱怨8个字符的缩进会使代码向右边移动的太远，在80个字符的终端屏幕上<br>
就很难读这样的代码。这个问题的答案是，如果你需要3级以上的缩进，不管用何种方式你<br>
的代码已经有问题了，应该修正你的程序。<br>
<br>
简而言之，8个字符的缩进可以让代码更容易阅读，还有一个好处是当你的函数嵌套太深的<br>
时候可以给你警告。留心这个警告。<br>
<br>
在switch语句中消除多级缩进的首选的方式是让“switch”和从属于它的“case”标签对齐于同<br>
一列，而不要“两次缩进”“case”标签。比如：<br>
<br>
switch (suffix) {<br>
case 'G':<br>
case 'g':<br>
mem &lt;&lt;= 30;<br>
break;<br>
case 'M':<br>
case 'm':<br>
mem &lt;&lt;= 20;<br>
break;<br>
case 'K':<br>
case 'k':<br>
mem &lt;&lt;= 10;<br>
/* fall through */<br>
default:<br>
break;<br>
}<br>
<br>
<br>
不要把多个语句放在一行里，除非你有什么东西要隐藏：<br>
<br>
if (condition) do_this;<br>
do_something_everytime;<br>
<br>
也不要在一行里放多个赋值语句。内核代码风格超级简单。就是避免可能导致别人误读的表<br>
达式。<br>
<br>
除了注释、文档和Kconfig之外，不要使用空格来缩进，前面的例子是例外，是有意为之。<br>
<br>
选用一个好的编辑器，不要在行尾留空格。<br>
<br>
<br>
第二章：把长的行和字符串打散<br>
<br>
代码风格的意义就在于使用平常使用的工具来维持代码的可读性和可维护性。<br>
<br>
每一行的长度的限制是80列，我们强烈建议您遵守这个惯例。<br>
<br>
长于80列的语句要打散成有意义的片段。每个片段要明显短于原来的语句，而且放置的位置<br>
也明显的靠右。同样的规则也适用于有很长参数列表的函数头。长字符串也要打散成较短的<br>
字符串。唯一的例外是超过80列可以大幅度提高可读性并且不会隐藏信息的情况。<br>
<br>
void fun(int a, int b, int c)<br>
{<br>
if (condition)<br>
printk(KERN_WARNING &quot;Warning this is a long printk with &quot;<br>
&quot;3 parameters a: %u b: %u &quot;<br>
&quot;c: %u \n&quot;, a, b, c);<br>
else<br>
next_statement;<br>
}<br>
<br>
第三章：大括号和空格的放置<br>
<br>
C语言风格中另外一个常见问题是大括号的放置。和缩进大小不同，选择或弃用某种放置策<br>
略并没有多少技术上的原因，不过首选的方式，就像Kernighan和Ritchie展示给我们的，是<br>
把起始大括号放在行尾，而把结束大括号放在行首，所以：<br>
<br>
if (x is true) {<br>
we do y<br>
}<br>
<br>
这适用于所有的非函数语句块（if、switch、for、while、do）。比如：<br>
<br>
switch (action) {<br>
case KOBJ_ADD:<br>
return &quot;add&quot;;<br>
case KOBJ_REMOVE:<br>
return &quot;remove&quot;;<br>
case KOBJ_CHANGE:<br>
return &quot;change&quot;;<br>
default:<br>
return NULL;<br>
}<br>
<br>
不过，有一个例外，那就是函数：函数的起始大括号放置于下一行的开头，所以：<br>
<br>
int function(int x)<br>
{<br>
body of function<br>
}<br>
<br>
全世界的异端可能会抱怨这个不一致性是……呃……不一致的，不过所有思维健全的人都知道（<br>
a）K&amp;R是_正确的_，并且（b）K&amp;R是正确的。此外，不管怎样函数都是特殊的（在C语言中<br>
，函数是不能嵌套的）。<br>
<br>
注意结束大括号独自占据一行，除非它后面跟着同一个语句的剩余部分，也就是do语句中的<br>
“while”或者if语句中的“else”，像这样：<br>
<br>
do {<br>
body of do-loop<br>
} while (condition);<br>
<br>
和<br>
<br>
if (x == y) {<br>
..<br>
} else if (x &gt; y) {<br>
...<br>
} else {<br>
....<br>
}<br>
<br>
理由：K&amp;R。<br>
<br>
也请注意这种大括号的放置方式也能使空（或者差不多空的）行的数量最小化，同时不失可<br>
读性。因此，由于你的屏幕上的新行是不可再生资源（想想25行的终端屏幕），你将会有更<br>
多的空行来放置注释。<br>
<br>
当只有一个单独的语句的时候，不用加不必要的大括号。<br>
<br>
if (condition)<br>
action();<br>
<br>
这点不适用于本身为某个条件语句的一个分支的单独语句。这时需要在两个分支里都使用大<br>
括号。<br>
<br>
if (condition) {<br>
do_this();<br>
do_that();<br>
} else {<br>
otherwise();<br>
}<br>
<br>
3.1：空格<br>
<br>
Linux内核的空格使用方式（主要）取决于它是用于函数还是关键字。（大多数）关键字后<br>
要加一个空格。值得注意的例外是sizeof、typeof、alignof和__attribute__，这些关键字<br>
某些程度上看起来更像函数（它们在Linux里也常常伴随小括号而使用，尽管在C语言里这样<br>
的小括号不是必需的，就像“struct fileinfo info”声明过后的“sizeof info”）。<br>
<br>
所以在这些关键字之后放一个空格：<br>
if, switch, case, for, do, while<br>
但是不要在sizeof、typeof、alignof或者__attribute__这些关键字之后放空格。例如，<br>
s = sizeof(struct file);<br>
<br>
不要在小括号里的表达式两侧加空格。这是一个反例：<br>
<br>
s = sizeof( struct file );<br>
<br>
当声明指针类型或者返回指针类型的函数时，“*”的首选使用方式是使之靠近变量名或者函<br>
数名，而不是靠近类型名。例子：<br>
<br>
char *linux_banner;<br>
unsigned long long memparse(char *ptr, char **retptr);<br>
char *match_strdup(substring_t *s);<br>
<br>
在大多数二元和三元操作符两侧使用一个空格，例如下面所有这些操作符：<br>
<br>
=&#160; +&#160; -&#160; &lt;&#160; &gt;&#160; *&#160; /&#160; %&#160; |&#160; &amp;&#160; ^&#160; &lt;=&#160; &gt;=&#160; ==&#160; !=&#160; ?&#160; :<br>
<br>
但是一元操作符后不要加空格：<br>
&amp;&#160; *&#160; +&#160; -&#160; ~&#160; !&#160; sizeof&#160; typeof&#160; alignof&#160; __attribute__&#160; defined<br>
<br>
后缀自加和自减一元操作符前不加空格：<br>
++&#160; --<br>
<br>
前缀自加和自减一元操作符后不加空格：<br>
++&#160; --<br>
<br>
“.”和“-&gt;”结构体成员操作符前后不加空格。<br>
<br>
不要在行尾留空白。有些可以自动缩进的编辑器会在新行的行首加入适量的空白，然后你<br>
就可以直接在那一行输入代码。不过假如你最后没有在那一行输入代码，有些编辑器就不<br>
会移除已经加入的空白，就像你故意留下一个只有空白的行。包含行尾空白的行就这样产<br>
生了。<br>
<br>
当git发现补丁包含了行尾空白的时候会警告你，并且可以应你的要求去掉行尾空白；不过<br>
如果你是正在打一系列补丁，这样做会导致后面的补丁失败，因为你改变了补丁的上下文。<br>
<br>
<br>
第四章：命名<br>
<br>
C是一个简朴的语言，你的命名也应该这样。和Modula-2和Pascal程序员不同，C程序员不使<br>
用类似ThisVariableIsATemporaryCounter这样华丽的名字。C程序员会称那个变量为“tmp”<br>
，这样写起来会更容易，而且至少不会令其难于理解。<br>
<br>
不过，虽然混用大小写的名字是不提倡使用的，但是全局变量还是需要一个具描述性的名字<br>
。称一个全局函数为“foo”是一个难以饶恕的错误。<br>
<br>
全局变量（只有当你真正需要它们的时候再用它）需要有一个具描述性的名字，就像全局函<br>
数。如果你有一个可以计算活动用户数量的函数，你应该叫它“count_active_users()”或者<br>
类似的名字，你不应该叫它“cntuser()”。<br>
<br>
在函数名中包含函数类型（所谓的匈牙利命名法）是脑子出了问题——编译器知道那些类型而<br>
且能够检查那些类型，这样做只能把程序员弄糊涂了。难怪微软总是制造出有问题的程序。<br>
<br>
本地变量名应该简短，而且能够表达相关的含义。如果你有一些随机的整数型的循环计数器<br>
，它应该被称为“i”。叫它“loop_counter”并无益处，如果它没有被误解的可能的话。类似<br>
的，“tmp”可以用来称呼任意类型的临时变量。<br>
<br>
如果你怕混淆了你的本地变量名，你就遇到另一个问题了，叫做函数增长荷尔蒙失衡综合症<br>
。请看第六章（函数）。<br>
<br>
<br>
第五章：Typedef<br>
<br>
不要使用类似“vps_t”之类的东西。<br>
<br>
对结构体和指针使用typedef是一个错误。当你在代码里看到：<br>
<br>
vps_t a;<br>
<br>
这代表什么意思呢？<br>
<br>
相反，如果是这样<br>
<br>
struct virtual_container *a;<br>
<br>
你就知道“a”是什么了。<br>
<br>
很多人认为typedef“能提高可读性”。实际不是这样的。它们只在下列情况下有用：<br>
<br>
(a) 完全不透明的对象（这种情况下要主动使用typedef来隐藏这个对象实际上是什么）。<br>
<br>
例如：“pte_t”等不透明对象，你只能用合适的访问函数来访问它们。<br>
<br>
注意！不透明性和“访问函数”本身是不好的。我们使用pte_t等类型的原因在于真的是<br>
完全没有任何共用的可访问信息。<br>
<br>
(b) 清楚的整数类型，如此，这层抽象就可以帮助消除到底是“int”还是“long”的混淆。<br>
<br>
u8/u16/u32是完全没有问题的typedef，不过它们更符合类别(d)而不是这里。<br>
<br>
再次注意！要这样做，必须事出有因。如果某个变量是“unsigned long“，那么没有必要<br>
<br>
typedef unsigned long myflags_t;<br>
<br>
不过如果有一个明确的原因，比如它在某种情况下可能会是一个“unsigned int”而在<br>
其他情况下可能为“unsigned long”，那么就不要犹豫，请务必使用typedef。<br>
<br>
(c) 当你使用sparse按字面的创建一个新类型来做类型检查的时候。<br>
<br>
(d) 和标准C99类型相同的类型，在某些例外的情况下。<br>
<br>
虽然让眼睛和脑筋来适应新的标准类型比如“uint32_t”不需要花很多时间，可是有些<br>
人仍然拒绝使用它们。<br>
<br>
因此，Linux特有的等同于标准类型的“u8/u16/u32/u64”类型和它们的有符号类型是被<br>
允许的——尽管在你自己的新代码中，它们不是强制要求要使用的。<br>
<br>
当编辑已经使用了某个类型集的已有代码时，你应该遵循那些代码中已经做出的选择。<br>
<br>
(e) 可以在用户空间安全使用的类型。<br>
<br>
在某些用户空间可见的结构体里，我们不能要求C99类型而且不能用上面提到的“u32”<br>
类型。因此，我们在与用户空间共享的所有结构体中使用__u32和类似的类型。<br>
<br>
可能还有其他的情况，不过基本的规则是永远不要使用typedef，除非你可以明确的应用上<br>
述某个规则中的一个。<br>
<br>
总的来说，如果一个指针或者一个结构体里的元素可以合理的被直接访问到，那么它们就不<br>
应该是一个typedef。<br>
<br>
<br>
第六章：函数<br>
<br>
函数应该简短而漂亮，并且只完成一件事情。函数应该可以一屏或者两屏显示完（我们都知<br>
道ISO/ANSI屏幕大小是80x24），只做一件事情，而且把它做好。<br>
<br>
一个函数的最大长度是和该函数的复杂度和缩进级数成反比的。所以，如果你有一个理论上<br>
很简单的只有一个很长（但是简单）的case语句的函数，而且你需要在每个case里做很多很<br>
小的事情，这样的函数尽管很长，但也是可以的。<br>
<br>
不过，如果你有一个复杂的函数，而且你怀疑一个天分不是很高的高中一年级学生可能甚至<br>
搞不清楚这个函数的目的，你应该严格的遵守前面提到的长度限制。使用辅助函数，并为之<br>
取个具描述性的名字（如果你觉得它们的性能很重要的话，可以让编译器内联它们，这样的<br>
效果往往会比你写一个复杂函数的效果要好。）<br>
<br>
函数的另外一个衡量标准是本地变量的数量。此数量不应超过5－10个，否则你的函数就有<br>
问题了。重新考虑一下你的函数，把它分拆成更小的函数。人的大脑一般可以轻松的同时跟<br>
踪7个不同的事物，如果再增多的话，就会糊涂了。即便你聪颖过人，你也可能会记不清你2<br>
个星期前做过的事情。<br>
<br>
在源文件里，使用空行隔开不同的函数。如果该函数需要被导出，它的EXPORT*宏应该紧贴<br>
在它的结束大括号之下。比如：<br>
<br>
int system_is_up(void)<br>
{<br>
return system_state == SYSTEM_RUNNING;<br>
}<br>
EXPORT_SYMBOL(system_is_up);<br>
<br>
在函数原型中，包含函数名和它们的数据类型。虽然C语言里没有这样的要求，在Linux里这<br>
是提倡的做法，因为这样可以很简单的给读者提供更多的有价值的信息。<br>
<br>
<br>
第七章：集中的函数退出途径<br>
<br>
虽然被某些人声称已经过时，但是goto语句的等价物还是经常被编译器所使用，具体形式是<br>
无条件跳转指令。<br>
<br>
当一个函数从多个位置退出并且需要做一些通用的清理工作的时候，goto的好处就显现出来<br>
了。<br>
<br>
理由是：<br>
<br>
- 无条件语句容易理解和跟踪<br>
- 嵌套程度减小<br>
- 可以避免由于修改时忘记更新某个单独的退出点而导致的错误<br>
- 减轻了编译器的工作，无需删除冗余代码;)<br>
<br>
int fun(int a)<br>
{<br>
int result = 0;<br>
char *buffer = kmalloc(SIZE);<br>
<br>
if (buffer == NULL)<br>
return -ENOMEM;<br>
<br>
if (condition1) {<br>
while (loop1) {<br>
...<br>
}<br>
result = 1;<br>
goto out;<br>
}<br>
...<br>
out:<br>
kfree(buffer);<br>
return result;<br>
}<br>
<br>
第八章：注释<br>
<br>
注释是好的，不过有过度注释的危险。永远不要在注释里解释你的代码是如何运作的：更好<br>
的做法是让别人一看你的代码就可以明白，解释写的很差的代码是浪费时间。<br>
<br>
一般的，你想要你的注释告诉别人你的代码做了什么，而不是怎么做的。也请你不要把注释<br>
放在一个函数体内部：如果函数复杂到你需要独立的注释其中的一部分，你很可能需要回到<br>
第六章看一看。你可以做一些小注释来注明或警告某些很聪明（或者槽糕）的做法，但不要<br>
加太多。你应该做的，是把注释放在函数的头部，告诉人们它做了什么，也可以加上它做这<br>
些事情的原因。<br>
<br>
当注释内核API函数时，请使用kernel-doc格式。请看<br>
Documentation/kernel-doc-nano-HOWTO.txt和scripts/kernel-doc以获得详细信息。<br>
<br>
Linux的注释风格是C89“/* ... */”风格。不要使用C99风格“// ...”注释。<br>
<br>
长（多行）的首选注释风格是：<br>
<br>
/*<br>
* This is the preferred style for multi-line<br>
* comments in the Linux kernel source code.<br>
* Please use it consistently.<br>
*<br>
* Description:&#160; A column of asterisks on the left side,<br>
* with beginning and ending almost-blank lines.<br>
*/<br>
<br>
注释数据也是很重要的，不管是基本类型还是衍生类型。为了方便实现这一点，每一行应只<br>
声明一个数据（不要使用逗号来一次声明多个数据）。这样你就有空间来为每个数据写一段<br>
小注释来解释它们的用途了。<br>
<br>
<br>
第九章：你已经把事情弄糟了<br>
<br>
这没什么，我们都是这样。可能你的使用了很长时间Unix的朋友已经告诉你“GNU emacs”能<br>
自动帮你格式化C源代码，而且你也注意到了，确实是这样，不过它所使用的默认值和我们<br>
想要的相去甚远（实际上，甚至比随机打的还要差——无数个猴子在GNU emacs里打字永远不<br>
会创造出一个好程序）（译注：请参考Infinite Monkey Theorem）<br>
<br>
所以你要么放弃GNU emacs，要么改变它让它使用更合理的设定。要采用后一个方案，你可<br>
以把下面这段粘贴到你的.emacs文件里。<br>
<br>
(defun linux-c-mode ()<br>
&quot;C mode with adjusted defaults for use with the Linux kernel.&quot;<br>
(interactive)<br>
(c-mode)<br>
(c-set-style &quot;K&amp;R&quot;)<br>
(setq tab-width 8)<br>
(setq indent-tabs-mode t)<br>
(setq c-basic-offset 8))<br>
<br>
这样就定义了M-x linux-c-mode命令。当你hack一个模块的时候，如果你把字符串<br>
-*- linux-c -*-放在头两行的某个位置，这个模式将会被自动调用。如果你希望在你修改<br>
/usr/src/linux里的文件时魔术般自动打开linux-c-mode的话，你也可能需要添加<br>
<br>
(setq auto-mode-alist (cons '(&quot;/usr/src/linux.*/.*\\.[ch]$&quot; . linux-c-mode)<br>
auto-mode-alist))<br>
<br>
到你的.emacs文件里。<br>
<br>
不过就算你尝试让emacs正确的格式化代码失败了，也并不意味着你失去了一切：还可以用“<br>
indent”。<br>
<br>
不过，GNU indent也有和GNU emacs一样有问题的设定，所以你需要给它一些命令选项。不<br>
过，这还不算太糟糕，因为就算是GNU indent的作者也认同K&amp;R的权威性（GNU的人并不是坏<br>
人，他们只是在这个问题上被严重的误导了），所以你只要给indent指定选项“-kr -i8”<br>
（代表“K&amp;R，8个字符缩进”），或者使用“scripts/Lindent”，这样就可以以最时髦的方式<br>
缩进源代码。<br>
<br>
“indent”有很多选项，特别是重新格式化注释的时候，你可能需要看一下它的手册页。不过<br>
记住：“indent”不能修正坏的编程习惯。<br>
<br>
<br>
第十章：Kconfig配置文件<br>
<br>
对于遍布源码树的所有Kconfig*配置文件来说，它们缩进方式与C代码相比有所不同。紧挨<br>
在“config”定义下面的行缩进一个制表符，帮助信息则再多缩进2个空格。比如：<br>
<br>
config AUDIT<br>
bool &quot;Auditing support&quot;<br>
depends on NET<br>
help<br>
Enable auditing infrastructure that can be used with another<br>
kernel subsystem, such as SELinux (which requires this for<br>
logging of avc messages output).&#160; Does not do system-call<br>
auditing without CONFIG_AUDITSYSCALL.<br>
<br>
仍然被认为不够稳定的功能应该被定义为依赖于“EXPERIMENTAL”：<br>
<br>
config SLUB<br>
depends on EXPERIMENTAL &amp;&amp; !ARCH_USES_SLAB_PAGE_STRUCT<br>
bool &quot;SLUB (Unqueued Allocator)&quot;<br>
...<br>
<br>
而那些危险的功能（比如某些文件系统的写支持）应该在它们的提示字符串里显著的声明这<br>
一点：<br>
<br>
config ADFS_FS_RW<br>
bool &quot;ADFS write support (DANGEROUS)&quot;<br>
depends on ADFS_FS<br>
...<br>
<br>
要查看配置文件的完整文档，请看Documentation/kbuild/kconfig-language.txt。<br>
<br>
<br>
第十一章：数据结构<br>
<br>
如果一个数据结构，在创建和销毁它的单线执行环境之外可见，那么它必须要有一个引用计<br>
数器。内核里没有垃圾收集（并且内核之外的垃圾收集慢且效率低下），这意味着你绝对需<br>
要记录你对这种数据结构的使用情况。<br>
<br>
引用计数意味着你能够避免上锁，并且允许多个用户并行访问这个数据结构——而不需要担心<br>
这个数据结构仅仅因为暂时不被使用就消失了，那些用户可能不过是沉睡了一阵或者做了一<br>
些其他事情而已。<br>
<br>
注意上锁不能取代引用计数。上锁是为了保持数据结构的一致性，而引用计数是一个内存管<br>
理技巧。通常二者都需要，不要把两个搞混了。<br>
<br>
很多数据结构实际上有2级引用计数，它们通常有不同“类”的用户。子类计数器统计子类用<br>
户的数量，每当子类计数器减至零时，全局计数器减一。<br>
<br>
这种“多级引用计数”的例子可以在内存管理（“struct mm_struct”：mm_users和mm_count）<br>
和文件系统（“struct super_block”：s_count和s_active）中找到。<br>
<br>
记住：如果另一个执行线索可以找到你的数据结构，但是这个数据结构没有引用计数器，这<br>
里几乎肯定是一个bug。<br>
<br>
<br>
第十二章：宏，枚举和RTL<br>
<br>
用于定义常量的宏的名字及枚举里的标签需要大写。<br>
<br>
#define CONSTANT 0x12345<br>
<br>
在定义几个相关的常量时，最好用枚举。<br>
<br>
宏的名字请用大写字母，不过形如函数的宏的名字可以用小写字母。<br>
<br>
一般的，如果能写成内联函数就不要写成像函数的宏。<br>
<br>
含有多个语句的宏应该被包含在一个do-while代码块里：<br>
<br>
#define macrofun(a, b, c)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; \<br>
do {&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; \<br>
if (a == 5)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; \<br>
do_this(b, c);&#160;&#160;&#160;&#160;&#160;&#160;&#160; \<br>
} while (0)<br>
<br>
使用宏的时候应避免的事情：<br>
<br>
1) 影响控制流程的宏：<br>
<br>
#define FOO(x)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; \<br>
do {&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; \<br>
if (blah(x) &lt; 0)&#160;&#160;&#160;&#160;&#160;&#160;&#160; \<br>
return -EBUGGERED;&#160;&#160;&#160; \<br>
} while(0)<br>
<br>
非常不好。它看起来像一个函数，不过却能导致“调用”它的函数退出；不要打乱读者大脑里<br>
的语法分析器。<br>
<br>
2) 依赖于一个固定名字的本地变量的宏：<br>
<br>
#define FOO(val) bar(index, val)<br>
<br>
可能看起来像是个不错的东西，不过它非常容易把读代码的人搞糊涂，而且容易导致看起来<br>
不相关的改动带来错误。<br>
<br>
3) 作为左值的带参数的宏： FOO(x) = y；如果有人把FOO变成一个内联函数的话，这种用<br>
法就会出错了。<br>
<br>
4) 忘记了优先级：使用表达式定义常量的宏必须将表达式置于一对小括号之内。带参数的<br>
宏也要注意此类问题。<br>
<br>
#define CONSTANT 0x4000<br>
#define CONSTEXP (CONSTANT | 3)<br>
<br>
cpp手册对宏的讲解很详细。Gcc internals手册也详细讲解了RTL（译注：register<br>
transfer language），内核里的汇编语言经常用到它。<br>
<br>
<br>
第十三章：打印内核消息<br>
<br>
内核开发者应该是受过良好教育的。请一定注意内核信息的拼写，以给人以好的印象。不要<br>
用不规范的单词比如“dont”，而要用“do not”或者“don't”。保证这些信息简单、明了、无<br>
歧义。<br>
<br>
内核信息不必以句号（译注：英文句号，即点）结束。<br>
<br>
在小括号里打印数字(%d)没有任何价值，应该避免这样做。<br>
<br>
&lt;linux/device.h&gt;里有一些驱动模型诊断宏，你应该使用它们，以确保信息对应于正确的<br>
设备和驱动，并且被标记了正确的消息级别。这些宏有：dev_err(), dev_warn(),<br>
dev_info()等等。对于那些不和某个特定设备相关连的信息，&lt;linux/kernel.h&gt;定义了<br>
pr_debug()和pr_info()。<br>
<br>
写出好的调试信息可以是一个很大的挑战；当你写出来之后，这些信息在远程除错的时候<br>
就会成为极大的帮助。当DEBUG符号没有被定义的时候，这些信息不应该被编译进内核里<br>
（也就是说，默认地，它们不应该被包含在内）。如果你使用dev_dbg()或者pr_debug()，<br>
就能自动达到这个效果。很多子系统拥有Kconfig选项来启用-DDEBUG。还有一个相关的惯例<br>
是使用VERBOSE_DEBUG来添加dev_vdbg()消息到那些已经由DEBUG启用的消息之上。<br>
<br>
<br>
第十四章：分配内存<br>
<br>
内核提供了下面的一般用途的内存分配函数：kmalloc()，kzalloc()，kcalloc()和<br>
vmalloc()。请参考API文档以获取有关它们的详细信息。<br>
<br>
传递结构体大小的首选形式是这样的：<br>
<br>
p = kmalloc(sizeof(*p), ...);<br>
<br>
另外一种传递方式中，sizeof的操作数是结构体的名字，这样会降低可读性，并且可能会引<br>
入bug。有可能指针变量类型被改变时，而对应的传递给内存分配函数的sizeof的结果不变。<br>
<br>
强制转换一个void指针返回值是多余的。C语言本身保证了从void指针到其他任何指针类型<br>
的转换是没有问题的。<br>
<br>
<br>
第十五章：内联弊病<br>
<br>
有一个常见的误解是内联函数是gcc提供的可以让代码运行更快的一个选项。虽然使用内联<br>
函数有时候是恰当的（比如作为一种替代宏的方式，请看第十二章），不过很多情况下不是<br>
这样。inline关键字的过度使用会使内核变大，从而使整个系统运行速度变慢。因为大内核<br>
会占用更多的指令高速缓存（译注：一级缓存通常是指令缓存和数据缓存分开的）而且会导<br>
致pagecache的可用内存减少。想象一下，一次pagecache未命中就会导致一次磁盘寻址，将<br>
耗时5毫秒。5毫秒的时间内CPU能执行很多很多指令。<br>
<br>
一个基本的原则是如果一个函数有3行以上，就不要把它变成内联函数。这个原则的一个例<br>
外是，如果你知道某个参数是一个编译时常量，而且因为这个常量你确定编译器在编译时能<br>
优化掉你的函数的大部分代码，那仍然可以给它加上inline关键字。kmalloc()内联函数就<br>
是一个很好的例子。<br>
<br>
人们经常主张给static的而且只用了一次的函数加上inline，如此不会有任何损失，因为没<br>
有什么好权衡的。虽然从技术上说这是正确的，但是实际上这种情况下即使不加inline gcc<br>
也可以自动使其内联。而且其他用户可能会要求移除inline，由此而来的争论会抵消inline<br>
自身的潜在价值，得不偿失。<br>
<br>
<br>
第十六章：函数返回值及命名<br>
<br>
函数可以返回很多种不同类型的值，最常见的一种是表明函数执行成功或者失败的值。这样<br>
的一个值可以表示为一个错误代码整数（-Exxx＝失败，0＝成功）或者一个“成功”布尔值（<br>
0＝失败，非0＝成功）。<br>
<br>
混合使用这两种表达方式是难于发现的bug的来源。如果C语言本身严格区分整形和布尔型变<br>
量，那么编译器就能够帮我们发现这些错误……不过C语言不区分。为了避免产生这种bug，请<br>
遵循下面的惯例：<br>
<br>
如果函数的名字是一个动作或者强制性的命令，那么这个函数应该返回错误代码整<br>
数。如果是一个判断，那么函数应该返回一个“成功”布尔值。<br>
<br>
比如，“add work”是一个命令，所以add_work()函数在成功时返回0，在失败时返回-EBUSY。<br>
类似的，因为“PCI device present”是一个判断，所以pci_dev_present()函数在成功找到<br>
一个匹配的设备时应该返回1，如果找不到时应该返回0。<br>
<br>
所有导出（译注：EXPORT）的函数都必须遵守这个惯例，所有的公共函数也都应该如此。私<br>
有（static）函数不需要如此，但是我们也推荐这样做。<br>
<br>
返回值是实际计算结果而不是计算是否成功的标志的函数不受此惯例的限制。一般的，他们<br>
通过返回一些正常值范围之外的结果来表示出错。典型的例子是返回指针的函数，他们使用<br>
NULL或者ERR_PTR机制来报告错误。<br>
<br>
<br>
第十七章：不要重新发明内核宏<br>
<br>
头文件include/linux/kernel.h包含了一些宏，你应该使用它们，而不要自己写一些它们的<br>
变种。比如，如果你需要计算一个数组的长度，使用这个宏<br>
<br>
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))<br>
<br>
类似的，如果你要计算某结构体成员的大小，使用<br>
<br>
#define FIELD_SIZEOF(t, f) (sizeof(((t*)0)-&gt;f))<br>
<br>
还有可以做严格的类型检查的min()和max()宏，如果你需要可以使用它们。你可以自己看看<br>
那个头文件里还定义了什么你可以拿来用的东西，如果有定义的话，你就不应在你的代码里<br>
自己重新定义。<br>
<br>
<br>
第十八章：编辑器模式行和其他需要罗嗦的事情<br>
<br>
有一些编辑器可以解释嵌入在源文件里的由一些特殊标记标明的配置信息。比如，emacs<br>
能够解释被标记成这样的行：<br>
<br>
-*- mode: c -*-<br>
<br>
或者这样的：<br>
<br>
/*<br>
Local Variables:<br>
compile-command: &quot;gcc -DMAGIC_DEBUG_FLAG foo.c&quot;<br>
End:<br>
*/<br>
<br>
Vim能够解释这样的标记：<br>
<br>
/* vim:set sw=8 noet */<br>
<br>
不要在源代码中包含任何这样的内容。每个人都有他自己的编辑器配置，你的源文件不应<br>
该覆盖别人的配置。这包括有关缩进和模式配置的标记。人们可以使用他们自己定制的模<br>
式，或者使用其他可以产生正确的缩进的巧妙方法。 <a href="http://hi.baidu.com/rwen2012/blog/item/308fd413897ca48a6538dbcf.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/rwen2012/blog/category/c%D3%EF%D1%D4%CA%B5%BC%F9">c语言实践</a>&nbsp;<a href="http://hi.baidu.com/rwen2012/blog/item/308fd413897ca48a6538dbcf.html#comment">查看评论</a>]]></description>
        <pubDate>2009-10-23  11:04</pubDate>
        <category><![CDATA[c语言实践]]></category>
        <author><![CDATA[Rwen2012]]></author>
		<guid>http://hi.baidu.com/rwen2012/blog/item/308fd413897ca48a6538dbcf.html</guid>
</item>

<item>
        <title><![CDATA[Many Ways to Use Remote Desktop (X11VNC)]]></title>
        <link><![CDATA[http://hi.baidu.com/rwen2012/blog/item/49713109029ec1a52fddd435.html]]></link>
        <description><![CDATA[
		
		<h2 class="contentheading"><a class="contentpagetitle" href="http://www.linux.com/learn/tutorials/102976-many-ways-to-use-remote-desktop-x11vnc">   Many Ways to Use Remote Desktop (X11VNC) </a></h2>
<div class="article-toolswrap">
<div class="article-tools clearfix">
<div class="article-meta"><span class="createdate">    Thursday, 22 October 2009 06:21  </span>       <span class="createby">    <a href="http://www.linux.com/community/profile?userid=10674">Aaron</a>  </span></div>
</div>
</div>
<div class="tt_top">


</div>
<p>There are many ways to get into a computer by using remote desktop. Some examples include: ssh, VNC, RDP, XDMCP, ICA, X11VNC, etc.</p>
<p>Remote desktop can be used for lots of different reasons, such as if you promised your son to get him a game in your house and you have to go to work, VNC can come to the rescue!. Or, if you need help with configuring something on your system and know a trusted person that can assist you remotely, X11VNC is the tool to help.</p>
<p>Today, I'm going to talk about X11VNC. X11VNC is the most commonly used remote desktop tool for X systems. To start X11VNC, you need to first install it. To get X11VNC, type this command in a terminal of a Debian- or Ubuntu-based:</p>
<pre>sudo apt-get install x11vnc</pre>
<ol>
    <li>To start it up, just for a test, type
    <pre>x11vnc</pre>
    and you might see&#160;something that catches your attention. <em>You're using X11VNC without a password</em>. Press Ctrl + C.</li>
    <li>Time to setup a password. Type
    <pre>x11vnc -storepasswd</pre>
    </li>
    <li>Enter a password.</li>
    <li>X11VNC will ask you to save your password into a place like /home/&lt;YOUR LOGIN NAME&gt;/.vnc/passwd. It will ask you to confirm. Press y.</li>
    <li>To start X11VNC with a password, get ready to type 32 letters or more if your name is large. Type
    <pre>x11vnc -rfbauth /home/&lt;YOUR LOGIN NAME&gt;/.vnc/passwd</pre>
    and there you have it!</li>
</ol>
<p>Note your host and port. Since the server setup is complete, let's move on to client. You should have two accounts for this step.</p>
<ol>
    <li>Login to the other account without closing the terminal or logging off that account.</li>
    <li>Open a terminal and type
    <pre>vncviewer &lt;THE HOST NAME&gt;:&lt;THE PORT&gt;.</pre>
    </li>
</ol>
You're done, remote desktop is set up.<br>
<br>
<br>
http://www.linux.com/learn/tutorials/102976-many-ways-to-use-remote-desktop-x11vnc <a href="http://hi.baidu.com/rwen2012/blog/item/49713109029ec1a52fddd435.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/rwen2012/blog/category/Tools">Tools</a>&nbsp;<a href="http://hi.baidu.com/rwen2012/blog/item/49713109029ec1a52fddd435.html#comment">查看评论</a>]]></description>
        <pubDate>2009-10-23  08:51</pubDate>
        <category><![CDATA[Tools]]></category>
        <author><![CDATA[Rwen2012]]></author>
		<guid>http://hi.baidu.com/rwen2012/blog/item/49713109029ec1a52fddd435.html</guid>
</item>

<item>
        <title><![CDATA[ffs/fls]]></title>
        <link><![CDATA[http://hi.baidu.com/rwen2012/blog/item/35db04a95e25abf61e17a2c9.html]]></link>
        <description><![CDATA[
		
		#if __LINUX_ARM_ARCH__ &lt; 5<br>
<br>
#include &lt;asm-generic/bitops/ffz.h&gt;<br>
#include &lt;asm-generic/bitops/__fls.h&gt;<br>
#include &lt;asm-generic/bitops/__ffs.h&gt;<br>
#include &lt;asm-generic/bitops/fls.h&gt;<br>
#include &lt;asm-generic/bitops/ffs.h&gt;<br>
<br>
#else<br>
<br>
static inline int constant_fls(int x)<br>
{<br>
int r = 32;<br>
<br>
if (!x)<br>
return 0;<br>
if (!(x &amp; 0xffff0000u)) {<br>
x &lt;&lt;= 16;<br>
r -= 16;<br>
}<br>
if (!(x &amp; 0xff000000u)) {<br>
x &lt;&lt;= 8;<br>
r -= 8;<br>
}<br>
if (!(x &amp; 0xf0000000u)) {<br>
x &lt;&lt;= 4;<br>
r -= 4;<br>
}<br>
if (!(x &amp; 0xc0000000u)) {<br>
x &lt;&lt;= 2;<br>
r -= 2;<br>
}<br>
if (!(x &amp; 0x80000000u)) {<br>
x &lt;&lt;= 1;<br>
r -= 1;<br>
}<br>
return r;<br>
}<br>
<br>
/*<br>
* On ARMv5 and above those functions can be implemented around<br>
* the clz instruction for much better code efficiency.<br>
*/<br>
<br>
static inline int fls(int x)<br>
{<br>
int ret;<br>
<br>
if (__builtin_constant_p(x))<br>
return constant_fls(x);<br>
<br>
asm(&quot;clz\t%0, %1&quot; : &quot;=r&quot; (ret) : &quot;r&quot; (x) : &quot;cc&quot;);<br>
ret = 32 - ret;<br>
return ret;<br>
}<br>
<br>
#define __fls(x) (fls(x) - 1)<br>
#define ffs(x) ({ unsigned long __t = (x); fls(__t &amp; -__t); })<br>
#define __ffs(x) (ffs(x) - 1)<br>
#define ffz(x) __ffs( ~(x) )<br>
<br>
#endif<br>
<br>
<br>
#ifndef _ASM_GENERIC_BITOPS_FFS_H_<br>
#define _ASM_GENERIC_BITOPS_FFS_H_<br>
<br>
/**<br>
* ffs - find first bit set<br>
* @x: the word to search<br>
*<br>
* This is defined the same way as<br>
* the libc and compiler builtin ffs routines, therefore<br>
* differs in spirit from the above ffz (man ffs).<br>
*/<br>
<br>
static inline int ffs(int x)<br>
{<br>
int r = 1;<br>
<br>
if (!x)<br>
return 0;<br>
if (!(x &amp; 0xffff)) {<br>
x &gt;&gt;= 16;<br>
r += 16;<br>
}<br>
if (!(x &amp; 0xff)) {<br>
x &gt;&gt;= 8;<br>
r += 8;<br>
}<br>
if (!(x &amp; 0xf)) {<br>
x &gt;&gt;= 4;<br>
r += 4;<br>
}<br>
if (!(x &amp; 3)) {<br>
x &gt;&gt;= 2;<br>
r += 2;<br>
}<br>
if (!(x &amp; 1)) {<br>
x &gt;&gt;= 1;<br>
r += 1;<br>
}<br>
return r;<br>
}<br>
<br>
#endif /* _ASM_GENERIC_BITOPS_FFS_H_ */<br>
<br> <a href="http://hi.baidu.com/rwen2012/blog/item/35db04a95e25abf61e17a2c9.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/rwen2012/blog/category/c%D3%EF%D1%D4%CA%B5%BC%F9">c语言实践</a>&nbsp;<a href="http://hi.baidu.com/rwen2012/blog/item/35db04a95e25abf61e17a2c9.html#comment">查看评论</a>]]></description>
        <pubDate>2009-10-19  15:36</pubDate>
        <category><![CDATA[c语言实践]]></category>
        <author><![CDATA[Rwen2012]]></author>
		<guid>http://hi.baidu.com/rwen2012/blog/item/35db04a95e25abf61e17a2c9.html</guid>
</item>

<item>
        <title><![CDATA[srand()/rand()]]></title>
        <link><![CDATA[http://hi.baidu.com/rwen2012/blog/item/3ea0f63593ffd281a61e12ca.html]]></link>
        <description><![CDATA[
		
		#include &lt;stdio.h&gt;<br>
#include &lt;stdlib.h&gt;<br>
#include &lt;time.h&gt;<br>
#include &lt;sys/types.h&gt;<br>
<br>
void rand_init(void){<br>
srand(time(0));<br>
}<br>
<br>
u_int8_t&#160; get_rand8(void){<br>
return(rand() % 256);<br>
}<br>
u_int16_t get_rand16(void){<br>
return(rand() % 65536);<br>
}<br>
u_int32_t get_rand32(void){<br>
return(rand());<br>
}<br>
u_int32_t get_n(u_int32_t n){<br>
return(rand() % n);<br>
} 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/rwen2012/blog/category/c%D3%EF%D1%D4%CA%B5%BC%F9">c语言实践</a>&nbsp;<a href="http://hi.baidu.com/rwen2012/blog/item/3ea0f63593ffd281a61e12ca.html#comment">查看评论</a>]]></description>
        <pubDate>2009-10-12  09:41</pubDate>
        <category><![CDATA[c语言实践]]></category>
        <author><![CDATA[Rwen2012]]></author>
		<guid>http://hi.baidu.com/rwen2012/blog/item/3ea0f63593ffd281a61e12ca.html</guid>
</item>

<item>
        <title><![CDATA[type.h]]></title>
        <link><![CDATA[http://hi.baidu.com/rwen2012/blog/item/4163bb034fb6e782d53f7cf8.html]]></link>
        <description><![CDATA[
		
		#ifndef _TYPES_H_<br>
#define _TYPES_H_<br>
<br>
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))<br>
<br>
typedef unsigned char&#160;&#160;&#160; &#160;&#160;&#160; u8;<br>
typedef unsigned short&#160;&#160;&#160; &#160;&#160;&#160; u16;<br>
typedef unsigned int&#160;&#160;&#160; &#160;&#160;&#160; u32;<br>
typedef unsigned long long&#160;&#160;&#160; u64;<br>
typedef signed char&#160;&#160;&#160; &#160;&#160;&#160; s8;<br>
typedef short&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; s16;<br>
typedef int&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; s32;<br>
typedef long long&#160;&#160;&#160; &#160;&#160;&#160; s64;<br>
<br>
#define min(x,y) ({ \<br>
typeof(x) _x = (x);&#160;&#160;&#160; \<br>
typeof(y) _y = (y);&#160;&#160;&#160; \<br>
(void) (&amp;_x == &amp;_y);&#160;&#160;&#160; \<br>
_x &lt; _y ? _x : _y; })<br>
<br>
#define max(x,y) ({ \<br>
typeof(x) _x = (x);&#160;&#160;&#160; \<br>
typeof(y) _y = (y);&#160;&#160;&#160; \<br>
(void) (&amp;_x == &amp;_y);&#160;&#160;&#160; \<br>
_x &gt; _y ? _x : _y; })<br>
<br>
#endif /* _TYPES_H_ */ <a href="http://hi.baidu.com/rwen2012/blog/item/4163bb034fb6e782d53f7cf8.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/rwen2012/blog/category/c%D3%EF%D1%D4%CA%B5%BC%F9">c语言实践</a>&nbsp;<a href="http://hi.baidu.com/rwen2012/blog/item/4163bb034fb6e782d53f7cf8.html#comment">查看评论</a>]]></description>
        <pubDate>2009-09-30  10:36</pubDate>
        <category><![CDATA[c语言实践]]></category>
        <author><![CDATA[Rwen2012]]></author>
		<guid>http://hi.baidu.com/rwen2012/blog/item/4163bb034fb6e782d53f7cf8.html</guid>
</item>

<item>
        <title><![CDATA[tmpfile]]></title>
        <link><![CDATA[http://hi.baidu.com/rwen2012/blog/item/f9554d46801dad036b63e5cf.html]]></link>
        <description><![CDATA[
		
		ngx_fd_t<br>
ngx_open_tempfile(u_char *name, ngx_uint_t persistent, ngx_uint_t access)<br>
{<br>
ngx_fd_t&#160; fd;<br>
<br>
fd = open((const char *) name, O_CREAT|O_EXCL|O_RDWR,<br>
access ? access : 0600);<br>
<br>
if (fd != -1 &amp;&amp; !persistent) {<br>
unlink((const char *) name);<br>
}<br>
<br>
return fd;<br>
}<br> 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/rwen2012/blog/category/c%D3%EF%D1%D4%CA%B5%BC%F9">c语言实践</a>&nbsp;<a href="http://hi.baidu.com/rwen2012/blog/item/f9554d46801dad036b63e5cf.html#comment">查看评论</a>]]></description>
        <pubDate>2009-09-18  09:54</pubDate>
        <category><![CDATA[c语言实践]]></category>
        <author><![CDATA[Rwen2012]]></author>
		<guid>http://hi.baidu.com/rwen2012/blog/item/f9554d46801dad036b63e5cf.html</guid>
</item>

<item>
        <title><![CDATA[base64 decode/encode from nginx]]></title>
        <link><![CDATA[http://hi.baidu.com/rwen2012/blog/item/7a429600495ddf1b738b65c1.html]]></link>
        <description><![CDATA[
		
		<br>
void<br>
ngx_encode_base64(ngx_str_t *dst, ngx_str_t *src)<br>
{<br>
u_char&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; *d, *s;<br>
size_t&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; len;<br>
static u_char&#160;&#160; basis64[] =<br>
&quot;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/&quot;;<br>
<br>
len = src-&gt;len;<br>
s = src-&gt;data;<br>
d = dst-&gt;data;<br>
<br>
while (len &gt; 2) {<br>
*d++ = basis64[(s[0] &gt;&gt; 2) &amp; 0x3f];<br>
*d++ = basis64[((s[0] &amp; 3) &lt;&lt; 4) | (s[1] &gt;&gt; 4)];<br>
*d++ = basis64[((s[1] &amp; 0x0f) &lt;&lt; 2) | (s[2] &gt;&gt; 6)];<br>
*d++ = basis64[s[2] &amp; 0x3f];<br>
<br>
s += 3;<br>
len -= 3;<br>
}<br>
<br>
if (len) {<br>
*d++ = basis64[(s[0] &gt;&gt; 2) &amp; 0x3f];<br>
<br>
if (len == 1) {<br>
*d++ = basis64[(s[0] &amp; 3) &lt;&lt; 4];<br>
*d++ = '=';<br>
<br>
} else {<br>
*d++ = basis64[((s[0] &amp; 3) &lt;&lt; 4) | (s[1] &gt;&gt; 4)];<br>
*d++ = basis64[(s[1] &amp; 0x0f) &lt;&lt; 2];<br>
}<br>
<br>
*d++ = '=';<br>
}<br>
<br>
dst-&gt;len = d - dst-&gt;data;<br>
}<br>
<br>
<br>
ngx_int_t<br>
ngx_decode_base64(ngx_str_t *dst, ngx_str_t *src)<br>
{<br>
size_t&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; len;<br>
u_char&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; *d, *s;<br>
static u_char&#160;&#160; basis64[] = {<br>
77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,<br>
77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,<br>
77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 62, 77, 77, 77, 63,<br>
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 77, 77, 77, 77, 77, 77,<br>
77,&#160; 0,&#160; 1,&#160; 2,&#160; 3,&#160; 4,&#160; 5,&#160; 6,&#160; 7,&#160; 8,&#160; 9, 10, 11, 12, 13, 14,<br>
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 77, 77, 77, 77, 77,<br>
77, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,<br>
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 77, 77, 77, 77, 77,<br>
<br>
77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,<br>
77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,<br>
77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,<br>
77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,<br>
77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,<br>
77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,<br>
77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,<br>
77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77<br>
};<br>
<br>
for (len = 0; len &lt; src-&gt;len; len++) {<br>
if (src-&gt;data[len] == '=') {<br>
break;<br>
}<br>
<br>
if (basis64[src-&gt;data[len]] == 77) {<br>
return NGX_ERROR;<br>
}<br>
}<br>
<br>
if (len % 4 == 1) {<br>
return NGX_ERROR;<br>
}<br>
<br>
s = src-&gt;data;<br>
d = dst-&gt;data;<br>
<br>
while (len &gt; 3) {<br>
*d++ = (u_char) (basis64[s[0]] &lt;&lt; 2 | basis64[s[1]] &gt;&gt; 4);<br>
*d++ = (u_char) (basis64[s[1]] &lt;&lt; 4 | basis64[s[2]] &gt;&gt; 2);<br>
*d++ = (u_char) (basis64[s[2]] &lt;&lt; 6 | basis64[s[3]]);<br>
<br>
s += 4;<br>
len -= 4;<br>
}<br>
<br>
if (len &gt; 1) {<br>
*d++ = (u_char) (basis64[s[0]] &lt;&lt; 2 | basis64[s[1]] &gt;&gt; 4);<br>
}<br>
<br>
if (len &gt; 2) {<br>
*d++ = (u_char) (basis64[s[1]] &lt;&lt; 4 | basis64[s[2]] &gt;&gt; 2);<br>
}<br>
<br>
dst-&gt;len = d - dst-&gt;data;<br>
<br>
return NGX_OK;<br>
}<br>
<br> <a href="http://hi.baidu.com/rwen2012/blog/item/7a429600495ddf1b738b65c1.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/rwen2012/blog/category/c%D3%EF%D1%D4%CA%B5%BC%F9">c语言实践</a>&nbsp;<a href="http://hi.baidu.com/rwen2012/blog/item/7a429600495ddf1b738b65c1.html#comment">查看评论</a>]]></description>
        <pubDate>2009-09-18  09:46</pubDate>
        <category><![CDATA[c语言实践]]></category>
        <author><![CDATA[Rwen2012]]></author>
		<guid>http://hi.baidu.com/rwen2012/blog/item/7a429600495ddf1b738b65c1.html</guid>
</item>

<item>
        <title><![CDATA[纪念Richard Stevens逝世10周年]]></title>
        <link><![CDATA[http://hi.baidu.com/rwen2012/blog/item/8eadc0447062eb45500ffe27.html]]></link>
        <description><![CDATA[
		
		理查德·史蒂文斯（William Richard (Rich) Stevens，1951年2月5日－1999年9月1日），美国计算机科学家，是众多的畅销UNIX、TCP/IP书籍的作者。 

著作 

* 1990年 - “UNIX Network Programming” - ISBN 0-139-49876-1 中文名：《UNIX网络编程》 
* 1992年 - Advanced Programming in the UNIX Environment - ISBN 0-201-56317-7 中文名：《UNIX环境高级编程》 
* 1994年 - TCP/IP Illustrated, Volume 1: The Protocols - ISBN 0-201-63346-9 中文名：《TCP/IP详解 卷1：协议》 
* 1995年 - TCP/IP Illustrated, Volume 2: The Implementation (with Gary R. Wright) - ISBN 0-201-63354-X 中文名：《TCP/IP详解 卷2：实现》 
* 1996年 - TCP/IP Illustrated, Volume 3: TCP for Transactions, HTTP, NNTP, and the UNIX Domain Protocols - ISBN 0-201-63495-3 中文名：《TCP/IP详解 卷3：事务TCP、HTTP、NNTP和UNIX域套接字协议》 
* 1998年 - UNIX Network Programming, Volume 1, Second Edition: Networking APIs: Sockets and XTI - ISBN 0-134-90012-X 中文名：《UNIX网络编程 卷1》 
* 1999年 - UNIX Network Programming, Volume 2, Second Edition: Interprocess Communications - ISBN 0-130-81081-9 中文名：《UNIX网络编程 卷2》 
 <a href="http://hi.baidu.com/rwen2012/blog/item/8eadc0447062eb45500ffe27.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/rwen2012/blog/category/%CB%E6%B1%CA">随笔</a>&nbsp;<a href="http://hi.baidu.com/rwen2012/blog/item/8eadc0447062eb45500ffe27.html#comment">查看评论</a>]]></description>
        <pubDate>2009-09-05  10:06</pubDate>
        <category><![CDATA[随笔]]></category>
        <author><![CDATA[Rwen2012]]></author>
		<guid>http://hi.baidu.com/rwen2012/blog/item/8eadc0447062eb45500ffe27.html</guid>
</item>

<item>
        <title><![CDATA[读配置文件]]></title>
        <link><![CDATA[http://hi.baidu.com/rwen2012/blog/item/74ba2c6091676a4debf8f899.html]]></link>
        <description><![CDATA[
		
		/* readconfig.c by R.wen(rwen2012@gmail.com), 20090903 */<br>
<br>
/* read file like this: (net-eth0.txt)<br>
<br>
MODE&#160; =&#160; static<br>
IPADDR=192.168.9.159<br>
NETMASK=255.255.255.0<br>
GATEWAY=192.168.9.1<br>
<br>
*/<br>
<br>
#include &lt;stdio.h&gt; <br>
#include &lt;fcntl.h&gt; <br>
#include &lt;sys/stat.h&gt; <br>
#include &lt;sys/types.h&gt;<br>
#include &lt;unistd.h&gt;<br>
#include &lt;stdlib.h&gt;<br>
#include &lt;string.h&gt;<br>
<br>
<br>
int readline(int fd, char *buf)<br>
{<br>
char c;<br>
int n;<br>
<br>
for (;;) {<br>
n = read(fd, &amp;c, 1);<br>
if (n == 1) {<br>
if (c != '\n' &amp;&amp; c !=' ') *buf++ = c;<br>
else if (c == ' ') continue;<br>
else break; /* '\n' */<br>
} else <br>
return 0;<br>
}<br>
<br>
*buf = '\0';&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; <br>
return 1;<br>
}<br>
<br>
<br>
typedef int (*fn_t)(char *name, char *value, void *arg);<br>
int parse(char *buf, fn_t fn, void *arg)<br>
{<br>
char *s;<br>
char *name, *value;&#160;&#160;&#160; <br>
<br>
name = buf;<br>
s = strchr(buf, '=');<br>
if (!s) return -1;<br>
value = s;<br>
<br>
*s = '\0';<br>
value++;<br>
<br>
fn(name, value, arg);<br>
<br>
return 0;<br>
}<br>
<br>
<br>
typedef struct ipconf {<br>
char mode[64];<br>
char ipaddr[64];&#160;&#160;&#160; <br>
char netmask[64];<br>
char gateway[64];<br>
} ipconf_t;<br>
<br>
int getipconf(char *name, char *value, void *arg)<br>
{<br>
//&#160;&#160;&#160; char *name, *value;<br>
int ret;<br>
<br>
ipconf_t *ipc = (ipconf_t *)arg;<br>
<br>
if (!strcmp(&quot;MODE&quot;, name)) {<br>
strcpy(ipc-&gt;mode, value);<br>
} else if (!strcmp(&quot;IPADDR&quot;, name)) {<br>
strcpy(ipc-&gt;ipaddr, value);<br>
} else if (!strcmp(&quot;NETMASK&quot;, name)){<br>
strcpy(ipc-&gt;netmask, value);<br>
} else if (!strcmp(&quot;GATEWAY&quot;, name)) {<br>
strcpy(ipc-&gt;gateway, value);<br>
} else <br>
printf(&quot;not reconigse: name = %s, value = %s\n&quot;, name, value);<br>
<br>
return 0;<br>
}<br>
<br>
<br>
int main(void)<br>
{<br>
int fd;<br>
char buf[512];<br>
ipconf_t ipc;<br>
int ret;<br>
<br>
fd = open(&quot;net-eth0.txt&quot;, O_RDONLY);<br>
<br>
for (;;) {<br>
ret = readline(fd, buf);<br>
if (ret &lt;= 0)<br>
break;<br>
<br>
parse(buf, getipconf, &amp;ipc);<br>
}<br>
<br>
printf(&quot;ipc-&gt;mode: %s\n&quot;, ipc.mode);<br>
printf(&quot;ipc-&gt;ipaddr: %s\n&quot;, ipc.ipaddr);<br>
printf(&quot;ipc-&gt;netmask: %s\n&quot;, ipc.netmask);<br>
printf(&quot;ipc-&gt;gateway: %s\n&quot;, ipc.gateway);<br>
<br>
return 0;<br>
}<br>
<br>
<br>
<br> <a href="http://hi.baidu.com/rwen2012/blog/item/74ba2c6091676a4debf8f899.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/rwen2012/blog/category/c%D3%EF%D1%D4%CA%B5%BC%F9">c语言实践</a>&nbsp;<a href="http://hi.baidu.com/rwen2012/blog/item/74ba2c6091676a4debf8f899.html#comment">查看评论</a>]]></description>
        <pubDate>2009-09-03  17:20</pubDate>
        <category><![CDATA[c语言实践]]></category>
        <author><![CDATA[Rwen2012]]></author>
		<guid>http://hi.baidu.com/rwen2012/blog/item/74ba2c6091676a4debf8f899.html</guid>
</item>

<item>
        <title><![CDATA[UDP编程中的connect(zt)]]></title>
        <link><![CDATA[http://hi.baidu.com/rwen2012/blog/item/523c4bf4f63327e67709d723.html]]></link>
        <description><![CDATA[
		
		标准的udp客户端开了套接口后，一般使用sendto和recvfrom函数来发数据，最近看到ntpclient的代码里面是使用send函数直接法的，就分析了一下，原来udp发送数据有两种方法供大家选用的，顺便把udp的connect用法也就解释清楚了。<br>
方法一： <br>
socket-----&gt;sendto()或recvfrom() <br>
方法二： <br>
socket-----&gt;connect()-----&gt;send()或recv()<br>
<br>
首先从这里看出udp中也是可以使用connect的，但是这两种方法到底有什么区别呢？首先把这四个发送函数的定义列出来： <br>
<font color="#009900">int send(int s, const void *msg, size_t len, int flags); <br>
</font><font color="#009900">int sendto(int s, const void *msg, size_t len, int flags, <br>
const struct sockaddr *to,&#160;socklen_t tolen);<br>
<br>
int recv(int s, void *buf, size_t len, int flags);<br>
</font><font color="#009900">int&#160; recvfrom(int&#160; s, void *buf, size_t len, int flags, <br>
struct sockaddr *from,&#160; socklen_t *fromlen);<br>
<font color="#000000">从他们的定义可以看出，sendto和recvfrom在收发时指定地址，而send和recv则没有，那么他们的地址是在那里指定的呢，答案就在于connect.<br>
</font><font color="#009900">int&#160; connect(int&#160; sockfd,&#160; const&#160; struct sockaddr *serv_addr, socklen_t<br>
addrlen);<br>
<font color="#000000">在udp编程中，如果你只往一个地址发送，那么你可以使用send和recv，在使用它们之前用connect把它们的目的地址指定一下就可以了。connect函数在udp中就是这个作用，</font></font></font><font color="#ff0000">用它来检测udp端口的是否开放是没有用的。</font><font color="#000000">下面是ntpclient中的代码<br>
</font><font color="#009900">struct sockaddr_in sa_dest;<br>
bzero((char *) sa_dest, sizeof(*sa_dest));<br>
sa_dest-&gt;sin_family=AF_INET;<br>
if(StuffNetAddr(&amp;(sa_dest-&gt;sin_addr),host))<br>
return 1;<br>
<br>
sa_dest-&gt;sin_port=htons(port);<br>
<br>
if (connect(usd,(struct sockaddr *)&amp;sa_dest,sizeof(sa_dest))==-1)<br>
{perror(&quot;connect&quot;);return 1;}<br>
<br>
return 0;<br>
<br>
<br>
<br>
=================================<br>
<br>
</font>
<div class="cnt">
<p>除非套接口已连接，否则异步错误是不会返回到UDP套接口的，我们确实可以给UDP套接口调用connect，然而这样做的结果却与TCP连接大相径庭：没有三路握手过程。</p>
<p>相反内核只是检查是否存在立即可知的错误(例如一个显然不可达的目的地)，记录对端的IP地址和端口号（取自传递给connect的套接口地址结构），然后立即返回到调用进程。</p>
<p>对于已连接UDP套接口，与缺省的未连接套接口相比，发生了三个变化：<br>
1 我们再也不能给输出操作指定宿IP和端口号，也就是说我们不使用sendto，而改用write或send，写到已连接UDP套接口上的任何内容都自动发送到由connect指定的协议地址（例如IP地址和端口号）<br>
2 我们不必使用recvfrom以获悉数据报的发送者，而改用read，recv或recvmsg，在一个已连接UDP套接口上由内核为输入操作返回的数据 报仅仅是那些来自connect所指定协议地址的数据报。目的地为这个已连接UDP套接口的本地协议地址，发源地却不是该套接口早先connect到的协 议地址的数据报，不会投递到该套接口。这样就限制了一个已连接UDP套接口而且仅能与一个对端交换数据报。<br>
3 由已连接的UDP套接口引发的异步错误返回给他们所在的进程。<br>
<br>
相反我们说过未连接UDP套接口不接收任何异步错误给一个UDP套接口多次调用connect拥有一个已连接UDP套接口的进程可以为下列2个目的之一：<br>
a.指定新的IP地址和端口号； <br>
b.断开套接口 <br>
<br>
第一个目的（即给一个已连接UDP套接口指定新的对端）不同于TCP套接口中connect的使用:对于TCP套接口，connect只能调用一次。<br>
<br>
为了断开一个已connect的UDP套接口连接，我们再次调用connect时把套接口地址结构的地址簇成员（sin_family）设置为AF_UNSPEC。 <br>
这么做可能返回一个EAFNOSUPPORT错误，不过没有关系。<br>
使得套接口断开连接的是在已连接UDP套接口上调用connect的进程。</p>
</div>
<br>
<br>
=================================<br>
<br>
有如下的一些好处：<br>
1）选定了对端，内核只会将帮定对象的对端发来的数据报传给套接口，因此在一定环境下可以提升安全性；<br>
2)会返回异步错误，如果对端没启动，默认情况下发送的包对应的ICMP回射包不会给调用进程，如果用了connect，嘿嘿<img src="http://img.baidu.com/hi/jx/j_0026.gif"><br>
3）发送两个包间不要先断开再连接，提升了效率。<br>
<br>
<br>
做个实验测试下吧<br>
<br>
先弄个UDP回射服务器，把所有收到的数据报回射回去：<br>
a@a-desktop:~/d/lab$ cat rollbackserver.cpp<br>
#include&lt;iostream&gt;<br>
#include&lt;stdlib.h&gt;<br>
#include&lt;string.h&gt;<br>
#include&lt;unistd.h&gt;<br>
#include&lt;sys/socket.h&gt;<br>
#include&lt;netinet/in.h&gt;<br>
#include&lt;arpa/inet.h&gt;<br>
using namespace std;<br>
int main()<br>
{<br>
int sockListener,nMsgLen;<br>
char szBuf[1024];<br>
struct sockaddr_in addrListener;<br>
socklen_t addrLen;<br>
addrLen=sizeof(struct sockaddr_in);<br>
bzero(&amp;addrListener,sizeof(addrListener));<br>
addrListener.sin_family=AF_INET;<br>
addrListener.sin_port=htons(8000);<br>
<br>
if((sockListener=socket(AF_INET,SOCK_DGRAM,0))==-1)<br>
{<br>
perror(&quot;error in getting a socket&quot;);<br>
exit(1);<br>
}<br>
<br>
if(bind(sockListener,(struct sockaddr*)&amp;addrListener,sizeof(addrListener))==-1)<br>
{<br>
perror(&quot;bind a listener for a socket&quot;);<br>
exit(2);<br>
}<br>
<br>
struct sockaddr_in addrClient;<br>
cout&lt;&lt;&quot;callback server begin to listen&quot;&lt;&lt;endl;<br>
while(true)<br>
{<br>
nMsgLen=recvfrom(sockListener,szBuf,1024,0,(struct sockaddr*)&amp;addrClient,&amp;addrLen);<br>
if(nMsgLen&gt;0)<br>
{<br>
szBuf[nMsgLen]='\0';<br>
cout&lt;&lt;&quot;send back:&quot;&lt;&lt;szBuf&lt;&lt;endl;<br>
sendto(sockListener,szBuf,nMsgLen,0,(struct sockaddr*)&amp;addrClient,addrLen);<br>
}<br>
}<br>
<br>
}<br>
<br>
<br>
再写个客户端，绑定个端口，再连接服务器端。随时接受键盘输入并发送到服务器端，随时接受端口到来的数据并打印。如果没有连接 ，发送到此端口的数据会被接受，但是调用connect后会怎样呢？<br>
a-desktop:~/d/lab$ cat udpclient.cpp<br>
#include&lt;iostream&gt;<br>
#include&lt;stdlib.h&gt;<br>
#include&lt;string.h&gt;<br>
#include&lt;unistd.h&gt;<br>
#include&lt;sys/socket.h&gt;<br>
#include&lt;netinet/in.h&gt;<br>
#include&lt;arpa/inet.h&gt;<br>
#include&lt;sys/select.h&gt;<br>
using namespace std;<br>
int main()<br>
{<br>
int sockClient,nMsgLen,nReady;<br>
char szRecv[1024],szSend[1024],szMsg[1024];<br>
struct sockaddr_in addrServer,addrClient,addrLocal;<br>
socklen_t addrLen;<br>
fd_set setHold,setTest;<br>
<br>
sockClient=socket(AF_INET,SOCK_DGRAM,0);<br>
addrLen=sizeof(struct sockaddr_in);<br>
bzero(&amp;addrServer,sizeof(addrServer));<br>
addrServer.sin_family=AF_INET;<br>
addrServer.sin_addr.s_addr=inet_addr(&quot;127.0.0.1&quot;);<br>
addrServer.sin_port=htons(8000);<br>
<br>
addrLocal.sin_family=AF_INET;//bind to a local port<br>
addrLocal.sin_addr.s_addr=htonl(INADDR_ANY);<br>
addrLocal.sin_port=htons(9000);<br>
if(bind(sockClient,(struct sockaddr*)&amp;addrLocal,sizeof(addrLocal))==-1)<br>
{<br>
perror(&quot;error in binding&quot;);<br>
exit(2);<br>
}<br>
<br>
if(connect(sockClient,(struct sockaddr*)&amp;addrServer,sizeof(addrServer))==-1)<br>
{<br>
perror(&quot;error in connecting&quot;);<br>
exit(1);<br>
}<br>
<br>
FD_ZERO(&amp;setHold);<br>
FD_SET(STDIN_FILENO,&amp;setHold);<br>
FD_SET(sockClient,&amp;setHold);<br>
cout&lt;&lt;&quot;you can type in sentences any time&quot;&lt;&lt;endl;<br>
while(true)<br>
{<br>
setTest=setHold;<br>
nReady=select(sockClient+1,&amp;setTest,NULL,NULL,NULL);<br>
if(FD_ISSET(0,&amp;setTest))<br>
{<br>
nMsgLen=read(0,szMsg,1024);<br>
write(sockClient,szMsg,nMsgLen);<br>
}<br>
if(FD_ISSET(sockClient,&amp;setTest))<br>
{<br>
nMsgLen=read(sockClient,szRecv,1024);<br>
szRecv[nMsgLen]='\0';<br>
cout&lt;&lt;&quot;read:&quot;&lt;&lt;szRecv&lt;&lt;endl;<br>
}<br>
<br>
}<br>
<br>
}<br>
最后来个“第三者”，向第二个的端口发数据报。看她会不会成为忠贞的感情守护人:<br>
a@a-desktop:~/d/lab$ cat clienta.cpp<br>
#include&lt;string.h&gt;<br>
#include&lt;iostream&gt;<br>
#include&lt;stdlib.h&gt;<br>
#include&lt;unistd.h&gt;<br>
#include&lt;sys/socket.h&gt;<br>
#include&lt;netinet/in.h&gt;<br>
#include&lt;arpa/inet.h&gt;<br>
using namespace std;<br>
int main()<br>
{<br>
socklen_t addrLen=sizeof(struct sockaddr_in);<br>
struct sockaddr_in addrServer;<br>
char szMsg[1024];<br>
int sockClient;<br>
<br>
addrServer.sin_family=AF_INET;<br>
addrServer.sin_addr.s_addr=inet_addr(&quot;127.0.0.1&quot;);<br>
addrServer.sin_port=htons(9000);<br>
<br>
sockClient=socket(AF_INET,SOCK_DGRAM,0);<br>
while(true)<br>
{<br>
static int id=0;<br>
snprintf(szMsg,sizeof(szMsg),&quot;this is %d&quot;,id++);<br>
sendto(sockClient,szMsg,strlen(szMsg),0,(struct sockaddr*)&amp;addrServer,sizeof(addrServer));<br>
sleep(1);<br>
}<br>
}<br>
<br>
<br>
<br>
实验结果：<br>
现运行第一个程序，再运行第三个程序，然后运行第二个程序。<br>
服务器端：<br>
<br>
a@a-desktop:~/d/lab$ ./rollback<br>
callback server begin to listen<br>
send back:xinheblue likes playing<br>
<br>
send back:and listenning to music<br>
<br>
<br>
第二个程序：<br>
a@a-desktop:~/d/lab$ ./udpclient<br>
you can type in sentences any time<br>
xinheblue likes playing<br>
read:xinheblue likes playing<br>
<br>
and listenning to music<br>
read:and listenning to music<br>
<br>
<br>
实现结果证明，第二个程序调用connect后，不甩第三个程序发来的数据包。对于感情，希望将来我的她也能这样。。。 <a href="http://hi.baidu.com/rwen2012/blog/item/523c4bf4f63327e67709d723.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/rwen2012/blog/category/Networking">Networking</a>&nbsp;<a href="http://hi.baidu.com/rwen2012/blog/item/523c4bf4f63327e67709d723.html#comment">查看评论</a>]]></description>
        <pubDate>2009-09-03  12:35</pubDate>
        <category><![CDATA[Networking]]></category>
        <author><![CDATA[Rwen2012]]></author>
		<guid>http://hi.baidu.com/rwen2012/blog/item/523c4bf4f63327e67709d723.html</guid>
</item>

<item>
        <title><![CDATA[iptoint  && inttoip]]></title>
        <link><![CDATA[http://hi.baidu.com/rwen2012/blog/item/a781d2cac1304d8fc81768c4.html]]></link>
        <description><![CDATA[
		
		<pre><span ><span class="stx-macro">#include &lt;<a href="http://www.google.com/codesearch/p?hl=zh-CN&amp;sa=N&amp;cd=2&amp;ct=rc#YMpixvTr-Pg&amp;q=file:%28/%7C%5E%29stdio%5C.h$&amp;exact_package=ftp://ftp.mirrorservice.org/sites/ftp.ripe.net/ripe/test-traffic/tracerouteDB.tar&amp;is_navigation=1" class="anav">stdio.h</a>&gt;<br></span></span><span ><span class="stx-macro">#include &lt;<a href="http://www.google.com/codesearch/p?hl=zh-CN&amp;sa=N&amp;cd=2&amp;ct=rc#YMpixvTr-Pg&amp;q=file:%28/%7C%5E%29stdlib%5C.h$&amp;exact_package=ftp://ftp.mirrorservice.org/sites/ftp.ripe.net/ripe/test-traffic/tracerouteDB.tar&amp;is_navigation=1" class="anav">stdlib.h</a>&gt;<br></span></span><span ><span class="stx-macro">#include &lt;<a href="http://www.google.com/codesearch/p?hl=zh-CN&amp;sa=N&amp;cd=2&amp;ct=rc#YMpixvTr-Pg&amp;q=file:%28/%7C%5E%29strings%5C.h$&amp;exact_package=ftp://ftp.mirrorservice.org/sites/ftp.ripe.net/ripe/test-traffic/tracerouteDB.tar&amp;is_navigation=1" class="anav">strings.h</a>&gt;<br></span></span><span ><br></span><span ><span class="stx-macro">#include &lt;<a href="http://www.google.com/codesearch/p?hl=zh-CN&amp;sa=N&amp;cd=2&amp;ct=rc#YMpixvTr-Pg&amp;q=file:%28/%7C%5E%29sys/types%5C.h$&amp;exact_package=ftp://ftp.mirrorservice.org/sites/ftp.ripe.net/ripe/test-traffic/tracerouteDB.tar&amp;is_navigation=1" class="anav">sys/types.h</a>&gt;<br></span></span><span ><span class="stx-macro">#include &lt;<a href="http://www.google.com/codesearch/p?hl=zh-CN&amp;sa=N&amp;cd=2&amp;ct=rc#YMpixvTr-Pg&amp;q=file:%28/%7C%5E%29sys/socket%5C.h$&amp;exact_package=ftp://ftp.mirrorservice.org/sites/ftp.ripe.net/ripe/test-traffic/tracerouteDB.tar&amp;is_navigation=1" class="anav">sys/socket.h</a>&gt;<br></span></span><span ><span class="stx-macro">#include &lt;<a href="http://www.google.com/codesearch/p?hl=zh-CN&amp;sa=N&amp;cd=2&amp;ct=rc#YMpixvTr-Pg&amp;q=file:%28/%7C%5E%29netinet/in%5C.h$&amp;exact_package=ftp://ftp.mirrorservice.org/sites/ftp.ripe.net/ripe/test-traffic/tracerouteDB.tar&amp;is_navigation=1" class="anav">netinet/in.h</a>&gt;<br></span></span><span ><span class="stx-macro">#include &lt;<a href="http://www.google.com/codesearch/p?hl=zh-CN&amp;sa=N&amp;cd=2&amp;ct=rc#YMpixvTr-Pg&amp;q=file:%28/%7C%5E%29arpa/inet%5C.h$&amp;exact_package=ftp://ftp.mirrorservice.org/sites/ftp.ripe.net/ripe/test-traffic/tracerouteDB.tar&amp;is_navigation=1" class="anav">arpa/inet.h</a>&gt;<br></span></span><span ><br></span><span ><br></span><span ><span class="stx-keyword">static</span> <span class="stx-keyword">char</span> <span class="stx-keyword">const</span> rcsid[] = <span class="stx-string">&quot;$Id: rv_<span class="KB">iptoint</span>.c,v 1.2 2004/03/10 18:04:33 wilhelm Exp $&quot;</span>;<br></span><span ><br></span><span ><span class="stx-keyword">unsigned</span> <span class="stx-keyword">int</span> rv_<span class="KB">iptoint</span> (<span class="stx-keyword">char</span> * ipstring) {<br></span><span class="stx-comment"><span >/*       ==============<br></span><span ><br></span><span >   Converts an IP number (e.g. 1.2.3.4) into an 32 unsigned int (&quot;0x01020304&quot;).<br></span><span ><br></span><span >   Input : char * ipstring    String containing the ip number<br></span><span >   Output: unsigned int       IP number as a 32 bit unsigned int.<br></span><span ><br></span><span >   Non-numbers in the input string will be converted to FF.<br></span><span ><br></span><span ><br></span><span >   $Author: wilhelm $<br></span><span >   $Date: 2004/03/10 18:04:33 $<br></span><span >   $Revision: 1.2 $<br></span><span ><br></span></span><span ><span class="stx-comment">*/</span><br></span><span ><br></span><span >   <span class="stx-keyword">unsigned</span> <span class="stx-keyword">int</span> temp;<br></span><span >   <span class="stx-keyword">char</span> buffer[<span class="stx-number">10</span>];<br></span><span >   <span class="stx-keyword">char</span> *point= &amp;buffer[<span class="stx-number">0</span>];<br></span><span >   <span class="stx-keyword">int</span> i;<br></span><span ><br></span><span >   point = strtok ( ipstring, <span class="stx-string">&quot;.&quot;</span> );<br></span><span >   <span class="stx-keyword">if</span> (point == NULL) { <span class="stx-keyword">return</span> <span class="stx-number">0</span>; }<br></span><span ><br></span><span >   <span class="stx-keyword">if</span> (strcmp(point, <span class="stx-string">&quot;??&quot;</span>) == <span class="stx-number">0</span>) {<br></span><span >      temp = <span class="stx-number">0xFF</span>;<br></span><span >   }<br></span><span >   <span class="stx-keyword">else</span> {<br></span><span >      temp = (<span class="stx-keyword">int</span>) strtol (point, (<span class="stx-keyword">char</span>**)NULL, <span class="stx-number">10</span>);<br></span><span >   }<br></span><span ><br></span><span >   <span class="stx-keyword">for</span> (i=<span class="stx-number">0</span> ; i&lt;<span class="stx-number">3</span> ; i++) {<br></span><span >       point = strtok ( NULL, <span class="stx-string">&quot;.&quot;</span> );<br></span><span >       <span class="stx-keyword">if</span> ( (point == NULL) ) {<br></span><span >          <span class="stx-keyword">return</span> <span class="stx-number">0</span>;<br></span><span >       }<br></span><span >       <span class="stx-keyword">else</span> <span class="stx-keyword">if</span> ((strcmp(point, <span class="stx-string">&quot;??&quot;</span>) == <span class="stx-number">0</span>) ) {<br></span><span >          temp = temp*<span class="stx-number">0x100</span> + <span class="stx-number">0xFF</span>;<br></span><span >       }<br></span><span >       <span class="stx-keyword">else</span> {<br></span><span >          temp = temp*<span class="stx-number">0x100</span> + (<span class="stx-keyword">int</span>) strtol (point, (<span class="stx-keyword">char</span>**)NULL, <span class="stx-number">10</span>);<br></span><span >       }<br></span><span >   }<br></span><span ><br></span><span >   <span class="stx-keyword">return</span> temp;<br></span><span >}<br><br><br><br></span><span ><span class="stx-macro">#include &lt;<a href="http://www.google.com/codesearch/p?hl=zh-CN&amp;sa=N&amp;cd=2&amp;ct=rc#YMpixvTr-Pg&amp;q=file:%28/%7C%5E%29stdio%5C.h$&amp;exact_package=ftp://ftp.mirrorservice.org/sites/ftp.ripe.net/ripe/test-traffic/tracerouteDB.tar&amp;is_navigation=1" class="anav">stdio.h</a>&gt;<br></span></span><span ><span class="stx-macro">#include &lt;<a href="http://www.google.com/codesearch/p?hl=zh-CN&amp;sa=N&amp;cd=2&amp;ct=rc#YMpixvTr-Pg&amp;q=file:%28/%7C%5E%29strings%5C.h$&amp;exact_package=ftp://ftp.mirrorservice.org/sites/ftp.ripe.net/ripe/test-traffic/tracerouteDB.tar&amp;is_navigation=1" class="anav">strings.h</a>&gt;<br></span></span><span ><br></span><span ><span class="stx-keyword">static</span> <span class="stx-keyword">char</span> <span class="stx-keyword">const</span> rcsid[] = <span class="stx-string">&quot;$Id: rv_inttoip.c,v 1.1 2002/08/15 23:15:48 ttraffic Exp $&quot;</span>;<br></span><span ><br></span><span ><span class="stx-keyword">char</span>* rv_inttoip (<span class="stx-keyword">unsigned</span> <span class="stx-keyword">int</span> ipno, <span class="stx-keyword">char</span>* point) {<br></span><span class="stx-comment"><span >/*    ============<br></span><span ><br></span><span >   Converts an unsigned int (&quot;0x01020304&quot;) into a standard IP number (1.2.3.4);<br></span><span >   Space for the string must have been alloced in the calling routine.<br></span><span ><br></span><span >   $Author: ttraffic $<br></span><span >   $Date: 2002/08/15 23:15:48 $<br></span><span >   $Revision: 1.1 $<br></span><span ><br></span></span><span ><span class="stx-comment">*/</span><br></span><span >   <span class="stx-keyword">int</span> byte[<span class="stx-number">4</span>], i;<br></span><span ><br></span><span >   <span class="stx-keyword">for</span> (i=<span class="stx-number">0</span> ; i&lt;<span class="stx-number">4</span> ; i++) {<br></span><span >      byte[i] = ipno &amp; <span class="stx-number">0xFF</span>;<br></span><span >      ipno = ipno / <span class="stx-number">0x100</span>;<br></span><span >   }<br></span><span ><br></span><span >   sprintf (point, <span class="stx-string">&quot;%d.%d.%d.%d&quot;</span>, byte[<span class="stx-number">3</span>], byte[<span class="stx-number">2</span>], byte[<span class="stx-number">1</span>], byte[<span class="stx-number">0</span>]);<br></span><span ><br></span><span >   <span class="stx-keyword">return</span> point;<br></span><span >}<br></span></pre> <a href="http://hi.baidu.com/rwen2012/blog/item/a781d2cac1304d8fc81768c4.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/rwen2012/blog/category/c%D3%EF%D1%D4%CA%B5%BC%F9">c语言实践</a>&nbsp;<a href="http://hi.baidu.com/rwen2012/blog/item/a781d2cac1304d8fc81768c4.html#comment">查看评论</a>]]></description>
        <pubDate>2009-09-02  18:00</pubDate>
        <category><![CDATA[c语言实践]]></category>
        <author><![CDATA[Rwen2012]]></author>
		<guid>http://hi.baidu.com/rwen2012/blog/item/a781d2cac1304d8fc81768c4.html</guid>
</item>

<item>
        <title><![CDATA[xor  encryption and decryption]]></title>
        <link><![CDATA[http://hi.baidu.com/rwen2012/blog/item/4c85da16ddf51f58f3de32d3.html]]></link>
        <description><![CDATA[
		
		<pre><span ><span class="stx-comment">/* <span class="KB">Encrypt</span>ion and decryption are symmetric */</span><br></span><span ><span class="stx-macro">#define stream_decrypt stream_<span class="KB">encrypt</span><br></span></span><span ><span class="stx-keyword">static</span> <span class="stx-keyword">void</span> stream_<span class="KB">encrypt</span>(stream_state *self, <span class="stx-keyword">unsigned</span> <span class="stx-keyword">char</span> *block,<br></span><span >                           <span class="stx-keyword">int</span> len)<br></span><span >{<br></span><span >        <span class="stx-keyword">int</span> i, j = self-&gt;last_pos;<br></span><span >        <span class="stx-keyword">for</span>(i=<span class="stx-number">0</span>; i&lt;len; i++, j=(j+<span class="stx-number">1</span>) % self-&gt;keylen)<br></span><span >        {<br></span><span >                block[i] ^= self-&gt;key[j];<br></span><span >        }<br></span><span >        self-&gt;last_pos = j;<br></span><span >}</span><span ><br></span></pre> <a href="http://hi.baidu.com/rwen2012/blog/item/4c85da16ddf51f58f3de32d3.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/rwen2012/blog/category/c%D3%EF%D1%D4%CA%B5%BC%F9">c语言实践</a>&nbsp;<a href="http://hi.baidu.com/rwen2012/blog/item/4c85da16ddf51f58f3de32d3.html#comment">查看评论</a>]]></description>
        <pubDate>2009-08-13  12:50</pubDate>
        <category><![CDATA[c语言实践]]></category>
        <author><![CDATA[Rwen2012]]></author>
		<guid>http://hi.baidu.com/rwen2012/blog/item/4c85da16ddf51f58f3de32d3.html</guid>
</item>

<item>
        <title><![CDATA[xor encryption]]></title>
        <link><![CDATA[http://hi.baidu.com/rwen2012/blog/item/094af41c230c118287d6b6d2.html]]></link>
        <description><![CDATA[
		
		<pre><span class="stx-comment"><span >/**************************************************************<br></span><span class="DD">*     Basic <span class="KB ED">xor</span> <span class="KB">encrypt</span>ion program by spade89 :)              *<br></span><span >*       this code is for everyhuman no copyrights             *<br></span><span >*     feel free to modify or duplicate as much as you want.   *<br></span><span >*                                                             *<br></span><span >***************************************************************<br></span></span><span ><span class="stx-comment">*/</span><br></span><span ><span class="stx-macro">#include&lt;<a href="http://www.google.cn/codesearch/p?hl=zh-CN&amp;sa=N&amp;cd=21&amp;ct=rc#vmQtEsnWaB8&amp;q=file:%28/%7C%5E%29iostream%5C.h$&amp;exact_package=http://www.christiancoders.com&amp;is_navigation=1" class="anav">iostream.h</a>&gt;<br></span></span><span ><span class="stx-macro">#include&lt;<a href="http://www.google.cn/codesearch/p?hl=zh-CN&amp;sa=N&amp;cd=21&amp;ct=rc#vmQtEsnWaB8&amp;q=file:%28/%7C%5E%29conio%5C.h$&amp;exact_package=http://www.christiancoders.com&amp;is_navigation=1" class="anav">conio.h</a>&gt;<br></span></span><span ><span class="stx-macro">#include&lt;<a href="http://www.google.cn/codesearch/p?hl=zh-CN&amp;sa=N&amp;cd=21&amp;ct=rc#vmQtEsnWaB8&amp;q=file:%28/%7C%5E%29stdio%5C.h$&amp;exact_package=http://www.christiancoders.com&amp;is_navigation=1" class="anav">stdio.h</a>&gt;<br></span></span><span ><span class="stx-macro">#include&lt;<a href="http://www.google.cn/codesearch/p?hl=zh-CN&amp;sa=N&amp;cd=21&amp;ct=rc#vmQtEsnWaB8&amp;q=file:%28/%7C%5E%29string%5C.h$&amp;exact_package=http://www.christiancoders.com&amp;is_navigation=1" class="anav">string.h</a>&gt;<br></span></span><span ><span class="stx-keyword">int</span> <span class="KB">encrypt</span>(<span class="stx-keyword">char</span> *,<span class="stx-keyword">char</span> *);<br></span><span ><span class="stx-keyword">int</span> decrypt(<span class="stx-keyword">char</span> *,<span class="stx-keyword">char</span> *);<br></span><span ><span class="stx-keyword">long</span> filesize(FILE *);<br></span><span ><span class="stx-keyword">int</span> main(){<br></span><span >         begining:<br></span><span >        <span class="stx-keyword">unsigned</span> <span class="stx-keyword">char</span> key[<span class="stx-number">128</span>],filename[<span class="stx-number">64</span>];<br></span><span >       textcolor(LIGHTGREEN);<br></span><span >      <span class="stx-comment">//startup:<br></span></span><span >         cprintf(<span class="stx-string">&quot;BASIC <span class="KB">XOR</span> <span class="KB">ENCRYPT</span>ION BY SPADE %c&quot;</span>) ;cout&lt;&lt;endl;<br></span><span >         <span class="stx-keyword">for</span>(<span class="stx-keyword">int</span> i=<span class="stx-number">0</span>;i&lt;<span class="stx-number">80</span>;i++)cprintf(<span class="stx-string">&quot;%c&quot;</span>,<span class="stx-number">6</span>);<br></span><span >       cout&lt;&lt;endl;<br></span><span ><span class="stx-comment">//   synchronize i/o<br></span></span><span >      cin.tie(&amp;cout);<br></span><span >          cout&lt;&lt;<span class="stx-string">&quot;Enter filename:\n&quot;</span>;<br></span><span >  <span class="stx-comment">//get filename<br></span></span><span >        cin&gt;&gt;filename;<br></span><span >           cout&lt;&lt;<span class="stx-string">&quot;Enter key:\n&quot;</span>;<br></span><span >           <span class="stx-comment">//get <span class="KB">encrypt</span>ion decryption key<br></span></span><span >           cin&gt;&gt;key;<br></span><span ><br></span><span >           <span class="stx-keyword">char</span> op;<br></span><span >           cout&lt;&lt;<span class="stx-string">&quot;Enter option&lt;<span class="KB">Encrypt</span>/Decrypt&gt;:\n&quot;</span>;<br></span><span >           <span class="stx-comment">//see what the user wants us to do<br></span></span><span >              op=getch();<br></span><span ><br></span><span >           <span class="stx-keyword">switch</span>(op){<br></span><span ><br></span><span >           <span class="stx-keyword">case</span> <span class="stx-string">'d'</span>:<br></span><span >           <span class="stx-keyword">case</span> <span class="stx-string">'D'</span>:<br></span><span >           decrypt(filename,key);<br></span><span >           <span class="stx-keyword">break</span>;<br></span><span >           <span class="stx-keyword">case</span> <span class="stx-string">'e'</span>:<br></span><span >           <span class="stx-keyword">case</span> <span class="stx-string">'E'</span>:<br></span><span >              <span class="KB">encrypt</span>(filename,key);<br></span><span >              <span class="stx-keyword">default</span>:<br></span><span >              <span class="stx-keyword">break</span>;<br></span><span >              }<br></span><span >              op=getch();<br></span><span >              <span class="stx-comment">//see of tje user still wants to continue, 0x1b is escape key<br></span></span><span >                 <span class="stx-keyword">if</span>(op==<span class="stx-number">0x1b</span>)<span class="stx-keyword">goto</span> end;<br></span><span >                 <span class="stx-keyword">goto</span> begining;<br></span><span >                           end:<br></span><span >                           <span class="stx-keyword">return</span> <span class="stx-number">0</span>;<br></span><span >}<br></span><span class="stx-comment"><span >/*<br></span><span >function filesize<br></span><span >arguments FILE *stream<br></span><span >a file stream object<br></span><span >returns size of the file as long<br></span></span><span ><span class="stx-comment">*/</span><br></span><span ><span class="stx-keyword">long</span> filesize(FILE *stream)<br></span><span >{<br></span><span >   <span class="stx-keyword">long</span> curpos, length;<br></span><span ><br></span><span >   curpos = ftell(stream);<br></span><span >   fseek(stream, <span class="stx-number">0</span>L, SEEK_END);<br></span><span >   length = ftell(stream);<br></span><span >   fseek(stream, curpos, SEEK_SET);<br></span><span >   <span class="stx-keyword">return</span> length;<br></span><span ><br></span><span >}<br></span><span class="stx-comment"><span >/*<br></span><span >function <span class="KB">encrypt</span>:<br></span><span >arguments char *fname,char *key<br></span><span >  fname is filename to be <span class="KB">encrypt</span>ed,key is the <span class="KB">encrypt</span>ion key<br></span><span >returns -1 if file fails to open, 0 if all goes well<br></span><span ><br></span><span ><br></span></span><span ><span class="stx-comment">*/</span><br></span><span ><span class="stx-keyword">int</span> <span class="KB">encrypt</span>(<span class="stx-keyword">char</span> *fname,<span class="stx-keyword">char</span> *key){<br></span><span ><br></span><span >FILE *out;<br></span><span >         <span class="stx-keyword">unsigned</span> <span class="stx-keyword">char</span> *buf;<br></span><span >                         <span class="stx-comment">//open file and check if it exists<br></span></span><span >   <span class="stx-keyword">if</span>((out=fopen(fname,<span class="stx-string">&quot;rb+&quot;</span>))==NULL){textcolor(LIGHTRED);<br></span><span >   cprintf(<span class="stx-string">&quot;error opening file!!! :(&quot;</span>);cout&lt;&lt;endl; <span class="stx-keyword">return</span> -<span class="stx-number">1</span>;}<br></span><span ><span class="stx-comment">//   find the size of our file and convert the result to int<br></span></span><span >   <span class="stx-keyword">int</span> size=(<span class="stx-keyword">int</span>) filesize(out);<br></span><span >   <span class="stx-comment">//make sure we are at begining of file<br></span></span><span >   fseek(out, <span class="stx-number">0</span>L, SEEK_SET);<br></span><span >   <span class="stx-comment">//make a buffer for file data<br></span></span><span >         buf=<span class="stx-keyword">new</span> <span class="stx-keyword">char</span>[size];<br></span><span >                          <span class="stx-comment">//read all the data of the file into buf<br></span></span><span >    <span class="stx-keyword">for</span>(<span class="stx-keyword">int</span> i=<span class="stx-number">0</span>;i&lt;size;i++){<br></span><span >           buf[i]=fgetc(out);<br></span><span ><br></span><span ><br></span><span ><br></span><span >}<br></span><span ><span class="stx-comment">//close our file stream<br></span></span><span >fclose(out);<br></span><span >                <span class="stx-comment">//remove our file from the system<br></span></span><span >remove(fname);<br></span><span >   <span class="stx-comment">//make a new file using our oringinal file name<br></span></span><span >     <span class="stx-keyword">if</span>((out=fopen(fname,<span class="stx-string">&quot;ab+&quot;</span>))==NULL){textcolor(LIGHTRED);<br></span><span >     cprintf(<span class="stx-string">&quot;error opening file!!! :(&quot;</span>);cout&lt;&lt;endl; <span class="stx-keyword">return</span> -<span class="stx-number">1</span>;}<br></span><span ><br></span><span >        <span class="stx-keyword">for</span>(<span class="stx-keyword">int</span> i=<span class="stx-number">0</span>,j=<span class="stx-number">0</span>;i&lt;size;i++,j++){<br></span><span >                          <span class="stx-comment">//when j equals length of the key make j=0<br></span></span><span >                           <span class="stx-keyword">if</span>(j==strlen(key)-<span class="stx-number">1</span>)j=<span class="stx-number">0</span>;<br></span><span >                           <span class="stx-comment">//<span class="KB">xor</span> each value of buf with each value of key<br></span></span><span >                           buf[i]=buf[i]^key[j];<br></span><span >                          <span class="stx-comment">//write the <span class="KB">encrypt</span>ed char's<br></span></span><span >                           fputc(buf[i],out);<br></span><span >                           }<br></span><span >                           textcolor(YELLOW);<br></span><span >                    cprintf(<span class="stx-string">&quot;File <span class="KB">encrypt</span>ed :)&quot;</span>);cout&lt;&lt;endl;<br></span><span >            <span class="stx-keyword">return</span> <span class="stx-number">1</span>;<br></span><span >}<br></span><span class="stx-comment"><span >/*<br></span><span >function decrypt:<br></span><span >arguments char *fname,char *key<br></span><span >  fname is filename to be decrypted,key is the decryption key<br></span><span >returns -1 if file fails to open, 0 if all goes well<br></span><span >                 this function is basically a duplicate of <span class="KB">encrypt</span><br></span><span ><br></span></span><span ><span class="stx-comment">*/</span><br></span><span ><span class="stx-keyword">int</span> decrypt(<span class="stx-keyword">char</span> *fname,<span class="stx-keyword">char</span> *key){<br></span><span >FILE *out;<br></span><span >         <span class="stx-keyword">unsigned</span> <span class="stx-keyword">char</span> *buf;<br></span><span >     <span class="stx-comment">//open file and check if it exists<br></span></span><span >   <span class="stx-keyword">if</span>((out=fopen(fname,<span class="stx-string">&quot;rb+&quot;</span>))==NULL){textcolor(LIGHTRED);cprintf(<span class="stx-string">&quot;error opening file!!! :(&quot;</span>);cout&lt;&lt;endl; <span class="stx-keyword">return</span> -<span class="stx-number">1</span>;}<br></span><span >   <span class="stx-comment">//   find the size of our file and convert the result to int<br></span></span><span >   <span class="stx-keyword">int</span> size=(<span class="stx-keyword">int</span>) filesize(out);<br></span><span >   <span class="stx-comment">//make sure we are at begining of file<br></span></span><span >   fseek(out, <span class="stx-number">0</span>L, SEEK_SET);<br></span><span >         <span class="stx-comment">//make a buffer for file data<br></span></span><span >         buf=<span class="stx-keyword">new</span> <span class="stx-keyword">char</span>[size];<br></span><span >                         <span class="stx-comment">//read all the data of the file into buf<br></span></span><span >    <span class="stx-keyword">for</span>(<span class="stx-keyword">int</span> i=<span class="stx-number">0</span>;i&lt;size;i++){<br></span><span >           buf[i]=fgetc(out);<br></span><span ><br></span><span ><br></span><span ><br></span><span >}<br></span><span ><span class="stx-comment">//close our file stream<br></span></span><span >fclose(out);<br></span><span ><span class="stx-comment">//remove our file from the system<br></span></span><span >remove(fname);<br></span><span >     <span class="stx-comment">//make a new file using our oringinal file name<br></span></span><span >     <span class="stx-keyword">if</span>((out=fopen(fname,<span class="stx-string">&quot;ab+&quot;</span>))==NULL){textcolor(LIGHTRED);<br></span><span >     cprintf(<span class="stx-string">&quot;error opening file!!! :(&quot;</span>);<br></span><span >     cout&lt;&lt;endl;<br></span><span >      <span class="stx-keyword">return</span> -<span class="stx-number">1</span>;}<br></span><span ><br></span><span >        <span class="stx-keyword">for</span>(<span class="stx-keyword">int</span> i=<span class="stx-number">0</span>,j=<span class="stx-number">0</span>;i&lt;size;i++,j++){<br></span><span >                                    <span class="stx-comment">//when j equals length of the key make j=0<br></span></span><span >                           <span class="stx-keyword">if</span>(j==strlen(key)-<span class="stx-number">1</span>)j=<span class="stx-number">0</span>;<br></span><span >                            <span class="stx-comment">//<span class="KB">xor</span> each value of buf with each value of key<br></span></span><span >                           buf[i]=buf[i]^key[j];<br></span><span >                                  <span class="stx-comment">//write the decrypted char's<br></span></span><span >                           fputc(buf[i],out);<br></span><span >                           }<br></span><span >                           textcolor(YELLOW);<br></span><span >                           cprintf(<span class="stx-string">&quot;File decrypted :)&quot;</span>,<span class="stx-number">0x38</span>); cout&lt;&lt;endl;<br></span><span ><span class="stx-keyword">return</span> <span class="stx-number">1</span>;<br></span><span >}<br></span><span ><br></span></pre> <a href="http://hi.baidu.com/rwen2012/blog/item/094af41c230c118287d6b6d2.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/rwen2012/blog/category/c%D3%EF%D1%D4%CA%B5%BC%F9">c语言实践</a>&nbsp;<a href="http://hi.baidu.com/rwen2012/blog/item/094af41c230c118287d6b6d2.html#comment">查看评论</a>]]></description>
        <pubDate>2009-08-13  12:48</pubDate>
        <category><![CDATA[c语言实践]]></category>
        <author><![CDATA[Rwen2012]]></author>
		<guid>http://hi.baidu.com/rwen2012/blog/item/094af41c230c118287d6b6d2.html</guid>
</item>

<item>
        <title><![CDATA[测试循环展开的优化（ARM）]]></title>
        <link><![CDATA[http://hi.baidu.com/rwen2012/blog/item/2dcfb4de84e72f5d95ee3774.html]]></link>
        <description><![CDATA[
		
		/* test the loop unroling, by R.wen */<br>
/* 循环展开可以避免小循环中，由于循环开销所占的比例过大造成的性能下降*/<br>
<br>
#include &lt;stdio.h&gt;<br>
#include &lt;time.h&gt;<br>
<br>
int checksum(int num)<br>
{<br>
int i;<br>
int sum1=0, sum2=0;<br>
<br>
time_t t1, t2;<br>
<br>
t1 = time(NULL);<br>
for (i=num; i&gt;0; i--)<br>
sum1 += i;<br>
<br>
t2 = time(NULL);<br>
t1 = t2 - t1;<br>
{<br>
for (i=num/4; i&gt;0; i--) {<br>
sum2 += i;<br>
sum2 += i+1;&#160;&#160; &#160;&#160; &#160;<br>
sum2 += i+2;<br>
sum2 += i+3;<br>
}<br>
<br>
for (i=num&amp;3; i&gt;0; i--)<br>
sum2 += i;<br>
}<br>
<br>
t2 = time(NULL) - t2;<br>
<br>
printf(&quot;sum1 = %d, time1 = %d, sum2 = %d, time2 = %d\n&quot;, \<br>
sum1, sum2, t1, t2);<br>
<br>
return (sum1 + sum2);<br>
}<br>
<br>
<br>
int main(void)<br>
{<br>
<br>
checksum(100000000);&#160;&#160; /* or use 10, 000, 000 */<br>
<br>
return 0;<br>
<br>
} <a href="http://hi.baidu.com/rwen2012/blog/item/2dcfb4de84e72f5d95ee3774.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/rwen2012/blog/category/c%D3%EF%D1%D4%CA%B5%BC%F9">c语言实践</a>&nbsp;<a href="http://hi.baidu.com/rwen2012/blog/item/2dcfb4de84e72f5d95ee3774.html#comment">查看评论</a>]]></description>
        <pubDate>2009-08-09  10:49</pubDate>
        <category><![CDATA[c语言实践]]></category>
        <author><![CDATA[Rwen2012]]></author>
		<guid>http://hi.baidu.com/rwen2012/blog/item/2dcfb4de84e72f5d95ee3774.html</guid>
</item>


</channel>
</rss>