Sunday, July 29, 2007

关于金盾工程,or GFW,转载+整理

目前很多SMTP服务器发送均出现551 User not local; please try < forward-path >
可能和大规模病毒爆发有关。

实际测试,感觉和IP地址无关,和国家安全防火墙以及邮件内容有关,而且,据了解未必和对方设置有关。

这个问题从2006年开始, 已经多次大面积发生。

国家安全防火墙平时也在扫描,2007年7月16日-17日,不知道怎么回事情,突然国内大面积的的出口邮件都被退回,是被国家安全防火墙在出口位置阻塞。网通电信运营在2007年7月16日上午收到国家安全防火墙的一些通告, 然后, 开始就出现了大量邮件被退回的情况。

估计国家安全防火墙在严查网络出口内容、防火墙新功能测试、 防火墙故障,也有可能是特殊时期的特殊扫描。 这次国家安全防火墙同时扫描客户端软件协议的标准端口,WEB方式和客户端协议有差异, 所以WEB方式问题少一些。

防火墙新功能测试, 因为部分客人反映,最近两天垃圾邮件少了,或根本没有进来。

当碰到这样的问题的时候,我们没有根本的解决办法,唯一能做的就是等待,直到 GFW恢复我们的网络。

几点建议:

1、多发几次, 一般常常也会过去。
2、登陆WEB发送邮件,目前测试WEB出去的邮件退回比较少。

有关GFW 

GFW(防火长城),也称"中国防火墙"或"中国国家防火墙",指中华人民共和国政府在其管辖互联网内部建立的多套网络审查系统的总称,包括金盾系统和相关行政审查系统。一般情况下主要指中国对互联网内容进行自动审查和过滤监控、由计算机与网络设备等软硬件所构成的系统。
其英文名称Great Firewall of China(与长城 Great Wall 相谐的效果),简写为Great Firewall,缩写GFW。随著使用的广泛,GFW已被用于动词,GFWed是指被防火长城所屏蔽。
GFW是"金盾工程"的一个子功能。"金盾工程"是以公安信息网络为先导,以各项公安工作信息化为主要内容,建立统一指挥、快速反应、协同作战机制,在全国范围内开展公安信息化的工程,主要包括建设公安综合业务通信网、公安综合信息系统、全国公安指挥调度系统以及全国公共网络监控中心等。该项目2003年开始生效。一般所说的GFW,主要指公共网络监控系统,尤其是指对境外涉及敏感内容的网站、IP地址、关键词、网址等的过滤。
GFW的效果通常为,国内网络用户无法访问某些国外网站或者网页;或者国外网络用户无法访问国内的某些网站或者网页。这里的无法访问,有永久性的无法访问(比如某些色情网站),也有因为URL中含有敏感关键词或者网页上有敏感内容而暂时性的无法访问。
国家防火墙并非中国的专利。实际上,美国也有国家网络监控系统,对进出美国的每一封电子邮件进行内容扫描。不同的是,中国的国家防火墙会直接切断一些敏感连接,而美国的国家防火墙则只是做数据监控记录。伊朗、巴基斯坦、乌兹别克斯坦、北非共和国、叙利亚、缅甸、马尔代夫、古巴、北韩、南韩、沙特阿拉伯、阿拉伯联合酋长国、也门使用与金盾类似的国家防火墙。

GFW的另类解释
GFW=Google Fire Wall
理由:google.com曾经被**过,并且现在频繁的被**。所以GFW是专门用来fire google的。  

GFW=Google Fans War
理由:这个GFW出来以后虽说**了一大堆网站,但**其他网站的时候都没有闹太大的事,唯独google被**硬起了google fans们极大的愤怒,所以GFW解释为Google Fans War极为贴切。

GFW=Gov. Fuck the World
理由:Gov.把全世界都fuck了。  

GFW对我们生活的影响

◎ 维基百科(Wikipeida)无法正常访问。(最近突然恢复,希望不是妥协)

◎ Google部分功能不能使用(如网页快照)、不能搜索敏感词、有时影响Gmail、Google Group等使用。

◎ 全球最大的博客站 blogspot.com 被屏蔽。

◎ 全球最大的图片站 Flickr 刚刚被屏蔽。(可以上,但全部图片被屏蔽)

◎ 全球最大的电子邮件站 hotmail.com 被变相屏蔽。(可以上,但邮件被屏蔽,经常看不了邮件)

找到GFW的位置

GFW这个东西很早我就已经知道,并且为防止GFW的"骚扰"我已经想过了很多办法来避免了,但由于收到外界机制的影响,仍然不可能完全避过GFW,而最近我所在的公司发到国外的邮件总是受阻,严重影响了公司的正常业务,所以我必须给他们一个非常圆满的答复,才有了找到GFW的位置的想法.

最近我们公司总是有人反应发到日本的邮件会被退回来,我查看了一下退信内容,发现主要有如下内容:

:
xxx.xxx.xxx.xxx does not like recipient.
Remote host said: 551 User not local; please try
Giving up on xxx.xxx.xxx.xxx.
或者:
:
xxx.xxx.xxx.xxx does not like recipient.
Remote host said: 500 error
Giving up on xxx.xxx.xxx.xxx.

而在邮件服务器的日志上发现如下内容:

Sep 26 14:46:23 livedoor qmail: 1159253183.972578 delivery 118310: failure: xxx.xxx.xxx.xxx_does_not_like_recipient./Remote_host_said:_500_error/Giving_up_on_xxx.xxx.xxx.xxx./
由于总报这样的问题,所以我在公司的网关服务器上安装上snort这个入侵检测软件,当然我并没发挥入侵检测的功能,因为我只想要里面的sniff功能探测数据包, 然后等待这种现象的再次来到.当邮件日志里再次出现上面的日志内容的时候,我进入网关服务器查找所有相关这个IP的记录,并且根据时间找到了:

-rw------- 1 root wheel 6941 Sep 26 14:44 TCP:60661-25

现在就请大家跟着我来分析这个文件:
=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
09/26-14:44:52.643691 0:E0:FC:34:C0:86 -> 0:14:22:1F:4A:49 type:0x800 len:0x4E
10.4.1.4:60661 -> 203.131.198.80:25 TCP TTL:127 TOS:0x0 ID:32988 IpLen:20 DgmLen:64 DF
******S* Seq: 0x2E68FF24 Ack: 0x0 Win: 0xFFFF TcpLen: 44
TCP Options (8) => MSS: 1460 NOP WS: 1 NOP NOP TS: 121485349 0
TCP Options => SackOK EOL
=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+

这是我们公司的邮件服务器10.4.1.4向对方发送SYN的请求包,TTL为127,虽然我们的邮件服务器是FreeBSD,但我还是把TTL修改为128了,而邮件服务器和网关服务器之间有一个路由,所以TTL会减1,就成为了127.

=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+

09/26-14:44:52.744474 0:14:22:1F:4A:49 -> 0:11:43:58:71:FF type:0x800 len:0x4A
203.131.198.80:25 -> 10.4.1.4:60661 TCP TTL:49 TOS:0x0 ID:0 IpLen:20 DgmLen:60 DF
***A**S* Seq: 0x1527A9A1 Ack: 0x2E68FF25 Win: 0x16A0 TcpLen: 40
TCP Options (5) => MSS: 1460 SackOK TS: 9713757 121485349 NOP
TCP Options => WS: 0
=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+

这里为对方服务器向我们公司的服务器回复SYN+ACK包.可以看到TTL为49,由于对方也是FreeBSD系统,而FreeBSD的默认TTL值为 64,这样我们可以计算出我们的服务器到对方的服务器经过的路由数,64减49等于15,所以网关服务器到对方服务器经过了15个路由,使用 traceroute命令追踪了一下结果,如下:

gw2# traceroute -n 203.131.198.80
traceroute to 203.131.198.80 (203.131.198.80), 64 hops max, 40 byte packets
1 210.83.214.161 0.722 ms 0.699 ms 0.612 ms
2 210.83.193.49 0.595 ms 0.486 ms 0.615 ms
3 210.52.131.6 16.979 ms 16.978 ms 16.975 ms
4 210.52.130.10 46.711 ms 45.836 ms 45.838 ms
5 210.52.132.230 50.208 ms 49.957 ms 50.085 ms
6 210.53.126.2 50.083 ms 49.955 ms 50.334 ms
7 202.147.16.125 50.583 ms 50.207 ms 50.587 ms
8 202.147.16.205 51.204 ms 50.081 ms 50.209 ms
9 202.147.16.214 103.055 ms 103.050 ms 103.179 ms
10 202.147.0.206 99.803 ms 99.677 ms 99.806 ms
11 203.192.131.250 103.802 ms 103.549 ms 103.430 ms
12 203.174.64.13 99.804 ms 100.053 ms 100.681 ms
13 203.174.64.146 100.056 ms 100.799 ms 102.075 ms
14 203.174.64.214 101.012 ms 99.676 ms 100.179 ms
15 203.131.198.80 100.805 ms 99.926 ms 99.929 ms
gw2#

这里可以很清楚的看到为15跳,充分证明了TTL没有任何问题,而对方的服务器也没有使用防火墙以及NAT来映射25号端口.
=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+

09/26-14:44:52.744633 0:E0:FC:34:C0:86 -> 0:14:22:1F:4A:49 type:0x800 len:0x42
10.4.1.4:60661 -> 203.131.198.80:25 TCP TTL:127 TOS:0x0 ID:33011 IpLen:20 DgmLen:52 DF
***A**** Seq: 0x2E68FF25 Ack: 0x1527A9A2 Win: 0x8218 TcpLen: 32
TCP Options (3) => NOP NOP TS: 121485450 9713757
=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
这里是我们公司返回一个ACK包,这样整个TCP连接的握手成功,接下来就要开始传输数据了.
=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
09/26-14:44:52.845542 0:14:22:1F:4A:49 -> 0:11:43:58:71:FF type:0x800 len:0x93
203.131.198.80:25 -> 10.4.1.4:60661 TCP TTL:49 TOS:0x0 ID:37317 IpLen:20 DgmLen:133 DF
***AP*** Seq: 0x1527A9A2 Ack: 0x2E68FF25 Win: 0x16A0 TcpLen: 32
TCP Options (3) => NOP NOP TS: 9713767 121485450
32 32 30 20 35 61 2D 70 30 37 2D 62 33 2E 64 61 220 5a-p07-b3.da
74 61 2D 68 6F 74 65 6C 2E 6E 65 74 20 46 2D 53 ta-hotel.net F-S
65 63 75 72 65 2F 76 69 72 75 73 67 77 5F 73 6D ecure/virusgw_sm
74 70 2F 32 32 30 2F 35 61 2D 70 30 37 2D 62 33 tp/220/5a-p07-b3
2E 64 61 74 61 2D 68 6F 74 65 6C 2E 6E 65 74 0D .data-hotel.net.
0A .
=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
首先是对方服务器给了我们一个220的服务器信息.
=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
09/26-14:44:52.845826 0:E0:FC:34:C0:86 -> 0:14:22:1F:4A:49 type:0x800 len:0x54
10.4.1.4:60661 -> 203.131.198.80:25 TCP TTL:127 TOS:0x0 ID:33066 IpLen:20 DgmLen:70 DF
***AP*** Seq: 0x2E68FF25 Ack: 0x1527A9F3 Win: 0x8218 TcpLen: 32
TCP Options (3) => NOP NOP TS: 121485551 9713767
48 45 4C 4F 20 6C 69 76 65 64 6F 6F 72 2E 63 6E HELO livedoor.cn
0D 0A ..
=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
我们的服务器给对方发送了一个SMTP协议所需要的HELO信息.由于内容太多中间SMTP协议的握手我就不再详细介绍了 ,所以我这里直接跳到出问题的地方.
=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
09/26-14:44:53.049710 0:E0:FC:34:C0:86 -> 0:14:22:1F:4A:49 type:0x800 len:0x6B
10.4.1.4:60661 -> 203.131.198.80:25 TCP TTL:127 TOS:0x0 ID:33110 IpLen:20 DgmLen:93 DF
***AP*** Seq: 0x2E68FF56 Ack: 0x1527AA19 Win: 0x8218 TcpLen: 32
TCP Options (3) => NOP NOP TS: 121485755 9713787
52 43 50 54 20 54 4F 3A 3C 6A 69 6D 67 72 65 65 RCPT TO:6E 40 6E 65 70 74 75 6E 65 2E 6C 69 76 65 64 6F x_at_neptune.livedo
6F 72 2E 63 6F 6D 3E 0D 0A or.com>..
=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
在这里,当我们的服务器发送RCPT To的信息到对方服务器以后,按照SMTP协议的原理,对方在有这个用户的情况下应该返回250 ok这个信息,但是这个时候问题出现了,我们的服务器马上收到一个如下的信息:
=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
09/26-14:44:53.103763 0:14:22:1F:4A:49 -> 0:11:43:58:71:FF type:0x800 len:0x41
203.131.198.80:25 -> 10.4.1.4:60661 TCP TTL:57 TOS:0x0 ID:64 IpLen:20 DgmLen:51
***AP*** Seq: 0x1527AA19 Ack: 0x2E68FF7F Win: 0x0 TcpLen: 20
35 30 30 20 65 72 72 6F 72 0D 0A 500 error..
=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
500 error的信息,再看看TTL的值,57?对端服务器的TTL由49突然变成了57?理论上来说说不过去,再接着看后面的信息:
=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
09/26-14:44:53.154738 0:14:22:1F:4A:49 -> 0:11:43:58:71:FF type:0x800 len:0x4A
203.131.198.80:25 -> 10.4.1.4:60661 TCP TTL:49 TOS:0x0 ID:37321 IpLen:20 DgmLen:60 DF
***AP*** Seq: 0x1527AA19 Ack: 0x2E68FF7F Win: 0x16A0 TcpLen: 32
TCP Options (3) => NOP NOP TS: 9713798 121485755
32 35 30 20 4F 6B 0D 0A 250 Ok..
=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
这才是真是服务器发送过来的信息,而由于500 error的错误信息比250 Ok的正确信息先到达我们的服务器,所以我们的服务器这个时候就已经认为对方服务器错误,所以按照SMTP协议必须终止邮件的发送,所以这个时候我们的服务器发送:
=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
09/26-14:44:53.155026 0:E0:FC:34:C0:86 -> 0:14:22:1F:4A:49 type:0x800 len:0x48
10.4.1.4:60661 -> 203.131.198.80:25 TCP TTL:127 TOS:0x0 ID:33131 IpLen:20 DgmLen:58 DF
***AP**F Seq: 0x2E68FF7F Ack: 0x1527AA24 Win: 0x8218 TcpLen: 32
TCP Options (3) => NOP NOP TS: 121485860 9713787
51 55 49 54 0D 0A QUIT..
=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
QUIT退出……,就这样一封正常的邮件被活生生的截断了.
现在我们来开始看那个TTL为57的信息,根据我的经验对方的TTL默认值应该是64,所以64减57等于7,也就是说这个阻断我们信息的信号来自和第7个路由同网断或者就是第7个路由.现在再看看我最上面的traceroute的结果:
gw2# traceroute -n 203.131.198.80
traceroute to 203.131.198.80 (203.131.198.80), 64 hops max, 40 byte packets
1 210.83.214.161 0.722 ms 0.699 ms 0.612 ms
2 210.83.193.49 0.595 ms 0.486 ms 0.615 ms
3 210.52.131.6 16.979 ms 16.978 ms 16.975 ms
4 210.52.130.10 46.711 ms 45.836 ms 45.838 ms
5 210.52.132.230 50.208 ms 49.957 ms 50.085 ms
6 210.53.126.2 50.083 ms 49.955 ms 50.334 ms
7 202.147.16.125 50.583 ms 50.207 ms 50.587 ms <――可能发送错误信息的IP
8 202.147.16.205 51.204 ms 50.081 ms 50.209 ms
9 202.147.16.214 103.055 ms 103.050 ms 103.179 ms
10 202.147.0.206 99.803 ms 99.677 ms 99.806 ms
11 203.192.131.250 103.802 ms 103.549 ms 103.430 ms
12 203.174.64.13 99.804 ms 100.053 ms 100.681 ms
13 203.174.64.146 100.056 ms 100.799 ms 102.075 ms
14 203.174.64.214 101.012 ms 99.676 ms 100.179 ms
15 203.131.198.80 100.805 ms 99.926 ms 99.929 ms <――真实服务器的IP
gw2#
使用 http://www.linkwan.com/gb/broadmeter/VisitorInfo/QureyIP.asp 的IP地址查询查到 202.147.16.125 属于澳大利亚,难道澳大利亚在监视我们的网络,想想虽然有这个可能性,但应该不会明显到这个程度.所以我想应该不是这个IP地址,然后我查了查第6跳的 IP地址 210.53.126.2 ,通过查询显示为"中国网通"很明显6和7之间就是中国网通的出口路由,那么GFW就顺理成章安装在 210.53.126.2 这个IP之后.

从上面的分析我们就可以完全的肯定阻断公司邮件正常来往的就是 210.53.126.2 之后的GFW发送的假信息.还好公司的邮件全都是正常的,GFW并不会完全封死,所以过段时间以后会自动恢复.由于发送的邮件非常多,也不一定是同一个服务器,所以不能用VPN来解决,不太现实.当碰到这样的问题的时候我们目前只怕唯一能做的就是等待,直到 GFW恢复我们的网络.

作者:刘宏光
邮件:iceblood_at_163.com
网址:http://www.nettf.net
日期:2006-9-26

这次被盾的太彻底了-By Email

原来blogspot是不能看只能写,现在是写都写不了了……
不能看还能用什么anonymouse之类的东西解决,现在就没办法了,测试一下邮件post的方式能不能正常工作。

btw: 最近好像我们伟大的金盾工程正在做什么测试,被盾的网页明显增加了,邮件好像也经常有问题,如果能的话稍后贴个有关GFW的东西上来。

Friday, July 20, 2007

新赛季看米兰德比需付费zz from sina

这年头,真是走一步路都要花钱……

四川新闻网-成都日报讯:
  再过一个多月,2007-2008赛季意甲联赛就要拉开战幕,而此时一条不太好的消息随之传来:继英超之后,意甲下赛季在中国大陆的转播也将部分进入收费时代。记者近日获悉,天盛传媒欧洲足球频道已经成功购买到意甲未来三个赛季A包转播权,这就意味着,类似“米兰德比”这样的强强对抗从下赛季起将只能在欧洲足球频道播放,中国球迷要想收看最精彩的意甲场次必须像英超一样交费。
  实际上,天盛在购买英超转播权之后已经不止一次表示,接下来还将继续购买意甲等其他欧洲赛事的转播权。不过,在央视一直宣称不放弃意甲的情况下,大多数人并未预料到付费看意甲会这么快成真。据悉,拥有意甲亚洲转播权的MP公司此次将意甲分为A、B、C三个等级打包出售,央视在今年二月拿到了B包转播权,但在A包价格上一直未能谈拢,结果被天盛横刀夺爱。按照三个等级的划分方式,B包只有除AC米兰、国际米兰和尤文图斯三支顶级豪门外的其他球队38轮共60场比赛,而包括三强直接对抗在内的所有最精彩赛事全部属于A包范畴。换句话说,天盛垄断了意甲联赛最佳转播资源。
  天盛购买意甲A包的费用目前没有透露,不过对于购买了欧洲足球频道节目的观众来说,并不会因此另交费用,该频道的收视费用依然为588元/年。据了解,天盛垄断英超转播权以来,由于种种原因,欧洲足球频道用户增长速度并非想象中迅速,此次天盛购买意甲转播权显然也有增强该频道竞争力的因素。
  意甲作为最早进入中国大陆的欧洲联赛,在中国球迷中一直有着巨大的影响和超出其他任何联赛的别样情结,免费意甲时代结束对中国球迷的冲击甚至还在失去英超之上。这一消息传出后,球迷的反应五味杂陈,不过与上次告别免费英超不同,这次球迷的反应中少了很多激愤和谩骂,更多的则是对未来付费电视的思考。对球迷来说,这的确是个无法回避,同时需要更多理智思考的问题。
  新闻追踪
  天盛:暂不考虑买断其他联赛
  或许是出于商业方面的考虑,天盛传媒目前并未明确证实购买意甲A包的消息。天盛CEO宋政在接受采访时表示,暂时不方便对此事进行答复,而该公司副总裁、新闻发言人喻凌霄则只肯定了一件事:天盛暂时没有买断其他联赛转播权的打算。
  宋政坦率表示,目前不方便对意甲的问题发表更多看法,不过他也表示,欧洲足球频道目前虽然以英超为主,但同样会为观众奉献其他联赛的精彩赛事。他对欧洲足球频道的前景表示乐观,认为随着中国大陆观众对付费电视的逐渐接受,该频道的用户会越来越多。
  对于天盛是否进一步买断西甲德甲等联赛在中国大陆的转播权问题,喻凌霄给予了否定回答。他说:“在天盛的工作计划中,暂时没有这方面的内容。德甲、西甲以及法甲等赛事目前在欧洲足球频道中就有转播,欧洲足球频道的内容已经非常全面了。”本报记者肖竹

有关程序中的Magic Number

Magic Number有很多意思了,在code里面,主要是指不使用const声明为常量而直接使用在程序里的数值常量,如:
int a[512]; 中的512
应尽量避免在程序中使用Magic Number。

以下转载自answers.com

Magic numbers in code
The term magic number also refers to the bad programming practice of using numbers directly in source code without explanation. In most cases this makes programs harder to read, understand, and maintain. Although most guides make an exception for the numbers zero and one, it is a good idea to define all other numbers in code as named constants.
For example, to shuffle the values in an array randomly, this pseudocode will do the job:

for i from 1 to 52
j := i + randomInt(53 - i) - 1
a.swapEntries(i, j)

where a is an array object, the function randomInt(x) chooses a random integer between 1 to x, inclusive, and swapEntries(i, j) swaps the ith and jth entries in the array. In this example, 52 is a magic number. It is considered better programming style to write:
constant int deckSize := 52
for i from 1 to deckSize
j := i + randomInt(deckSize + 1 - i) - 1
a.swapEntries(i, j)
This is preferable for several reasons:
It is easier to read and understand. A programmer reading the first example might wonder, What does the number 52 mean here? Why 52? The programmer might infer the meaning after reading the code carefully, but it's not obvious. Magic numbers become particularly confusing when the same number is used for different purposes in one section of code.
It is easier to alter the value of the number, as it is not redundantly duplicated. Changing the value of a magic number is error-prone, because the same value is often used several times in different places within a program. Also, if two semantically distinct variables or numbers have the same value they may be accidentally both edited together. To modify the first example to shuffle a Tarot deck, which has 78 cards, a programmer might naively replace every instance of 52 in the program with 78. This would cause two problems. First, it would miss the value 53 on the second line of the example, which would cause the algorithm to fail in a subtle way. Second, it would likely replace the characters 52 everywhere, regardless of whether they refer to the deck size or to something else entirely, which could introduce bugs. By contrast, changing the value of the deckSize variable in the second example would be a simple, one-line change.
The declarations of "magic number" variables are placed together, usually at the top of a function or file, facilitating their review and change.
It facilitates parameterization. For example, to generalize the above example into a procedure that shuffles a deck of any number of cards, it would be sufficient to turn deckSize into a parameter of that procedure. The first example would require several changes, perhaps:
function shuffle (int deckSize)
for i from 1 to deckSize
j := i + randomInt(deckSize + 1 - i) - 1
a.swapEntries(i, j)
It helps detect typos. Using a variable (instead of a literal) takes advantage of a compiler's checking (if any). Accidentally typing "62" instead of "52" would go undetected, whereas typing "dekSize" instead of "deckSize" would result in the compiler's warning that dekSize is undeclared.
It can reduce typing in some IDEs. If an IDE supports code completion, it will fill in most of the variable's name from the first few letters.
Disadvantages are:
It can increase the line length of the source code, forcing lines to be broken up if many constants are used on the same line.
It can make debugging more difficult, especially on systems where the debugger doesn't display the values of constants.

Allowed use of magic numbers
Although somewhat controversial, most programmers would concede that the use of 0 (zero) and 1 are the only two allowable magic numbers in general code. There are several reasons for this.
Some programming languages begin arrays and lists at index 0, while others begin at index 1
A 0-based array requires a count minus one upper index limit in a loop. For example:
for index := 0 to list.count-1 do
DoSomething(index);
0 equates to false and 1 to true in many programming languages. For this reason these two numbers are considered valid Magic Numbers (although most programmers would argue that the explicit constants TRUE and FALSE should be used instead).
Some languages (notably C and [[C++]]) use 0 to indicate a null pointer constant (although many programmers would argue that the explicit constant NULL should be used instead).

Problems with magic numbers
Because magic numbers are of an arbitrary value, they do not often carry a meaning by themselves; in most cases it is up to the documentation of ones code to specify exactly what the magic number represents. Also, magic numbers are not typesafe, that is, one could erroneously add one to another and arrive at a nonsensical result. Lastly, although highly coincidental, situations arise when numbers may accidentally match magic numbers during comparison operations. It is for these reasons that the use of Enumerated types, or enums, is quickly overtaking the use of magic numbers. Although enums are represented in most languages as a glorified integer (a notable exception is Java)[5], the name of the enum is used rather than the number itself, facilitating programming.

Tuesday, July 17, 2007

一篇文章的关键字-_-b

看TIP的一篇文章,可能是作者没有写关键字,index term这一条写的是:

Index Terms—Author, please supply your own keywords or send a blank e-mail to keywords@ieee.org to receive a list of suggested keywords.

汗啊

Thursday, July 5, 2007

cpu的kernel mode运行模式

就是说,kernel mode一般用于跑系统程序,在这一模式下,cpu对内存等资源有比较高的访问权限。具有而其他普通程序若想使用kernel mode,就必须进行系统调用。当然kernel mode在windows机器上也类似存在,只是windows给user mode的程序提供了更多的权限,见红字部分。以前linux课学过的,都忘了……

Kernel mode, also referred to as system mode, is one of the two distinct modes of operation of the CPU (central processing unit) in Linux. The other is user mode, a non-privileged mode for user programs, that is, for everything other than the kernel.
When the CPU is in kernel mode, it is assumed to be executing trusted software, and thus it can execute any instructions and reference any memory addresses (i.e., locations in memory). The kernel (which is the core of the operating system and has complete control over everything that occurs in the system) is trusted software, but all other programs are considered untrusted software. Thus, all user mode software must request use of the kernel by means of a system call in order to perform privileged instructions, such as process creation or input/output operations.
A system call is a request to the kernel in a Unix-like operating system by an active process for a service performed by the kernel. A process is an executing instance of a program. An active process is a process that is currently advancing in the CPU (while other processes are waiting in memory for their turns to use the CPU). Input/output (I/O) is any program, operation or device that transfers data to or from the CPU and to or from a peripheral device (such as disk drives, keyboards, mice and printers).
The Linux kernel was non-preemptive through Version 2.4. That is, while a process is in kernel mode, it cannot be arbitrarily suspended and replaced by another process (i.e., preempted) for the duration of its time slice (i.e., allocated interval of time in the CPU), in contrast to user mode, except when it voluntarily relinquishes control of the CPU. Processes in kernel mode can, however, be interrupted by an interrupt or an exception.
An interrupt is a signal to the operating system that an event has occurred, and it results in a change in the sequence of instructions that is executed by the CPU. In the case of a hardware interrupt, the signal originates from a hardware device such as a keyboard (i.e., when a user presses a key), mouse or system clock (a circuit that generates pulses at precise intervals that are used to coordinate the computer's activities). A software interrupt is an interrupt that originates in software, and it is usually triggered by a program in user mode. The standard procedure to change from user mode to kernel mode is to call the software interrupt 0x80. An exception is an unusual condition, for example an invalid instruction in a program.
All processes begin execution in user mode, and they switch to kernel mode only when obtaining a service provided by the kernel. This change in mode is termed a mode switch, not to be confused with a context switch (although it sometimes is), which is the switching of the CPU from one process to another.
When a user process runs a portion of the kernel code via a system call, the process temporarily becomes a kernel process and is in kernel mode. While in kernel mode, the process will have root (i.e., administrative) privileges and access to key system resources. The entire kernel, which is not a process but a controller of processes, executes only in kernel mode. When the kernel has satisfied the request by a process, it returns the process to user mode.
Some CPUs, including the nearly ubiquitous x86-compatible (i.e., Intel-compatible) processors, are designed to accommodate more than two execution modes. However, all standard kernels in Unix-like operating systems utilize only kernel mode and user mode.
Some operating systems, such as MS-DOS (the predecessor to the Microsoft Windows operating systems) do not have a distinct kernel mode; rather, they allow user programs to interact directly with the hardware components. However, Unix-like operating systems use the dual mode mechanism to hide all of the low level details regarding the physical organization of the system from application programs launched by the user as a means of assuring system stability and security.
The Linux kernel Version 2.6 (which was introduced in late 2003) is preemptive. That is, a process running in kernel mode can be suspended in order to run a different process. This can be an important benefit for real time applications (i.e., systems which must respond to external events nearly simultaneously).
Unix-like kernels are also reentrant, which means that several processes can be in kernel mode simultaneously. However, on a single-processor system, only one process, regardless of its mode, will be progressing in the CPU at any point in time, and the others will be temporarily blocked until their turns.

Wednesday, July 4, 2007

"你是盗版windows XP的受害者" 解决方法

好久不来了,真不能忍了,blogspot还在被盾中……

最近相当多的windowsXP用户在进行更新的时候都收到了自己的盗版的受害者这样的信息,并且这个烦人的信息在以后的每一次开机都要出现,让我们白白的浪费了很多时间,并且还在屏幕的右下角出现一个星形符号.很多人只有重装系统才能除掉这个讨厌的家伙,不过就算你重装系统,也要关掉自动更新,因为不然它还是会自动安装的啊.如果你关掉自动更新的话,那你的系统同样处于一种危险的境地.毕竟有时候微软公司的更新是一些系统补丁,这是我们不可缺少的东东.
有没有一种办法,不重装系统就能避免出现盗版受害者的提示呢?答案当然是有的,下面我就教大家一个办法吧.
在系统盘(我的系统装在C盘),当然大多数的朋友都装在C盘,在C盘找到文件WINDOWS.打开这个文件,再找到SYSTEM32,双击打开,在这个文件里找到wgalogon.dll和wgatray.exe这两个文件,将这两个文件后面的尾缀.exe统统改成.old.然后重启动电脑,你会发现那个讨人厌的东东再也不见踪影了.

如果有朋友在重命名的时候出现在了以下提示"程序正在被另一个人使用,不能重命名"之类的提示,请按下面的步骤进行:
1.重启动电脑,在启动的过程中按住F8.
2.在windows启动项中选择"进入安全模式下启动".
3.进入了windows之后,再按上面说的做法去做.(这样做的目的只让windows启动时只启动少量必要的程序,而像上面提到的两个程序就不会被启动,这样的话,各位就可以放手的去改动了,而不会受到任何影响了.)