﻿
<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[程序之美]]></title> 
<link>http://narmy.cn/linux/index.php</link> 
<description><![CDATA[__________高万龙的博客  博客已转移至http://narmy.cn/blog]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[程序之美]]></copyright>

<item>
<link>http://narmy.cn/linux/read.php/129.htm</link>
<title><![CDATA[马屁股和航天飞机的关系]]></title> 
<author>lengyuex &lt;lengyuex@gmail.com&gt;</author>
<category><![CDATA[有用的 &#124;&#124; 有趣的]]></category>
<pubDate>Tue, 11 May 2010 02:32:27 +0000</pubDate> 
<guid>http://narmy.cn/linux/read.php/129.htm</guid> 
<description>
<![CDATA[ 
	马屁股和航天飞机的关系<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;美国铁路两条铁轨之间的标准距离是四点八五英尺。这是一个很奇怪的标准，<br/>究竟从何而来的？ <br/>　　原来这是英国的铁路标准，因为美国的铁路最早是由英国人设计建造的。那么，为<br/>什么英国人用这个标准呢？<br/><br/>　　原来英国的铁路是由建电车轨道的人设计的，而这个四点八五英尺正是电车所用的<br/>标准。电车轨标准又是从哪里来的呢？<br/><br/>　　原来最先造电车的人以前是造马车的。而他们是用马车的轮宽做标准。好了，那<br/>么，马车为什么要用这个一定的轮距离标准呢？<br/><br/>　　因为如果那时候的马车用任何其它轮距的话，马车的轮子很快会在英国的老路上撞<br/>坏的。为什么？<br/><br/>　　因为这些路上的辙迹的宽度为四点八五英尺。这些辙迹又是从何而来呢？<br/><br/>　　答案是古罗马人定的，四点八五英尺正是罗马战车的宽度。如果任何人用不同的轮<br/>宽在这些路上行车的话，他的轮子的寿命都不会长。我们再问：罗马人为什么用四点八<br/>五英尺为战车的轮距宽度呢？<br/><br/>　　原因很简单，这是两匹拉战车的马的屁股的宽度。故事到此应该完结了，但事实上<br/>还没有完。<br/><br/>　　下次你在电视上看到美国航天飞机立在发射台上的雄姿时，你留意看，在它的燃料<br/>箱的两旁有两个火箭推进器，这些推进器是由设在犹他州的工厂所提供的。如果可能的<br/>话，这家工厂的工程师希望把这些推进器造得再胖一些，这样容量就会大一些，但是他<br/>们不可以，为什么？<br/><br/>　　因为这些推进器造好后要用火车从工厂运到发射点，路上要通过一些隧道，而这些<br/>隧道的宽度只比火车轨道的宽度宽了一点点。<br/><br/>　　故事是颇有趣的。从一定意义上说，今天世界上最先进的运输系统的设计，或许是<br/>由两千年前两匹战马的屁股宽度来决定的。历史惯性的力量是多么的强大，要冲破由惯<br/>性形成的规则又是多么的艰难。<br/>
]]>
</description>
</item>
<item>
<link>http://narmy.cn/linux/read.php/128.htm</link>
<title><![CDATA[有的女生就像Windows 虽然很优秀，但是安全隐患太大。有的女生就像UNIX 她条件很好，然而不是谁都能玩的起]]></title> 
<author>lengyuex &lt;lengyuex@gmail.com&gt;</author>
<category><![CDATA[有用的 &#124;&#124; 有趣的]]></category>
<pubDate>Tue, 04 May 2010 13:48:02 +0000</pubDate> 
<guid>http://narmy.cn/linux/read.php/128.htm</guid> 
<description>
<![CDATA[ 
	笑话一：爱情观 <br/>　　爱情就是死循环，一旦执行就陷进去了。 <br/>　　爱上一个人，就是内存泄漏--你永远释放不了。 <br/>　　真正爱上一个人的时候，那就是常量限定，永远不会改变。 <br/>　　女朋友就是私有变量，只有我这个类才能调用。 <br/>　　情人就是指针用的时候一定要注意，要不然就带来巨大的灾难。 <br/><br/>笑话二：女人篇 <br/>　　有的女人就是Windows虽然很优秀，但是安全隐患太大。 <br/>　　有的女人就是MFC她条件很好，然而不是谁都能玩的起。 <br/>　　有的女人就是C#长的很漂亮，但是家务活不行。 <br/>　　有的女人就是C++,她会默默的为你做很多的事情。 <br/>　有的女人就是汇编虽然很麻烦，但是有的时候还得求它。 <br/>　　有的女人就是SQL，她会为你的发展带来莫大的帮助。 <br/><br/>笑话三：程序员喝酒 <br/>　　大家喝的是啤酒。这时你入座了。 <br/>　　你给自己倒了杯可乐，这叫低配置。 <br/>　　你给自已倒了杯啤酒，这叫标准配置。 <br/>　　你给自己倒了杯茶水，这茶的颜色还跟啤酒一样，这叫木马。 <br/>　　你给自己倒了杯可乐，还滴了几滴醋，不仅颜色跟啤酒一样，而且不冒热气还有泡泡，这叫超级木马。 <br/>　　你的同事给你倒了杯白酒，这叫推荐配置。 <br/><br/>人到齐了，酒席开始了。 <br/>　　你先一个人喝了一小口，这叫单元测试。 <br/>你跟旁边的人说哥们咱们随意，这叫交叉测试。 <br/>　但是他说不行，这杯要干了，这叫压力测试。 <br/>　　于是你说那就大家一起来吧，这叫内部测试。 <br/>　　这个时候boss向全场举杯了，这叫公开测试。 <br/><br/>菜过三巡，你就不跟他们客气了。 <br/>　　你向对面的人敬酒，这叫p2p. <br/>　　你向对面的人敬酒，他回敬你，你又再敬他...这叫tcp. <br/>　　你向一桌人挨个敬酒，这叫令牌环。 <br/>　　你说只要是兄弟就干了这杯，这叫广播。 <br/>　　可是你的上司jj听了不高兴了，只有兄弟么，罚酒三杯。这叫炸弹。 <br/>　　可是你的下级mm听了不高兴了，我喝一口，你喝一杯，这叫恶意攻击。 <br/>　　有一个人过来向这桌敬酒，你说不行你先过了我这关，这叫防火墙。 <br/>　　你的小弟们过来敬你酒，这叫一对多。 <br/>　　你是boss，所有人过来敬你酒，这叫服务器。 <br/><br/>酒是一样的，可是喝法是不同的。 <br/>　　你喝了一杯，boss喝了一口，这叫c#。 <br/>　　你喝了一杯，mm喝了一口，这叫vb。 <br/>　　你喝了一杯，你大哥喝了半杯，这叫c++。 <br/>　　你喝了半杯，你小弟喝了一杯，这叫汇编。 <br/>　　你喝了一杯，你的搭档也喝了一杯，这叫c。 <br/><br/>酒是一样的，可是喝酒的人是不同的。 <br/>你越喝脸越红，这叫频繁分配释放资源。 <br/>　　你越喝脸越白，这叫资源不释放。 <br/>　　你已经醉了，却说我还能喝，叫做资源额度不足。 <br/>　　你明明能喝，却说我已经醉了，叫做资源保留。 <br/>　　你喝一段时间就上厕所，这叫cache。 <br/><br/>酒过三巡，你也该活动活动了。 <br/>　　你一桌一桌的走，这叫轮巡。 <br/>　　你突然看到某一桌的漂亮mm，走了过去，这叫优先级。 <br/>　　你去了坐下来就不打算走了，这叫死循环。 <br/>　　你的老大举杯邀你过去，你只好过去，这叫启动事件。 <br/>　　你向一桌敬酒，他们说不行不行我们都喝白的，于是你也喝白的，这叫本地化。 <br/>　　你向boss敬酒，可是boss被围了起来，你只能站在外圈，这叫排队。 <br/>　　你终于到了内圈，小心翼翼的向前一步，这叫访问临界区。 <br/>　　你拍着boss的肩膀说哥们咱们喝一杯，这叫越界。 <br/>　　你不知喝了几圈了，只会说两个字，干了，这叫udp。 <br/>　　可是还有人拿着酒瓶跑过来说，刚才都没跟你喝，这叫丢包。 <br/><br/>喝酒喝到最后的结果都一样。 <br/>　　你突然跑向厕所，这叫捕获异常。 <br/>　　你在厕所吐了，反而觉得状态不错，这叫清空内存。 <br/>　　你在台面上吐了，觉得很惭愧，这叫程序异常。 <br/>　　你在boss面前吐了，觉得很害怕，这叫系统崩溃。 <br/>　　你吐到了boss身上，只能索性晕倒了，这叫硬件休克。 <br/><br/>笑话四：大腕篇 <br/>写就要写最难懂的程序， <br/>　　用记事本做编辑器， <br/>　　编译就得用最难用的编译器， <br/>　　程序不带半点注释， <br/>　　程序里面至少要有三个类， <br/>　什么多继承呀, 多线程呀，template呀，inline呀， <br/>　　能给他用的全给他用上 一行里面有while有++有?:有goto， <br/>　　文章里面一定要搬出一个XX哥， <br/>　　用很随意的语气，关系特好的样子， <br/>　　如果自己出书 ，甭管是什么语言 一开头都打印“hello world! ” <br/>　　一副专业人士的派头(儿)， <br/>　　倍(儿)有感觉， <br/>　　编程中场再去冲杯咖啡， <br/>　　咖啡要雀巢的， <br/>　　一个程序最多也就一两个小时就搞定， <br/>　　最后再来句“最近感冒了，哎～” <br/>　　就一个字(儿)——酷！ <br/><br/>用下你写的程序就得要跟七八十个参数， <br/>　　同行的人不是用C就是用汇编， <br/>　　你要是用VB， <br/>　　你都不好意思跟人家打招呼。 <br/><br/>你说这样的高手，一个月得拿多少钱？ <br/>　　我觉得怎么着也得两千吧？ <br/>　　两千 那是老板！ <br/>　　五百封顶！ <br/>　　你别嫌少，还是日元。 <br/>　　你得理解老板的处境， <br/>　　本来公司就经营的惨不忍睹， <br/>　　根本不会再多给你一分钱。 <br/><br/>什么叫编程高手，你知道吗？ <br/>　编程高手就是写什么程序， <br/>　　都写最难的，不写最好的。 <br/>　所以，我们编程菜鸟的口号(儿)就是—— <br/>　　不求好用，但求难懂！<br/><br/> <br/><br/> <br/><br/> <br/><br/> <br/><br/> <br/><br/> <br/><br/> <br/><br/> <br/><br/> <br/><br/>一个高级程序员编的追女孩子的程序<br/><br/> <br/><br/>#define AND &&<br/><br/> <br/><br/>RESULT love(boy, girl)<br/><br/> <br/><br/>&#123; <br/>　　if( boy.有房() AND boy.有车() ) <br/>　　&#123; <br/>　　　boy.Set(Nothing); <br/>　　　return girl.嫁给(boy); <br/>　　&#125; <br/>　　else if( girl.愿意等() ) <br/>　　&#123; <br/>　　　next_year: <br/>　　　for( day=1; day<=365; day++) <br/>　　　&#123; <br/>　　　　if( day == 情人节 ) <br/>　　　　　if( boy.GiveGirl(玫瑰) ) <br/>　　　　　　girl.感情++; <br/>　　　　　else <br/>　　　　　　girl.感情--; <br/>　　　　if( day == girl.生日) <br/>　　　　　if( boy.GiveGirl(玫瑰) ) <br/>　　　　　　girl.感情++; <br/>　　　　　else <br/>　　　　　　girl.感情--; <br/>　　　　boy.拼命赚钱(); <br/>　　　&#125; <br/>　　　年龄++; <br/>　　　girl.感情--; <br/>　　　if( boy.有房() AND boy.有车() ) <br/>　　　&#123; <br/>　　　　boy.Set(Nothing); <br/>　　　　return girl.嫁给(boy); <br/>　　　&#125; <br/>　　　else if( boy.赚钱 > 100,000 AND girl.感情 > 8 ) <br/>　　　　goto next_year; <br/>　　　else <br/>　　　　return girl.goto( another_boy); <br/>　　&#125; <br/>　　return girl.goto( another_boy);<br/><br/><br/><br/><br/>程序员之男女：<br/>　程序员就象男人，语言就象女人。每个男人都想要很多女人，却很少有男人能真正了解女人，因为男人总是朝三暮四，而女人每天都在变，甚至有些是经过变性和美容的。<br/><br/>我们都笑了：<br/>　Borland说我很有前途，Sun笑了；Sun说我很有钱，IBM笑了；IBM说我很专业，Sybase笑了；Sybase说我数据库很牛，Oracle笑了；Oracle说我是开放的，Linux笑了；Linux说我要打败Unix，微软笑了；微软说我的系统很稳定，我们都笑了。 <br/><br/>语言与汽车：<br/>　Delphi就象吉普车，什么路上都能开，却在什么路上也开不好；PB就象卡丁车，只能在固定线路上开，到了室外就有些不稳了；VC就象是跑车，你开得起却买不起，而且一旦发生故障，想修都找不到毛病在哪；Java就象敞棚车，不管刮风下雨，还是艳阳高照，都能照开不误；VB就是摩托车了，骑的时间越长，你越痛恨它！ <br/><br/>程序员的理想：<br/>　天下语言剩一庙，晚上加班M M 抱； <br/>　部门经理都死掉，全部奖金一人要。 <br/><br/>程序员的放弃：<br/>　为了发展，放弃金钱；为了金钱，放弃美女；为了美女，放弃自由；为了自由，放弃一切。 <br/><br/>几个年龄段的程序员：<br/>　20岁的程序员没实力，30岁的程序员会做PPT，40岁的程序员有实力没魅力，50岁的程序员只有资历，60岁的程序员抱着孙子说这就是IT，70岁的程序员躺着病床上用电脑给自己算命。 <br/><br/>程序员恋爱篇：<br/>　单位的，没胆量（怕被别人发现）；介绍的，没商量（要钱要房）；网上的，见死光（全是恐龙）。 <br/><br/>程序员四大悲：<br/>　请假遇减薪，辞职逢生病，升迁遇倒闭，出差在外地。&nbsp;&nbsp;<br/><br/> <br/><br/> <br/><br/> <br/><br/>讽刺与幽默：<br/><br/> <br/><br/>　　中国电信招聘程序员，程序员A、B、C前去面试。考官问他们程序出错的经历及如何对付时间这种数据。　 <br/><br/>　　A：我编过数万行程序，从来没出过错。我很细心，将时间精确到毫秒没任何问题。　 <br/><br/>　　B：程序出错在所难免，但我特别擅长在最短时间内将错误找出来并将其纠正。用四舍五入将时间精确到秒就足够了，精度太高影响运算速度。　 <br/><br/>　　C：迄今为止，我编的程序只出过一种错误：运算结果总是比正确结果大一些。至于时间，学过计算机的人都知道，计算机用二进制进行计算，而时间是六十进制，所以，处理时间这种数据有技术难点。我认为可用近似取值将问题简化，比如一分钟三十秒，就近似为三分钟这种可以被六十整除的数。　 <br/><br/>　　结果，程序员C被录用了。<br/><br/> 
]]>
</description>
</item>
<item>
<link>http://narmy.cn/linux/read.php/121.htm</link>
<title><![CDATA[转载:真正的编程高手-----激励计算机专业的大学生]]></title> 
<author>lengyuex &lt;lengyuex@gmail.com&gt;</author>
<category><![CDATA[有用的 &#124;&#124; 有趣的]]></category>
<pubDate>Wed, 07 Apr 2010 07:46:40 +0000</pubDate> 
<guid>http://narmy.cn/linux/read.php/121.htm</guid> 
<description>
<![CDATA[ 
	Bill Joy<br/><br/><br/>前任Sun的首席科学家，当年在Berkeley时主持开发了最早版本的BSD。他还是vi和csh的作者。当然，Csh Programming Considered Harmful 是另一个话题乐。据说他想看看自己能不能写个操作系统，就在三天里写了个自己的Unix, 也就是BSD的前身。当然是传说了，但足见他的功力。另一个传说是，1980年初的时候，DARPA让BBN在Berkley Unix里加上BBN开发的TCP/IP代码。但当时还是研究生的B伯伯怒了，拒绝把BBN TCP/IP加入BSD，因为他觉得BBN的TCP/IP写得不好。于是B伯伯出手了，端的是一箭封喉，很快就写出了高性能的伯克利版TCP/IP。当时BBN和DARPA签了巨额合同开发TCP/IP Stack，谁知他们的代码还不如一个研究生的好。于是他们开会。只见当时B伯伯穿个T-shirt出现在会议室(当时穿T-shirt不象现在，还是相当散漫的哈)。只见BBN问：你怎么写出来的？而B伯伯答：简单，你读协议，然后编程就行了。最令偶晕倒的是，B伯伯硕士毕业后决定到工业界发展，于是就到了当时只有一间办公室的Sun, 然后他就把Sparc设计出来乐... 象这种软硬通吃的牛人，想不佩服都不行的说。据Bill Joy的同事说，一般开会的时候B伯伯总是拿一堆杂志漫不经心地读。但往往在关键之处，B伯伯发言，直切要害，提出漂亮的构想，让同事们彻底崩溃。对了，他还是Java Spec和JINI的主要作者之一。<br/><br/>John Carmack<br/><br/><br/>ID Software的founder和Lead Programmer。上个月和一个搞图形的师兄聊天，他竟然不知道John Carmack, 也让偶大大地晕了一把。不过也许搞研究的和搞实战的多少有些隔吧。想必喜欢第一人称射击游戏的都知道J哥哥。90年代初只要能在PC上搞个小动画都能让人惊叹一番的时候，J哥哥就推出了石破天惊的Castle Wolfstein, 然后再接再励，doom, doomII, Quake...每次都把3-D技术推到极致。J哥哥的简历上说自己的专长是"Exhaust 3-D technology"，真是牛人之言不我欺的说。做J哥哥这样的人是很幸福的，因为各大图形卡厂家一有了新产品就要向他“进贡”，不然如果他的游戏不支持哪种卡，哪种卡基本就会夭折乐。当初MS的Direct3D也得听取他的意见，修改了不少API。当然，J哥哥在结婚前十数年如一日地每天编程14小时以上，也是偶们凡人望尘莫及的。对了，J哥哥高中肆业(?!)，可以说是自学成才。不过呢，谁要用这个例子来为自己学习不好辩护，就大错特错了。那Leonardo Da Vinci还是自学成才呢(人是私生子，不能上学)。普通人和天才还是有区别的。对了，其实偶们叫“达分奇”是相当不对的，因为Vinci是地名，而Da Vinci就是从Vinci来的人的意思。换句话说，Leonardo Da Vinci就是“从Vinci来的Leonardo”的意思。叫别人“Da Vinci”就不知所谓乐。嗯，扯远了，打住。<br/><br/>David Cutler<br/><br/><br/>VMS和Windows NT的首席设计师，去微软前号称硅谷最牛的kernel开发员。当初他和他的手下在微软一周内把一个具备基本功能的bootable kernel写出来，然后说："who can't write an OS in a week?"，也是牛气冲天的说。顺便说一句，D爷爷到NT3.5时，管理1500名开发员，自己还兼做设计和编程，不改coder本色啊。D爷爷天生脾气火爆，和人争论时喜欢双手猛击桌子以壮声势。:-) 日常交谈F-word不离口。他面试秘书时必问："what do you think of the word 'FUCK'?"，让无数美女刹羽而归。终于有一天，一个同样火爆的女面对这个问题脱口而出："That's my favorite word"。于是她被录取乐，为D爷爷工作到NT3.5发布。<br/><br/>Donald E. Knuth<br/><br/><br/>高爷爷其实用不着偶多说。学编程的不知道他就好像学物理的不知道牛顿，学数学的不知道欧拉，学音乐的不知道莫扎特，学Delphi的不知到Anders Hejlsberg，或者学Linux不知道Linus Torvalds一样，不可原谅啊。:-) 为了让文章完整，就再罗唆几句吧。高爷爷本科时就开始给行行色色的公司写各种稀奇古怪的编译器挣外快了。他卖给别人时收一两千美元，那些公司拿了code，加工一下卖出去就是上万上十万。不过也没见高爷爷不爽过，学者本色的说。想想那可是60年代初啊，高爷爷写编译器写多了，顺带就搞出了个Attribute Grammar和LR(k)，大大地造福后人啊。至于高爷爷在CalTech的编程比赛(有Alan Kay得众多高高手参加)总是第一，写的Tex到86年就code freeze，还附带2^n美分奖励等等都是耳熟能详，偶就不饶舌乐。顺便说一下，高老大爷是无可争议的写作高手。他给Concrete Mathematics写的前言可谓字字铿锵，堪为前言的典范。他的技术文章也是一绝，文风细致，解释精当，而且没有学究气，不失轻快跳脱。记得几年前读Concrete Mathematics，时不时开怀大笑，让老妈极其郁闷，觉得我nerdy到家，不可救药。其实呢，子非鱼，安知鱼之乐，更不知那完全是高爷爷的功劳。说到写作高手，不能不提Stephen A. Cook。他的文章当年就被我们的写作老师极力推荐，号称典雅文风的样本。库爷爷一头银发，身材颀长，总是面带谦和的微笑，颇有仙风道骨，正好和他的仙文相配的说。高爷爷其实还是开源运动的先驱。虽然他没有象Richard Stallman那样八方奔走，但他捐献了好多作品，都可以在网上看到，比如著名的Mathematical Writing，MMIXWare，The Tex Book等，更不用说足以让他流芳百世的Tex乐。<br/><br/>Ken Thompson<br/><br/><br/>C语言前身B语言的作者，Unix的发明人之一(另一个是Dennis M. Riche老大，被尊为DMR)，Belle(一个厉害的国际象棋程序)的作者之一，操作系统Plan 9的主要作者(另一个是大牛人Rob Pike, 前不久被google挖走了)。Ken爷爷也算是计算机历史上开天辟地的人物了。1969年还是计算机史前时代，普通人都认为只有大型机才能运行通用的操作系统，小型机只有高山仰止的份儿。至于用高级语言来写操作系统，更是笑谈。Ken爷爷自然不是池中物，于是他和DMR怒了，在1969年到1970间用汇编在PDP-7上写出了UNIX的第一个版本。他们并不知道，一场轰轰烈烈的UNIX传奇由此拉开了序幕。Ken爷爷在1971年又把Unix用C重写，于是C在随后20年成就了不知多少豪杰的梦想和光荣。Ken爷爷还有段佳话：装了UNIX的PDP-11最早被安装在Bell Lab里供大家日常使用。很快大家就发现Ken爷爷总能进入他们的帐户，获得最高权限。Bell Lab里的科学家都心比天高，当然被搞得郁闷无比。于是有高手怒了，跳出来分析了UNIX代码，找到后门，修改代码，然后重新编译了整个UNIX。就在大家都以为“这个世界清净了”的时候，他们发现Ken爷爷还是轻而易举地拿到他们的帐户权限，百思不解后，只好继续郁闷。谁知道这一郁闷，就郁闷了14年，直到Ken爷爷道出个中缘由。原来，代码里的确有后门，但后门不在Unix代码里，而在编译Unix代码的C编译器里。每次C编译器编译UNIX的代码，就自动生成后门代码。而整个Bell Lab的人，都是用Ken爷爷的C编译器。<br/><br/>Rob Pike<br/><br/><br/>AT&T Bell Lab前Member of Technical Staff，现在google研究操作系统。罗伯伯是Unix的先驱，是贝尔实验室最早和Ken Thompson以及Dennis M. Ritche开发Unix的猛人，UTF-8的设计人。他还在美国名嘴David Letterman的晚间节目上露了一小脸，一脸憨厚地帮一胖子吹牛搞怪。让偶佩服不已的是，罗伯伯还是1980年奥运会射箭的银牌得主。他也是个颇为厉害的业余天文学家，设计的珈玛射线望远镜差点被NASA用在航天飞机上。他还是两本经典，The Unix Programming Environment 和 The Practice of Programming 的作者之一。如果初学者想在编程方面精益求精，实在该好好读读这两本书。它们都有中文版的说。罗伯伯还写出了Unix下第一个基于位图的窗口系统，并且是著名的blit终端的作者。当然了，罗伯伯还是号称锐意革新的操作系统，Plan9，的主要作者。可惜的是，Plan9并没有引起多少人的注意。罗伯伯一怒之下，写出了振聋发聩的雄文 Systems Software Research is Irrelevant，痛斥当下系统开发不思进取，固步自封的弊病。虽然这篇文章是罗伯伯含忿出手，颇有偏激之词，但确实道出了系统开发的无奈：开发周期越来越长，代价越来越大，用户被统一到少数几个系统上，结果越来越多的活动是测量和修补，而真正的革新越来越少。就在罗伯伯郁闷之极的时候，google登门求贤来乐。如果说现在还有一家大众公司在不遗余力地把系统开发推向极致的话，也就是google乐。随便看看google的成果就知道了。具有超强容错和负载平衡能力的分布式文件系统GFS(现在能够用100,000台廉价PC搭起一个巨型分布系统，并且高效便宜地进行管理的系统也不多哈)，大规模机器学习系统(拼写检查，广告匹配，拼音搜寻。。。哪个都很牛的说)，更不用说处理海量并行计算的各式google服务了。Rob在System Software Research is Irrelevant里萧瑟地说现在没有人再关心系统研究的前沿成果了。想不到他错了，因为google关心。google网络了大批功成名就的牛人，还有大量初生牛犊般博士做开发，显然不是没事耍酷，而是因为它们的开发总是试图吸取系统研究的最新成果。想必Rob Pike在google很幸福。愿他做出更棒的系统。<br/><br/>Dennis M. Ritchie<br/><br/><br/>既然Ken Thompson是我的偶像，新闻组上人称DMR的Dennis M. Ritchie自然也是，毕竟两人共同缔造了UNIX，而Dennis几乎独力把C搞大(当然，C的前身是B，而B是Ken Thompson一手做出来的)。J D两人1983年分享图灵奖，是有史以来少数几个因工程项目得奖的工程师(本来是唯一的一对儿，但Alan Kay才因为SmallTalk得奖，所以就成了唯二的乐)。一个人一生能做出一个卓越的系统已经不易，DMR的C和UNIX长盛不衰近30年，至今生机勃勃，DMR此生可以无憾的说。D爷爷也算有家学渊源：他老爸在AT&T贝尔实验室工作了一辈子，并在电路设计方面卓有成就，还出了本颇有影响的书The Design of Switching Circuits，据说在交换理论和逻辑设计方面有独到的论述。当然，D爷爷和他老爸是不同时代的人：他老爸的研究成形于晶体管发明之前，而D爷爷的工作离了晶体管就玩儿不转乐。:-D不要看D爷爷搞出了C，其实他最爱的编程语言是Alef，在Plan9上运行，支持并行编程。Alef的语法和C相似，但数据类型和执行方式都和C大大不同。说到语言，D爷爷对后来人有非常中肯的建议：抱着学习的目的来开发你自己的语言，不要冀望于它被众人接受。这个建议不光对语言开发有用，也适用于其它大型系统的开发。别的不说，DMR后来领导自己的团队在1995年和1996分别推出了Plan9和Inferno操作系统，又用多少人知道呢？其实，D爷爷当初也没想过C会风行世界。他开发C的初衷和Eric S. Raymond在Cathedral and Bazaar里阐述的一样，就是要消除自己对现有工具的不爽之处。谁知D爷爷无心插柳，C竟然受到众多程序员的狂热拥戴，连D爷爷自己都大惑不解。在一次采访中D爷爷说大概那是因为C的抽象程度碰巧既满足了程序员的要求，又容易实现。当然C一度是Unix上的通用语言也是原因。但不管怎么说，D爷爷对编程语言出色的审美意识奠定了C广为流传的基础。最后八卦一下。D爷爷的业余爱好和NBA大牛Karl Malone一样：开卡车。不过D爷爷更喜欢开NASCAR，而KM独爱巨无霸。J D爷爷自称心中不供偶像，如果一定要说一个，那就是Ken Thompson了。现在Ken爷爷退休当飞机教练去了，而D爷爷当了贝尔实验室系统开发部的头，整日忙于开支票。他俩合作20年，屡屡创造历史。这段令人神往的佳话，也就长留你我心中乐。P.S.，很多人都以为Brian W. Kernighan是C的作者。其实BWK只是写了那本经典K&R C。据D爷爷说，他，Ken和Kernighan三人中，Kernighan最能写文章，他次之，而Ken写得最少；但说到编程，Ken爷爷才是当之无愧的老大。<br/><br/>Edsger Wybe Dijkstra<br/><br/><br/>就是E.W. Dijkstra. 一提到EWD，很多人就会想起找最短路径的Dijkstra Algorithm，就好像一提到Sir. Tony Hoare，就想起Quick Sort一样。其实这些个算法不过是两个牛人在他们职业生涯中最琐碎的贡献。比如Dijkstra算法，无非是戴爷爷在1956年为了展示新计算机ARMAC的计算能力，初试身手的成果，属于他的算法处女作。据戴爷爷自述，他搞出最短路径算法的时候连纸笔都没用。当时他和他老婆在阿姆斯特丹一家咖啡厅的阳台上晒太阳喝咖啡，突然就把这个算法想出来乐。而且当时的算法研究还比较原始，牛人们忙着用计算机搞数值计算，对离散算法不屑一顾。那时连一个象样的专注于离散算法的专业期刊都没有。戴爷爷于是推迟发表这个算法。直到1959年，他才把这个算法发表在Numerische Mathematik的创刊号上，权为捧场。:-) EWD在多个领域牛气冲天，端的是理论和编程两手硬的高手。只不过他的很多工作比较深刻，学校的老先生们觉得本科生接受不了，不给本科生讲而已。戴爷爷大概因为最短路径算法一战成名，于是有人请他参加另一台计算机X1的设计工作，并且把设计实时中断系统的任务派给了他。现在看来实时中断也许不算什么，但要知到，X1前根本就没有实时中断的概念。实现它简直就是一场豪赌。戴爷爷起初还不情愿，但经不住项目负责人Bram和Carel的轮番“吹捧”：我们知道实时中断让您工作变得非常困难，但象您这样的牛人肯定能做出来的说。结果戴爷爷被糖衣炮弹彻底击穿，接下了这个烫手山芋。两三年后，他不仅搞出了实时中断，还围绕这个写出了自己的博士论文，顺利戴上博士帽。让戴爷爷真正成名立万的还是在X1上开发的Algo60，最早的高级语言之一。戴爷爷没日没夜地工作了8个月，就搞出了Algo60，也因此获得了1972年的图灵奖。因为Algo60，戴爷爷发表了一篇石破天惊的文章：Recursive Programming，于是人们才知道，原来高级语言也可以高效地实现递归，原来从此以后，所有程序员都不可避免地和戴爷爷发明的一个词(应该说是概念)打交道：堆栈。而且Algo60还让戴爷爷深入地思考多道程序设计的问题，最终发明了每个系统程序员都绕不开的概念：semaphore。当然，戴爷爷总是把他发明的概念严格形式化，极具科学家本色的说。和这些成就想比，他提出的吃饭的哲学家问题，也就没什么好说的了。说来好笑，当时的大学(忘了哪所了)还是觉得戴爷爷没有受过正统的数学训练，也不是专门搞数值分析的，所以最后不太情愿地给了他一个教职。这种小挫折并不能妨碍象戴爷爷这样的牛人创造历史。他一边教数值分析(:-D)，一边开始开发一个新的操作系统，并培养计算机科学家。几年后，THE Multiprogramming System横空出世。THE是第一个支持松散耦合，显式同步的进程并由此使得严格证明系统没有死锁变得容易的操作系统。可惜戴爷爷任职的系不识货，还强行解散了他的研究小组(1972年戴爷爷给他的系主任说他得了图灵奖，系主任的第一反应是你们搞计算机就喜欢乱发奖)。这让戴爷爷相当郁闷，得了抑郁症。在极度郁闷之中，戴爷爷决定用写作来治疗自己的抑郁症。于是经典就诞生乐：Notes on Structured Programming。戴爷爷从此被尊为结构化编程的奠基人，而且他的抑郁症也被治好乐。EWD太牛，结果他的故事也太多。先到这里吧。1973起，他的故事就在美国发生了。<br/><br/>Anders Hejlsberg<br/><br/><br/>微软.NET的首席架构师，编程语言设计和实现的顶尖高手。他一手做出了Turbo Pascal，也是Delphi, J++(尤其是WFC)，C#和.NET的主要作者。这些作品的名字足以为他立传。作为一个程序员，我在这样的大师面前实在无语。生子当如Anders的说。李维的《Borland传奇》里已详细讲述了Anders的传奇故事，我就不用费舌了：<a href="http://java.mblogger.cn/iexploiter/posts/1505.aspx" target="_blank">http://java.mblogger.cn/iexploiter/posts/1505.aspx</a>。Artima上有Anders谈C#的系列访谈。MSDN上有一段Anders导游的录像。有兴趣可以去看看牛人的丰采。
]]>
</description>
</item>
<item>
<link>http://narmy.cn/linux/read.php/74.htm</link>
<title><![CDATA[日常积累的一些linux和运维的东西 [转]]]></title> 
<author>lengyuex &lt;lengyuex@gmail.com&gt;</author>
<category><![CDATA[有用的 &#124;&#124; 有趣的]]></category>
<pubDate>Tue, 15 Sep 2009 11:56:14 +0000</pubDate> 
<guid>http://narmy.cn/linux/read.php/74.htm</guid> 
<description>
<![CDATA[ 
	<span style="font-family: Courier New;"><br/>转自：<a href="http://my.benorz.org/index.php/more/135/zh-cn" target="_blank">http://my.benorz.org/index.php/more/135/zh-cn</a><br/><br/>============证书生成======<br/>keytool -genkey -alias tomcat -keyalg RSA -keypass changeit -storepass changeit -keystore ben.keystore -validity 3600<br/><br/>=======================常用到的命令========================<br/>netstat -n &#124; awk ‘/^tcp/ &#123;++S[$NF]&#125; END &#123;for(a in S) print a, S[a]&#125;’<br/>　　状态：描述<br/>　　CLOSED：无连接是活动的或正在进行<br/>　　LISTEN：服务器在等待进入呼叫<br/>　　SYN_RECV：一个连接请求已经到达，等待确认<br/>　　SYN_SENT：应用已经开始，打开一个连接<br/>　　ESTABLISHED：正常数据传输状态<br/>　　FIN_WAIT1：应用说它已经完成<br/>　　FIN_WAIT2：另一边已同意释放<br/>　　ITMED_WAIT：等待所有分组死掉<br/>　　CLOSING：两边同时尝试关闭<br/>　　TIME_WAIT：另一边已初始化一个释放<br/>　　LAST_ACK：等待所有分组死掉<br/><br/>被DDOS了<br/>你使用这个命令可以查出哪个IP地址连接最多,将其封了.<br/><br/>netstat -na&#124;grep ESTABLISHED&#124;awk ‘&#123;print $5&#125;’&#124;awk -F: ‘&#123;print $1&#125;’&#124;sort&#124;uniq -c&#124;sort -r +0n<br/>netstat -na&#124;grep SYN&#124;awk ‘&#123;print $5&#125;’&#124;awk -F: ‘&#123;print $1&#125;’&#124;sort&#124;uniq -c&#124;sort -r +0n<br/>cat file &#124;grep google &#124;awk ‘/Googlebot/&#123;print $1&#125;’&#124;sort&#124;uniq&#124;sort -rn<br/><br/>netstat -n &#124;awk ‘/^tcp/&#123;print substr($5,0,(index($5,”:”)-1)),$NF&#125;’&#124;sort -r&#124;uniq -c&#124;sort -rn&#124;head -n 5<br/>[root@mth01 logs]# cat *.log&#124;awk ‘/GET/&#123;++N[$1]&#125; END&#123;for(i in N)&#123;print N[i],i&#125;&#125;’&#124;sort -rn&#124;head -n8<br/><br/>==============JVM内存优化===========<br/>-Xmn256M -Xms1024M -Xmx1024M -XX:MaxNewSize=512m -XX:MaxPermSize=512m”<br/><br/>增量备份<br/>rsync -v -a -z -e ssh –delete /opt/virtual/ 192.168.3.1:/bakhome/virtual<br/>rsync -v -a -z -e ssh –delete /opt/mthpic/ 192.168.3.1:/bakhome/mthpic<br/>===============================<br/><br/>——–什么序列号忘记了，好像是server 2003的————–<br/>EnterPrise ：YCFX3-376TJ-KD224-Y9B8J-7XDQK<br/>Standard ：738XF-4MBKQ-9GRM6-4MVVH-PVJ6Q<br/>Web ：GH9QJ-FY3VX-VCD6X-3T2VV-3G9QV<br/>Datacenter ：YWD28-W67QX-F22JD-3JJJ6-7H8R3<br/><br/>Windows XP 专业版 （这个号保证正版，可以用）：<br/>MRX3F-47B9T-2487J-KWKMF-RPWBY<br/><br/>时间服务器<br/>cn.pool.ntp.org<br/>=======缓存清理（只支持32位系统下使用）=================<br/>编译：<br/>引用 blog.s135.com<br/>wget <a href="http://www.wa.apana.org.au/~dean/sources/purge-20040201-src.tar.gz" target="_blank">http://www.wa.apana.org.au/~dean/sources/purge-20040201-src.tar.gz</a><br/>tar zxvf purge-20040201-src.tar.gz<br/>cd purge<br/>make<br/><br/>　　清除Squid缓存示例：<br/>　　1、清除 URL 以“.mp3”结尾的缓存文件<br/>引用<br/>purge -p pic.benorz.org:80 -P 1 -se ‘&#92;.jpg$’<br/>purge -p pic.benorz.org:80 -P 1 -se ‘&#92;.gif$’<br/>purge -p html.benorz.org:80 -P 1 -se ‘&#92;.swf$’<br/>purge -p html.benorz.org:80 -P 1 -se ‘&#92;.html$’<br/>purge -p html.benorz.org:80 -P 1 -se ‘benorz.org’<br/>　　2、清除URL中包含benorz.org的所有缓存：<br/>引用<br/>./purge -p localhost:80 -P 1 -se ‘benorz.org’<br/><br/>　　我喜欢将程序推到后台去执行，让它慢慢地去清Squid缓存，同时将输出内容记录到purge.log文件：<br/>引用<br/>./purge -p localhost:80 -P 1 -se ‘benorz.org’ > purge.log 2>&1 &<br/>============================================================================================<br/>Linux 每日小技巧<br/><br/>/*每日一更新*/<br/>/*从今天开始每天给大家提供一个小技巧,方便大家学习和LINUX知识!*/<br/>/*以命令,系统管理,小技巧为主*/<br/><br/>1.按内存从大到小排列进程:<br/>ps -eo “%C : %p : %z : %a”&#124;sort -k5 -nr<br/><br/>2.查看当前有哪些进程；查看进程打开的文件:<br/>ps -A ；lsof -p PID<br/><br/>3.获取当前IP地址（从中学习grep,awk,cut的作用）<br/>ifconfig eth0 &#124;grep “inet addr:” &#124;awk ‘&#123;print $2&#125;’&#124;cut -c 6-<br/><br/>4.统计每个单词出现的频率，并排序<br/>awk ‘&#123;arr[$1]+=1 &#125;END&#123;for(i in arr)&#123;print arr”&#92;t”i&#125;&#125;’ 文件名 &#124; sort -rn<br/><br/>5.显示10条最常用的命令<br/>sed -e “s/&#124; /&#92;n/g” ~/.bash_history &#124; cut -d ‘ ‘ -f 1 &#124; sort &#124; uniq -c &#124; sort -nr &#124; head<br/><br/>6.杀死Nginx进程(杀死某一进程)<br/>ps -ef&#124;grep -v grep &#124;grep nginx&#124;awk ‘&#123;print $2&#125;’ 或<br/>for i in `ps aux &#124; grep nginx &#124; grep -v grep &#124; awk &#123;’print $2′&#125;` ; do kill $i; done<br/><br/>7.列出当前文件夹目录大小，以G，M，K显示。<br/>du -b –max-depth 1 &#124; sort -nr &#124; perl -pe ’s&#123;([0-9]+)&#125;&#123;sprintf”%.1f%s”, $1>=2**30? ($1/2**30, “G”): $1>=2**20? ($1/2**20, “M”):$1>=2**10? ($1/2**10, “K”): ($1, “”)&#125;e’<br/><br/>8.清空linux buffer cache<br/>sync && echo 3 > /proc/sys/vm/drop_caches<br/><br/>9.将当前目录文件名全部转换成小写<br/>for i in *; do mv “$i” “$(echo $i&#124;tr A-Z a-z)”; done<br/><br/>10.消除vim中的^M的几种方法<br/>1)dos2uninx filename<br/>2)sed -e ’s/^M//’ filename<br/>3)vim中 :s/^M//gc<br/>4)col -bx < dosfile > newfile<br/>5)tr -s “&#92;r&#92;n” “&#92;n” < file > newfile<br/><br/>11. 清除所有arp缓存<br/>arp -n&#124;awk ‘/^[1-9]/ &#123;print “arp -d “$1&#125;’&#124;sh<br/><br/>12. 绑定已知机器的arp地址<br/>cat /proc/net/arp &#124; awk ‘&#123;print $1 ” ” $4&#125;’ &#124;sort -t. -n +3 -4 > /etc/ethers<br/><br/>==================oracle操作步骤=====================<br/>su oracle<br/><br/>source /home/oracle/.bash_profile<br/><br/>cd /opt/oracle/p*/10.2/bin<br/><br/>lsnrctl start<br/><br/>sqlplus / as sysdba<br/><br/>SQL> startup<br/><br/>====================<br/><br/>SQL> exit停止:$ sqlplus<br/><br/>Enter user-name:/ as sysdba<br/>SQL> shutdown immediate<br/>SQL> exit<br/><br/>列出 Oracle 进程：$ ps a€“fuoracle<br/>create or replace directory dump_dir as ‘/home/oracle/dump’<br/>impdp system/123456 dumpfile=gh_080822.dmp DIRECTORY=dump_dir<br/>impdp system/123456 dumpfile=mth20081014.dmp DIRECTORY=dump_dir<br/>impdp system/123456 dumpfile=mth.dmp DIRECTORY=dump_dir<br/>impdp mth/mth dumpfile=MTH_PROP_JOURNAL%U.dmp DIRECTORY=dump_dir<br/>impdp system/123456 dumpfile=gh_080822.dmp CONTENT=METADATA_ONLY DIRECTORY=dump_dir<br/>drop user xxxx cascade;<br/>用sys登录： connect as /sysdba;<br/>解锁scott: alter user scott account unlock;<br/>===================修改2003默认远程终端端口==================<br/>1、HKEY_LOCAL_MACHINE&#92;SYSTEM&#92;CurrentControlSet&#92;Control&#92;Terminal Server&#92;Wds&#92;rdpwd&#92;Tds&#92;tcp下的PortNumber=3389改为自宝义的端口号<br/>2、HKEY_LOCAL_MACHINE&#92;SYSTEM&#92;CurrentControlSet&#92;Control&#92;Terminal Server&#92;WinStations&#92;RDP-Tcp下的PortNumber=3389改为自宝义的端口号<br/>===================================<br/>基本的使用方法<br/>*取得squid运行状态信息： squidclient -p 80 mgr:info<br/>*取得squid内存使用情况： squidclient -p 80 mgr:mem<br/>*取得squid已经缓存的列表： squidclient -p 80 mgr:objects. use it carefully,it may crash<br/>*取得squid的磁盘使用情况： squidclient -p 80 mgr:diskd<br/>*强制更新某个url：squidclient -p 80 -m PURGE <a href="http://www.php-oa.com/static.php" target="_blank">http://www.php-oa.com/static.php</a><br/>*更多的请查看：squidclient -h 或者 squidclient -p 80 mgr:<br/><br/>* 如何得知 squid 执行中的状态？<br/>最简单的方式便是透过浏览器来观察。squid 本身提供一只 cgi 程式，档名为cachemgr.cgi，squid 安装完后将它复制到 Apache 下的 cgi-bin 这个目录下即可使用。<br/>要察看Cache Manager提供的资讯时，请在浏览器的位址列中键入<br/>http://服务器的名称或IP位址/cgi-bin/cachemgr.cgi<br/>当然,我更加喜欢使用下面的方法<br/>squidclient -t 1 -h localhost -p 80 mgr:inf 这样也行<br/>[root@MTH93 squid]# bin/squidclient -h BEN -p 80 mgr:<br/>HTTP/1.0 200 OK<br/>Server: squid/2.6.STABLE21-20080721<br/>Date: Thu, 23 Oct 2008 04:49:14 GMT<br/>Content-Type: text/plain<br/>Expires: Thu, 23 Oct 2008 04:49:14 GMT<br/>Last-Modified: Thu, 23 Oct 2008 04:49:14 GMT<br/>X-Cache: MISS from pic.benorz.org<br/>Via: 1.0 pic.benorz.org:80 (squid/2.6.STABLE21-20080721)<br/>Connection: close<br/><br/>mem Memory Utilization public<br/>cbdata Callback Data Registry Contents public<br/>events Event Queue public<br/>squidaio_counts Async IO Function Counters public<br/>coss COSS Stats public<br/>diskd DISKD Stats public<br/>config Current Squid Configuration hidden<br/>ipcache IP Cache Stats and Contents public<br/>fqdncache FQDN Cache Stats and Contents public<br/>dns Dnsserver Statistics public<br/>external_acl External ACL stats public<br/>http_headers HTTP Header Statistics public<br/>menu This Cachemanager Menu public<br/>shutdown Shut Down the Squid Process hidden<br/>offline_toggle Toggle offline_mode setting hidden<br/>info General Runtime Information public<br/>filedescriptors Process Filedescriptor Allocation public<br/>objects All Cache Objects public<br/>vm_objects In-Memory and In-Transit Objects public<br/>openfd_objects Objects with Swapout files open public<br/>pending_objects Objects being retreived from the network public<br/>client_objects Objects being sent to clients public<br/>io Server-side network read() size histograms public<br/>counters Traffic and Resource Counters public<br/>peer_select Peer Selection Algorithms public<br/>digest_stats Cache Digest and ICP blob public<br/>5min 5 Minute Average of Counters public<br/>60min 60 Minute Average of Counters public<br/>utilization Cache Utilization public<br/>histograms Full Histogram Counts public<br/>active_requests Client-side Active Requests public<br/>storedir Store Directory Stats public<br/>store_check_cachable_stats storeCheckCachable() Stats public<br/>store_io Store IO Interface Stats public<br/>pconn Persistent Connection Utilization Histograms public<br/>refresh Refresh Algorithm Statistics public<br/>delay Delay Pool Levels public<br/>forward Request Forwarding Statistics public<br/>client_list Cache Client List public<br/>asndb AS Number Database public<br/>server_list Peer Cache Statistics public<br/><br/>export JAVA_HOME=/usr/java/jdk1.6.0_12/<br/>export PATH=$JAVA_HOME/bin/:$PATH<br/>export CLASSPATH=$JAVA_HOME/lib:.</span><br/>Tags - <a href="http://narmy.cn/linux/go.php/tags/%25E8%25BF%2590%25E7%25BB%25B4/" rel="tag">运维</a> , <a href="http://narmy.cn/linux/go.php/tags/linux/" rel="tag">linux</a>
]]>
</description>
</item>
<item>
<link>http://narmy.cn/linux/read.php/21.htm</link>
<title><![CDATA[写给Linux内核新手-关于Linux内核学习的误区]]></title> 
<author>lengyuex &lt;lengyuex@gmail.com&gt;</author>
<category><![CDATA[有用的 &#124;&#124; 有趣的]]></category>
<pubDate>Thu, 16 Apr 2009 15:01:59 +0000</pubDate> 
<guid>http://narmy.cn/linux/read.php/21.htm</guid> 
<description>
<![CDATA[ 
	<span style="font-family: courier new;">写给Linux内核新手-关于Linux内核学习的误区<br/><br/>　　先说句正经的：其实我没资格写这篇文章，因为自己也就一两个月以来才开始有所领悟的。因此，这里与其说是关于Linux内核学习的经验，不如说是自己的教训吧，希望不要扔鸡蛋砸我^_^<br/><br/>　　　常常有人问：我想学习内核，需要什么基础吗？Linus Torvalds本人是这样回答的：你必须使用过Linux。 这个……还是有点太泛了吧，我想下面几个基础可能还是需要的，尽管不一定必需：<br/>　　1, 关于操作系统理论的最初级的知识。不需要通读并理解《操作系统概念》《现代操作系统》等巨著，但总要知道分时（time-shared）和实时（real-time）的区别是什么，进程是个什么东西，CPU和系统总线、内存的关系（很粗略即可），等等。<br/>　　2, 关于C语言。不需要已经很精通C语言，只要能熟练编写C程序，能看懂链表、散列表等数据结构的C实现，用过gcc编译器，就可以了。当然，如果已经精通C语言显然是大占便宜的。<br/>　　3, 关于CPU的知识。这块儿可以在学习内核过程中补，但这样的话你就需要看讲解很详细的书，比方后面将会提到的《情景分析》。你是否熟悉Intel 80386 CPU？尝试着回答这几个问题来判断一下：1）说出80386的中断门和陷阱门的区别；2）说出保护模式与实模式的区别；3）多处理器机器上，普通的读-改-写回一块内存这样的动作，为什么需要特殊的手段来保护。等等。讲解基于其它CPU的Linux内核的书，目前好象只有一本《IA64Linux内核：设计与实现》──也还是Intel的，其它都是讲解基于IA32的。<br/>　　以上算是知识方面吧，如果还要再补充一条，我想就是：动手编译过内核。<br/><br/><br/>　　好了，我们接下来走。好多人装上Linux之后，第一件事找到内核源码所在的路径，打开一个C程序文件，开始哗哗哗翻页，看看大名鼎鼎的Linux内核代码到底长啥模样──然后关闭。这是可理解的，但却不是学习的方法。刚开始，必须从读书入手。至少要对内核有一个Overview之后，才有可能带着问题去试图阅读源代码本身。 下面就讲一下我读过的几本书：<br/>　　1, 《Linux内核设计与实现》，英文名Linux Kernel Development（所以有人叫它LKD），机械工业出版社，￥35, 美国Robert Love著，陈莉君译者。 评说：<br/>　　此书是当今首屈一指的入门最佳图书。作者是为2.6内核加入了抢占的人，对调度部分非常精通，而调度是整个系统的核心，因此本书是很权威的。这本书讲解浅显易懂，全书没有列举一条汇编语句，但是给出了整个Linux操作系统2.6内核的概观，使你能通过阅读迅速获得一个overview。而且对内核中较为混乱的部分（如下半部），它的讲解是最透彻的。对没怎么深入内核的人来说，这是强烈推荐的一本书。<br/>　　　翻译：翻译水平、负责任程度都不错，但是印刷存在一些错误。买了此书的朋友可以参考我在Linux高级应用版的《Linux内核设计与实现中文版勘误》：<br/><a href="http://bbs.chinaunix.net/forum/viewtopic.php?t=541234" target="_blank">http://bbs.chinaunix.net/forum/viewtopic.php?t=541234</a><br/>另外，此书2005年有了第二版，目前尚无中译本面世。我就是对照着2nd-en勘误1st-cn的。<br/><br/>　　2, 《Linux内核源代码情景分析》上、下。毛德操、胡希明著，浙江大学出版社，上册￥80,下册￥70. 评说：<br/>　　本书是基于2.4.0内核的，比较早，也没听说会出第二版。上册讲解内存管理、中断、异常与系统调用、进程控制、文件系统与传统Unix IPC；下册讲解socket、设备驱动、SMP和引导。关于这套书的评价褒贬不一，我个人认为其深度是同类著作中最优秀的。本书基于Intel IA32体系，由于厚度大，很多体系上的知识都捎带讲解了，所以如果你想深入了解内核的工作机制而又不非常熟悉Intel CPU的体系构造，本书是最合适的。缺点是：版本较老，没有TCP/IP协议栈部分（它讲的socket只是Unix域协议的），图表太少，不适合初学者入门。还有就是对学生朋友来说，可能书价偏高，这样的话可以考虑先买上册，因为上册是核心部分，下册一大部分都在讲具体PCI/ISA/USB设备的驱动。<br/>　　翻译：没什么翻译，作者是国人，而且行文流畅。本人书桌上诸多计算机经典图书当中，这套是唯一又经典又无阅读障碍的。<br/>　　<a href="http://www.linuxforum.net" target="_blank">www.linuxforum.net</a>内核版好多朋友已经把这书读到六七遍了，我很惭愧，上册差不多读熟了，下册就SMP部分还看过──但这就花费了整整1年的时间，还有好多弄不懂的。这里顺便说明另外一个研究内核常见的误区：目标太庞大。要知道Linux内核（最新的2.6.13）bzip2压缩之后37M，解压缩之后244M，根本不是哪个人能够吃透的。即使是内核的核心开发团队中，恐怕也只Linus Torvalds、Alan Cox、David Miller、Ingo Molnar寥寥数人会有比较全面的了解，其它人都是做自己专门的部分。 我自己来说，目前已经决定放弃内存管理的全部（slab层、LRU、rbtree等）、文件系统部分、外设驱动部分，暂时也没打算弄IA32以外的其它体系的部分。<br/><br/>　　3, 《深入理解Linux内核》第二版。中国电力出版社。也是陈莉君译。此书是Linux内核黑客在推荐图书时的首选。 评说：<br/>　　此书C版的converse兄送了我一本第一版，因此就没买第二版，比较后悔。因此只就第一版说一说，第一版基于2.2,第二版2.4 。我见O'Reilly官方主页上说第三版的英文版将于2005年11月出版，也不知咱们何时才能见到。此书图表很多，形象地给出了关键数据结构的定义，与《情景分析》相比，本书内容紧凑，不会一个问题讲解动辄上百页，有提纲挈领的功用，但是深度上要逊于《情景分析》。<br/><br/>　　4, 其它的几本书。市面上能见到的其它的Linux内核的图书，象《Linux设备驱动程序》、《Linux内核源代码完全注释》以及新出的《Linux内核分析及编程》等。<br/>　　《Linux设备驱动程序》第二版是基于2.4的，中文翻译不错，中国电力出版。这书强调动手实践，但它是讲解“设备驱动”的，不是最核心的东西，而且有些东西没硬件的话无法实践，可能更适合驱动开发的程序员吧，不太适合那些For fun and profit的人。此书有第三版英文版，东南大学出版社影印，讲解2.6的，行文流畅，讲解的面也比第二版更广泛，我读过其中关于同步与互斥、内存分配的部分，感觉很不错。<br/>　　《Linux内核源代码完全注释》（机械工业出版社）是同济大学的博士生赵炯的著作，讲解0.1Linux内核，我没买也没看，有看过的朋友说一说。<br/>　　《Linux内核分析及编程》（电子工业出版社）是刚刚出版的，国人写的，讲解2.6.11 。很多人说好，但有人说不够系统，我没买，不敢评说。<br/>　　还有一本清华出的《Linux内核编程指南（第三版）》，原书应该是好书，但是翻译、排版十分糟烂，脱字跳行，根本没法看，我买了一本又扔掉了。<br/><br/>　　5, 其它资源。 TLDP（The Linux Documentation Project）有大量文档，其中不少是关于内核的，有些是在国外出版过的，象《Linux Kernel Interls》《The Linux Kernel》《Linux Kernel Module Programming Guide》等，作者都是亲身参加开发的人，著作较为可信。<br/><a href="Http://www.linuxforum.net" target="_blank">Http://www.linuxforum.net</a><br/>　　中国Linux论坛的内核版。该版是研究内核的中文Linux社区中水平最高的，有很多专家级别的牛人，强烈推荐去学习一下（但建议不要问太过分简单的问题，人家脾气再好也会烦的^_^），它的置顶贴简直是一个包罗万象的FAQ，精华区也有很多资料。只可惜太过曲高和寡，人气不是很旺。<br/><br/>　　6, 一本不是讲解Linux的书：《现代体系结构上的Unix系统：内核程序员的SMP和Caching技术》，人民邮电出版社2003版，定价￥39. 本书虽然不是讲解Linux，但是对所有Unix内核都是适用的，适合对SMP和CPU的Cache这些组成原理知识不是很熟的朋友，而且是很多国外牛人推荐的书。中文版翻译非常负责。<br/><br/><br/>　　还有个很重要的问题：怎样浏览内核源代码。有的朋友喜欢在Windows上工作，用Source Insight；有的在Linux，用Source Navigator；还有专门浏览源代码的软件，象lxr（Linux Cross Reference）；还有用ctags/ectags/cscope等，这些都是很优秀的软件。我个人用Vim + ctags浏览（参考了<a href="http://www.linuxforum.net" target="_blank">www.linuxforum.net</a>内核版wheelz大侠的文档，）。<br/><br/>　　此外，前边已经提到的一个重要的问题是：你研究内核的目的是什么， 开发？ 乐趣？如果是开发，而且是国内做开发，把kernel API熟悉一下就差不太多了（你也知道国内的水平有多差），比方说copy_from_user()、kmalloc()函数等，kernel API在Internet上找得到，编译内核时也可以用DocBook生成（具体请参考内核源代码包下的README文件）；如果是研究，那就差别很大了，需要下很大的苦功：会用kmalloc()绝不说明你懂得Linux内核的虚存管理子系统，正如同会讲汉语不说明你懂中国文化一样。<br/><br/><br/><br/><br/>　　说完了，发现前面讲的太罗嗦了，简化一下：<br/>　　1, 动手编译内核<br/>　　2, 精读《Linux内核设计与实现》<br/>　　3, 上<a href="http://www.linuxforum.net" target="_blank">www.linuxforum.net</a>内核版看置顶贴与精华区<br/>　　此外就凭自己兴趣选择吧。<br/><br/>下面是一篇没写完的《Linux内核模块编程入门》，不补写了，将就着看吧。 <br/><br/>albcamus 2005-10-13 02:41 <br/><br/>写给Linux内核新手-关于Linux内核学习的误区<br/><br/>Linux内核模块编程入门<br/>看到昨天有好几个问linux内核编程问题的帖子，不少是卡在了入门问题上，就整理一下入门的初步流程。针对2.6内核的Linux系统，需要你的机器上已经安装了kernel-devel这个包，也就是编译模块所必须的东西：内核的头文件和一些Makefile。<br/><br/>一，Hello World程序：<br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><span style="color: #808080; font-style: italic;">/*file: hello.c*/</span><br />
<span style="color: #339933;">#ifndef __KERNEL__</span><br />
<span style="color: #339933;">#define __KERNEL__</span><br />
<span style="color: #339933;">#endif</span><br />
<span style="color: #339933;">#ifndef MODULE</span><br />
<span style="color: #339933;">#define MODULE</span><br />
<span style="color: #339933;">#endif</span><br />
<span style="color: #339933;">#include &lt;linux/init.h&gt;;</span><br />
<span style="color: #339933;">#include &lt;linux/module.h&gt;;</span><br />
<span style="color: #339933;">#include &lt;linux/kernel.h&gt;;</span><br />
<br />
<span style="color: #993333;">static</span> <span style="color: #993333;">int</span> hello_init<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
printk<span style="color: #009900;">&#40;</span>KERN_ALERT <span style="color: #ff0000;">&quot;Hello, The fucking crazy world<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #993333;">static</span> <span style="color: #993333;">void</span> hello_exit<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
printk<span style="color: #009900;">&#40;</span>KERN_ALERT <span style="color: #ff0000;">&quot;Bye, The fucking crazy world!<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
module_init<span style="color: #009900;">&#40;</span>hello_init<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
module_exit<span style="color: #009900;">&#40;</span>hello_exit<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
MODULE_LICENSE<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;GPL&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
MODULE_AUTHOR<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;albcamus &lt;albcamus@163.com&gt;;&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div><br/><br/>2.6内核的kbuild子系统跟2.4相比有本质的改变。我们下面尝试两种方式编译这个程序：<br/>1, 你可以在本目录下这样写一个Makefile<br/><div class="code">obj-m := hell.o<br/>clean:<br/>rm -rf *.o .*.cmd *.ko *.mod.c .tmp_versions</div><br/>然后用这样的命令行编译：<br/>make -C /lib/modules/`uname -r`/build M=`pwd` modules<br/>这时ls一下，就能看到生成了很多文件，其中hello.ko就是我们需要的内核模块。<br/>2, 专业点儿，Makefile这样写：<br/><div class="code">obj-m := hello.o<br/>KERNELBUILD := /lib/modules/`uname -r`/build<br/>default:<br/>make -C $(KERNELBUILD) M=$(shell pwd) modules<br/>clean:<br/>rm -rf *.o .*.cmd *.ko *.mod.c .tmp_versions</div><br/>然后只要make一下就可以了。<br/><br/>插入模块用insmod命令：<br/>insmod ./hello.ko<br/>这时候大家可能会问：为什么我的屏幕上没有见到输出？这个是console的日志记录级别和你printk消息时指定的级别（本例中指定为KERN_ALERT，为次高，仅次于KERN_EMERG）决定的。无论如何，你可以tail 或者cat看看系统日志的最后几行，系统日志一般为/var/log/messages，或者直接用dmesg命令，肯定能看到输出了。<br/><br/>二，头文件问题。<br/>C程序员都知道，要使用某个外部的函数，应当#include某个头文件，这个头文件包含了那个函数的原型(prototype)。内核的头文件在include/下，其中include/asm是个符号链接，指向你所用内核的具体的体系结构目录，比方说我的系统是i386的，那么include/asm就指向include/asm-i386 。<br/>内核编程中我们不能链接libc库，不能使用libc库中的函数，所以很有些麻烦。一些重要的函数，象strcpy/strcmp/snprintf等，kernel也为我们实现并导出（export）了，而我们需要#include相关的头文件，在include/linux和include/asm中，你需要自己寻找你所要使用的函数在哪个头文件中声明，并将其#include进来。 <br/><br/><br/>写给Linux内核新手-关于Linux内核学习的误区<br/><br/>说点别的<br/>1、楼主4K太屈材了，但是中国现在这个状况没法说。我曾经去清华紫光面试，做AS400的售前／后支持「当时他们说有Unix基础就可以，不需要很了解400」，底薪4K＋提成，提成完全看销售业绩，估计很大一部分工作是配合销售去把产品骗出去，技术性工作估计不多。如果销售情况好的话收入还是很可观的，但是具他们内部人说没有销售挣得多。在国内许多大公司，一群本科是什么杂7杂8专业的，后来混了个“计算机”方面的“研究生”，啥都不懂成天混的人也都随便拿上5K+<br/><br/>2、牛人在中国会是什么下场？牛人就是象老牛一样多干活，还不一定有草吃。去年冬天我出差去昆明部署一个我们的软件，本来我只负责技术支持，职责就是按照文档把整个系统搭建起来。临走前开发人员和测试人员拍胸匍向我发誓程序完全没有问题了，我去到那里只要安装一下即可。结果到了那里，首先是客户系统被入侵而瘫痪，费了好大劲重建了系统恢复了数据库；接着发现程序有很严重bug，花了整整一天时间我给它debug。<br/>知道我最终的下场是什么吗？400块长途手机费不给报销，领导说按照规定每天只给报20。嗯，“按照规定”的话，发现被黑我就应该立刻打110『没必要估计客户的面子』，然后叫合作伙伴的人来装系统（系统原来是他们装的），这样就省下200块打电话请示领导、联络客户领导的手机费；“按照规定”的话，我作为非开发人员和测试人员没义务给程序debug，当我发现程序不能正常运作的时候就应该打道回府，这样就又能省下200块了<br/>我当时所在中国非常有名的一家软件上市公司「比红旗用友什么的大得多」，在这里我就不点名了<br/><br/>3、“到一家实力强劲的公司（如IBM,redflag）给人家打下手”？<br/>IBM内部的中国开发人员，只能从老美那里拿到裁减版的API手册，很多“牛人”的主要工作是汉化、debug、写文档和打包<br/>redflag？以前曾经有一个项目需要邮件系统，看了一下redflag的邮件服务器宣传还不错，联系了一下，跟一个什么产品经理谈了谈，结果是，为了拿到项目，他们完全可以放弃linux平台把它移植到客户指定的Solaris上去，总之就是只要能中标，怎么都行！所以我看redflag需要的不是“打下手”的，需要的是能够拿到单子的sells<br/><br/><br/>中国阿，就这么回事了<br/>PS:我现在在搞linux教育培训工作，收入还凑合，感觉这个环境铜臭味道少一些，可以有一些闲暇时间和精力去搞自给喜欢的研究，而且没人管^_^</span><br/>Tags - <a href="http://narmy.cn/linux/go.php/tags/linux/" rel="tag">linux</a> , <a href="http://narmy.cn/linux/go.php/tags/%25E5%2586%2585%25E6%25A0%25B8/" rel="tag">内核</a> , <a href="http://narmy.cn/linux/go.php/tags/%25E6%2596%25B0%25E6%2589%258B/" rel="tag">新手</a> , <a href="http://narmy.cn/linux/go.php/tags/%25E8%25AF%25AF%25E5%258C%25BA/" rel="tag">误区</a>
]]>
</description>
</item>
<item>
<link>http://narmy.cn/linux/read.php/19.htm</link>
<title><![CDATA[C/C++ 程序设计员应聘常见面试试题深入剖析]]></title> 
<author>lengyuex &lt;lengyuex@gmail.com&gt;</author>
<category><![CDATA[有用的 &#124;&#124; 有趣的]]></category>
<pubDate>Wed, 15 Apr 2009 06:30:06 +0000</pubDate> 
<guid>http://narmy.cn/linux/read.php/19.htm</guid> 
<description>
<![CDATA[ 
	<span style="font-family: courier new;">1.引言 <br/><br/>　　本文的写作目的并不在于提供C/C++程序员求职面试指导，而旨在从技术上分析面试题的内涵。文中的大多数面试题来自各大论坛，部分试题解答也参考了网友的意见。<br/><br/>　　许多面试题看似简单，却需要深厚的基本功才能给出完美的解答。企业要求面试者写一个最简单的strcpy函数都可看出面试者在技术上究竟达到了怎样的程度，我们能真正写好一个strcpy函数吗？我们都觉得自己能，可是我们写出的strcpy很可能只能拿到10分中的2分。读者可从本文看到strcpy函数从2分到10分解答的例子，看看自己属于什么样的层次。此外，还有一些面试题考查面试者敏捷的思维能力。 <br/><br/>　　分析这些面试题，本身包含很强的趣味性；而作为一名研发人员，通过对这些面试题的深入剖析则可进一步增强自身的内功。<br/><br/>　　2.找错题<br/><br/>　　试题1：<br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
<span style="color: #993333;">void</span> test1<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
　<span style="color: #993333;">char</span> <span style="color: #993333;">string</span><span style="color: #009900;">&#91;</span><span style="color: #0000dd;">10</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
　<span style="color: #993333;">char</span><span style="color: #339933;">*</span> str1 <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;0123456789&quot;</span><span style="color: #339933;">;</span><br />
　strcpy<span style="color: #009900;">&#40;</span> <span style="color: #993333;">string</span><span style="color: #339933;">,</span> str1 <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div><br/>　　试题2：<br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
<span style="color: #993333;">void</span> test2<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
　<span style="color: #993333;">char</span> <span style="color: #993333;">string</span><span style="color: #009900;">&#91;</span><span style="color: #0000dd;">10</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> str1<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">10</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
　<span style="color: #993333;">int</span> i<span style="color: #339933;">;</span><br />
　<span style="color: #b1b100;">for</span><span style="color: #009900;">&#40;</span>i<span style="color: #339933;">=</span><span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> i<span style="color: #339933;">&lt;</span><span style="color: #0000dd;">10</span><span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span><br />
　<span style="color: #009900;">&#123;</span><br />
　　str1<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">'a'</span><span style="color: #339933;">;</span><br />
　<span style="color: #009900;">&#125;</span><br />
　strcpy<span style="color: #009900;">&#40;</span> <span style="color: #993333;">string</span><span style="color: #339933;">,</span> str1 <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div><br/>　　试题3：<br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
<span style="color: #993333;">void</span> test3<span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span><span style="color: #339933;">*</span> str1<span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
　<span style="color: #993333;">char</span> <span style="color: #993333;">string</span><span style="color: #009900;">&#91;</span><span style="color: #0000dd;">10</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
　<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span> strlen<span style="color: #009900;">&#40;</span> str1 <span style="color: #009900;">&#41;</span> <span style="color: #339933;">&lt;=</span> <span style="color: #0000dd;">10</span> <span style="color: #009900;">&#41;</span><br />
　<span style="color: #009900;">&#123;</span><br />
　　strcpy<span style="color: #009900;">&#40;</span> <span style="color: #993333;">string</span><span style="color: #339933;">,</span> str1 <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
　<span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div><br/>　　解答：<br/><br/>　　试题1字符串str1需要11个字节才能存放下（包括末尾的’&#92;0’），而string只有10个字节的空间，strcpy会导致数组越界；<br/><br/>　　对试题2，如果面试者指出字符数组str1不能在数组内结束可以给3分；如果面试者指出strcpy(string, str1)调用使得从str1内存起复制到string内存起所复制的字节数具有不确定性可以给7分，在此基础上指出库函数strcpy工作方式的给10分；<br/><br/>　　对试题3，if(strlen(str1) <= 10)应改为if(strlen(str1) < 10)，因为strlen的结果未统计’&#92;0’所占用的1个字节。<br/><br/>　　剖析：<br/><br/>　　考查对基本功的掌握：<br/><br/>　　(1)字符串以’&#92;0’结尾；<br/><br/>　　(2)对数组越界把握的敏感度；<br/><br/>　　(3)库函数strcpy的工作方式，如果编写一个标准strcpy函数的总分值为10，下面给出几个不同得分的答案：<br/><br/>　　2分<br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
<span style="color: #993333;">void</span> strcpy<span style="color: #009900;">&#40;</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>strDest<span style="color: #339933;">,</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>strSrc <span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
　 <span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">*</span>strDest<span style="color: #339933;">++</span> <span style="color: #339933;">=</span> <span style="color: #339933;">*</span> strSrc<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> ‘\<span style="color: #0000dd;">0</span>’ <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div><br/>　　4分<br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
<span style="color: #993333;">void</span> strcpy<span style="color: #009900;">&#40;</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>strDest<span style="color: #339933;">,</span> <span style="color: #993333;">const</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>strSrc <span style="color: #009900;">&#41;</span> <br />
<span style="color: #666666; font-style: italic;">//将源字符串加const，表明其为输入参数，加2分</span><br />
<span style="color: #009900;">&#123;</span><br />
　 <span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">*</span>strDest<span style="color: #339933;">++</span> <span style="color: #339933;">=</span> <span style="color: #339933;">*</span> strSrc<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> ‘\<span style="color: #0000dd;">0</span>’ <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div><br/>　　7分<br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
<span style="color: #993333;">void</span> strcpy<span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span> <span style="color: #339933;">*</span>strDest<span style="color: #339933;">,</span> <span style="color: #993333;">const</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>strSrc<span style="color: #009900;">&#41;</span> <br />
<span style="color: #009900;">&#123;</span><br />
　<span style="color: #666666; font-style: italic;">//对源地址和目的地址加非0断言，加3分</span><br />
　assert<span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#40;</span>strDest <span style="color: #339933;">!=</span> <span style="color: #000000; font-weight: bold;">NULL</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #009900;">&#40;</span>strSrc <span style="color: #339933;">!=</span> <span style="color: #000000; font-weight: bold;">NULL</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
　<span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">*</span>strDest<span style="color: #339933;">++</span> <span style="color: #339933;">=</span> <span style="color: #339933;">*</span> strSrc<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> ‘\<span style="color: #0000dd;">0</span>’ <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div><br/>　　10分<br/><br/>//为了实现链式操作，将目的地址返回，加3分！<br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
<span style="color: #993333;">char</span> <span style="color: #339933;">*</span> strcpy<span style="color: #009900;">&#40;</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>strDest<span style="color: #339933;">,</span> <span style="color: #993333;">const</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>strSrc <span style="color: #009900;">&#41;</span> <br />
<span style="color: #009900;">&#123;</span><br />
　assert<span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#40;</span>strDest <span style="color: #339933;">!=</span> <span style="color: #000000; font-weight: bold;">NULL</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #009900;">&#40;</span>strSrc <span style="color: #339933;">!=</span> <span style="color: #000000; font-weight: bold;">NULL</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
　<span style="color: #993333;">char</span> <span style="color: #339933;">*</span>address <span style="color: #339933;">=</span> strDest<span style="color: #339933;">;</span> <br />
　<span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">*</span>strDest<span style="color: #339933;">++</span> <span style="color: #339933;">=</span> <span style="color: #339933;">*</span> strSrc<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> ‘\<span style="color: #0000dd;">0</span>’ <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <br />
　　<span style="color: #b1b100;">return</span> address<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div><br/>　　从2分到10分的几个答案我们可以清楚的看到，小小的strcpy竟然暗藏着这么多玄机，真不是盖的！需要多么扎实的基本功才能写一个完美的strcpy啊！<br/><br/>　　(4)对strlen的掌握，它没有包括字符串末尾的'&#92;0'。<br/><br/>　　读者看了不同分值的strcpy版本，应该也可以写出一个10分的strlen函数了，完美的版本为：<br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
&nbsp;<span style="color: #993333;">int</span> strlen<span style="color: #009900;">&#40;</span> <span style="color: #993333;">const</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>str <span style="color: #009900;">&#41;</span> <span style="color: #666666; font-style: italic;">//输入参数const</span><br />
<br />
<span style="color: #009900;">&#123;</span><br />
　assert<span style="color: #009900;">&#40;</span> strt <span style="color: #339933;">!=</span> <span style="color: #000000; font-weight: bold;">NULL</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//断言字符串地址非0</span><br />
　<span style="color: #993333;">int</span> len<span style="color: #339933;">;</span><br />
　<span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">*</span>str<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> <span style="color: #ff0000;">'<span style="color: #000099; font-weight: bold;">\0</span>'</span> <span style="color: #009900;">&#41;</span> <br />
　<span style="color: #009900;">&#123;</span> <br />
　　len<span style="color: #339933;">++;</span> <br />
　<span style="color: #009900;">&#125;</span> <br />
　<span style="color: #b1b100;">return</span> len<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div><br/>　　试题4：<br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
<span style="color: #993333;">void</span> GetMemory<span style="color: #009900;">&#40;</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>p <span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
　p <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span> <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span> malloc<span style="color: #009900;">&#40;</span> <span style="color: #0000dd;">100</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #993333;">void</span> Test<span style="color: #009900;">&#40;</span> <span style="color: #993333;">void</span> <span style="color: #009900;">&#41;</span> <br />
<span style="color: #009900;">&#123;</span><br />
　<span style="color: #993333;">char</span> <span style="color: #339933;">*</span>str <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">NULL</span><span style="color: #339933;">;</span><br />
　GetMemory<span style="color: #009900;">&#40;</span> str <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <br />
　strcpy<span style="color: #009900;">&#40;</span> str<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;hello world&quot;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
　<a href="http://www.opengroup.org/onlinepubs/009695399/functions/printf.html"><span style="color: #000066;">printf</span></a><span style="color: #009900;">&#40;</span> str <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div><br/>　　试题5：<br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
<span style="color: #993333;">char</span> <span style="color: #339933;">*</span>GetMemory<span style="color: #009900;">&#40;</span> <span style="color: #993333;">void</span> <span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span> <br />
　<span style="color: #993333;">char</span> p<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;hello world&quot;</span><span style="color: #339933;">;</span> <br />
　<span style="color: #b1b100;">return</span> p<span style="color: #339933;">;</span> <br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #993333;">void</span> Test<span style="color: #009900;">&#40;</span> <span style="color: #993333;">void</span> <span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span> <br />
　<span style="color: #993333;">char</span> <span style="color: #339933;">*</span>str <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">NULL</span><span style="color: #339933;">;</span> <br />
　str <span style="color: #339933;">=</span> GetMemory<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <br />
　<a href="http://www.opengroup.org/onlinepubs/009695399/functions/printf.html"><span style="color: #000066;">printf</span></a><span style="color: #009900;">&#40;</span> str <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <br />
<span style="color: #009900;">&#125;</span></div><br/>　　试题6：<br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
<span style="color: #993333;">void</span> GetMemory<span style="color: #009900;">&#40;</span> <span style="color: #993333;">char</span> <span style="color: #339933;">**</span>p<span style="color: #339933;">,</span> <span style="color: #993333;">int</span> num <span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
　<span style="color: #339933;">*</span>p <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span> <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span> malloc<span style="color: #009900;">&#40;</span> num <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #993333;">void</span> Test<span style="color: #009900;">&#40;</span> <span style="color: #993333;">void</span> <span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
　<span style="color: #993333;">char</span> <span style="color: #339933;">*</span>str <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">NULL</span><span style="color: #339933;">;</span><br />
　GetMemory<span style="color: #009900;">&#40;</span> <span style="color: #339933;">&amp;</span>str<span style="color: #339933;">,</span> <span style="color: #0000dd;">100</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
　strcpy<span style="color: #009900;">&#40;</span> str<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;hello&quot;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <br />
　<a href="http://www.opengroup.org/onlinepubs/009695399/functions/printf.html"><span style="color: #000066;">printf</span></a><span style="color: #009900;">&#40;</span> str <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <br />
<span style="color: #009900;">&#125;</span></div><br/>　　试题7：<br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
<span style="color: #993333;">void</span> Test<span style="color: #009900;">&#40;</span> <span style="color: #993333;">void</span> <span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
　<span style="color: #993333;">char</span> <span style="color: #339933;">*</span>str <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span> <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span> malloc<span style="color: #009900;">&#40;</span> <span style="color: #0000dd;">100</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
　strcpy<span style="color: #009900;">&#40;</span> str<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;hello&quot;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
　free<span style="color: #009900;">&#40;</span> str <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <br />
　... <span style="color: #666666; font-style: italic;">//省略的其它语句</span><br />
<span style="color: #009900;">&#125;</span></div><br/>　　解答：<br/><br/>　　试题4传入中GetMemory( char *p )函数的形参为字符串指针，在函数内部修改形参并不能真正的改变传入形参的值，执行完<br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
<span style="color: #993333;">char</span> <span style="color: #339933;">*</span>str <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">NULL</span><span style="color: #339933;">;</span><br />
GetMemory<span style="color: #009900;">&#40;</span> str <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div><br/>　　后的str仍然为NULL；<br/><br/>　　试题5中<br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
<span style="color: #993333;">char</span> p<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;hello world&quot;</span><span style="color: #339933;">;</span> <br />
<span style="color: #b1b100;">return</span> p<span style="color: #339933;">;</span></div><br/>　　的p[]数组为函数内的局部自动变量，在函数返回后，内存已经被释放。这是许多程序员常犯的错误，其根源在于不理解变量的生存期。<br/><br/>　　试题6的GetMemory避免了试题4的问题，传入GetMemory的参数为字符串指针的指针，但是在GetMemory中执行申请内存及赋值语句<br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
<span style="color: #339933;">*</span>p <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span> <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span> malloc<span style="color: #009900;">&#40;</span> num <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div><br/>　　后未判断内存是否申请成功，应加上：<br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #339933;">*</span>p <span style="color: #339933;">==</span> <span style="color: #000000; font-weight: bold;">NULL</span> <span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
　...<span style="color: #666666; font-style: italic;">//进行申请内存失败处理</span><br />
<span style="color: #009900;">&#125;</span></div><br/>　　试题7存在与试题6同样的问题，在执行<br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
<span style="color: #993333;">char</span> <span style="color: #339933;">*</span>str <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span> <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span> malloc<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">100</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div><br/>　　后未进行内存是否申请成功的判断；另外，在free(str)后未置str为空，导致可能变成一个“野”指针，应加上：<br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
str <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">NULL</span><span style="color: #339933;">;</span></div><br/>　　试题6的Test函数中也未对malloc的内存进行释放。<br/><br/>　　剖析：<br/><br/>　　试题4～7考查面试者对内存操作的理解程度，基本功扎实的面试者一般都能正确的回答其中50~60的错误。但是要完全解答正确，却也绝非易事。<br/><br/>　　对内存操作的考查主要集中在：<br/><br/>　　（1）指针的理解；<br/><br/>　　（2）变量的生存期及作用范围；<br/><br/>　　（3）良好的动态内存申请和释放习惯。<br/><br/>　　再看看下面的一段程序有什么错误：<br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
swap<span style="color: #009900;">&#40;</span> <span style="color: #993333;">int</span><span style="color: #339933;">*</span> p1<span style="color: #339933;">,</span><span style="color: #993333;">int</span><span style="color: #339933;">*</span> p2 <span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
　<span style="color: #993333;">int</span> <span style="color: #339933;">*</span>p<span style="color: #339933;">;</span><br />
　<span style="color: #339933;">*</span>p <span style="color: #339933;">=</span> <span style="color: #339933;">*</span>p1<span style="color: #339933;">;</span><br />
　<span style="color: #339933;">*</span>p1 <span style="color: #339933;">=</span> <span style="color: #339933;">*</span>p2<span style="color: #339933;">;</span><br />
　<span style="color: #339933;">*</span>p2 <span style="color: #339933;">=</span> <span style="color: #339933;">*</span>p<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div><br/>　　在swap函数中，p是一个“野”指针，有可能指向系统区，导致程序运行的崩溃。在VC++中DEBUG运行时提示错误“Access Violation”。该程序应该改为：<br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
swap<span style="color: #009900;">&#40;</span> <span style="color: #993333;">int</span><span style="color: #339933;">*</span> p1<span style="color: #339933;">,</span><span style="color: #993333;">int</span><span style="color: #339933;">*</span> p2 <span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
　<span style="color: #993333;">int</span> p<span style="color: #339933;">;</span><br />
　p <span style="color: #339933;">=</span> <span style="color: #339933;">*</span>p1<span style="color: #339933;">;</span><br />
　<span style="color: #339933;">*</span>p1 <span style="color: #339933;">=</span> <span style="color: #339933;">*</span>p2<span style="color: #339933;">;</span><br />
　<span style="color: #339933;">*</span>p2 <span style="color: #339933;">=</span> p<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div><br/> 　　3.内功题<br/><br/>　　试题1：分别给出BOOL，int，float，指针变量 与“零值”比较的 if 语句（假设变量名为var）<br/><br/>　　解答：<br/><br/>　　　BOOL型变量：if(!var)<br/><br/>　　　int型变量： if(var==0)<br/><br/>　　　float型变量：<br/><br/>　　　const float EPSINON = 0.00001;<br/><br/>　　　if ((x >= - EPSINON) && (x <= EPSINON)<br/><br/>　　　指针变量：　　if(var==NULL)<br/><br/>　　剖析：<br/><br/>　　考查对0值判断的“内功”，BOOL型变量的0判断完全可以写成if(var==0)，而int型变量也可以写成if(!var)，指针变量的判断也可以写成if(!var)，上述写法虽然程序都能正确运行，但是未能清晰地表达程序的意思。 <br/> <br/> <br/><br/>　　一般的，如果想让if判断一个变量的“真”、“假”，应直接使用if(var)、if(!var)，表明其为“逻辑”判断；如果用if判断一个数值型变量(short、int、long等)，应该用if(var==0)，表明是与0进行“数值”上的比较；而判断指针则适宜用if(var==NULL)，这是一种很好的编程习惯。<br/><br/>　　浮点型变量并不精确，所以不可将float变量用“==”或“！=”与数字比较，应该设法转化成“>=”或“<=”形式。如果写成if (x == 0.0)，则判为错，得0分。<br/><br/>　　试题2：以下为Windows NT下的32位C++程序，请计算sizeof的值<br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
<span style="color: #993333;">void</span> Func <span style="color: #009900;">&#40;</span> <span style="color: #993333;">char</span> str<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">100</span><span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
　<span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span> str <span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #339933;">?</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #993333;">void</span> <span style="color: #339933;">*</span>p <span style="color: #339933;">=</span> malloc<span style="color: #009900;">&#40;</span> <span style="color: #0000dd;">100</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #993333;">sizeof</span> <span style="color: #009900;">&#40;</span> p <span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #339933;">?</span></div><br/>　　解答：<br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
<span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span> str <span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #0000dd;">4</span><br />
<span style="color: #993333;">sizeof</span> <span style="color: #009900;">&#40;</span> p <span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #0000dd;">4</span></div><br/>　　剖析：<br/><br/>　　Func ( char str[100] )函数中数组名作为函数形参时，在函数体内，数组名失去了本身的内涵，仅仅只是一个指针；在失去其内涵的同时，它还失去了其常量特性，可以作自增、自减等操作，可以被修改。<br/><br/>　　数组名的本质如下：<br/><br/>　　（1）数组名指代一种数据结构，这种数据结构就是数组；<br/><br/>　　例如：<br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
<span style="color: #993333;">char</span> str<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">10</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
<a href="http://www.opengroup.org/onlinepubs/009695399/functions/cout.html"><span style="color: #000066;">cout</span></a> <span style="color: #339933;">&lt;&lt;</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>str<span style="color: #009900;">&#41;</span> <span style="color: #339933;">&lt;&lt;</span> endl<span style="color: #339933;">;</span></div><br/>　　输出结果为10，str指代数据结构char[10]。<br/><br/>　　（2）数组名可以转换为指向其指代实体的指针，而且是一个指针常量，不能作自增、自减等操作，不能被修改；<br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
<span style="color: #993333;">char</span> str<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">10</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span> <br />
str<span style="color: #339933;">++;</span> <span style="color: #666666; font-style: italic;">//编译出错，提示str不是左值　</span></div><br/>　　（3）数组名作为函数形参时，沦为普通指针。<br/><br/>　　Windows NT 32位平台下，指针的长度（占用内存的大小）为4字节，故sizeof( str ) 、sizeof ( p ) 都为4。<br/><br/>　　试题3：写一个“标准”宏MIN，这个宏输入两个参数并返回较小的一个。另外，当你写下面的代码时会发生什么事？<br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
least <span style="color: #339933;">=</span> MIN<span style="color: #009900;">&#40;</span><span style="color: #339933;">*</span>p<span style="color: #339933;">++,</span> b<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div><br/>　　解答：<br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
<span style="color: #339933;">#define MIN(A,B) ((A) &lt;= (B) ? (A) : (B))</span><br />
　　MIN<span style="color: #009900;">&#40;</span><span style="color: #339933;">*</span>p<span style="color: #339933;">++,</span> b<span style="color: #009900;">&#41;</span>会产生宏的副作用</div><br/><br/>　　剖析：<br/><br/>　　这个面试题主要考查面试者对宏定义的使用，宏定义可以实现类似于函数的功能，但是它终归不是函数，而宏定义中括弧中的“参数”也不是真的参数，在宏展开的时候对“参数”进行的是一对一的替换。<br/><br/>　　程序员对宏定义的使用要非常小心，特别要注意两个问题：<br/><br/>　　（1）谨慎地将宏定义中的“参数”和整个宏用用括弧括起来。所以，严格地讲，下述解答：<br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
<span style="color: #339933;">#define MIN(A,B) (A) &lt;= (B) ? (A) : (B)</span><br />
<span style="color: #339933;">#define MIN(A,B) (A &lt;= B ? A : B )</span></div><br/>　　都应判0分；<br/><br/>　　（2）防止宏的副作用。<br/><br/>　　宏定义<div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
<span style="color: #339933;">#define MIN(A,B) ((A) &lt;= (B) ? (A) : (B))对MIN(*p++, b)</span></div><br/><br/>的作用结果是：<br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">*</span>p<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&lt;=</span> <span style="color: #009900;">&#40;</span>b<span style="color: #009900;">&#41;</span> <span style="color: #339933;">?</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">*</span>p<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">:</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">*</span>p<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp;</div><br/>　　这个表达式会产生副作用，指针p会作三次++自增操作。<br/><br/>　　除此之外，另一个应该判0分的解答是：<br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
<span style="color: #339933;">#define MIN(A,B) ((A) &lt;= (B) ? (A) : (B));</span></div><br/>　　这个解答在宏定义的后面加“;”，显示编写者对宏的概念模糊不清，只能被无情地判0分并被面试官淘汰。<br/><br/>　　试题4：为什么标准头文件都有类似以下的结构？ <br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
<span style="color: #339933;">#ifndef __INCvxWorksh</span><br />
<span style="color: #339933;">#define __INCvxWorksh </span><br />
<span style="color: #339933;">#ifdef __cplusplus</span><br />
<br />
<span style="color: #000000; font-weight: bold;">extern</span> <span style="color: #ff0000;">&quot;C&quot;</span> <span style="color: #009900;">&#123;</span><br />
<span style="color: #339933;">#endif </span><br />
<span style="color: #808080; font-style: italic;">/*...*/</span> <br />
<span style="color: #339933;">#ifdef __cplusplus</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #339933;">#endif </span><br />
<span style="color: #339933;">#endif /* __INCvxWorksh */</span></div><br/>　　解答：<br/><br/>　　头文件中的编译宏<br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
<span style="color: #339933;">#ifndef　__INCvxWorksh</span><br />
<span style="color: #339933;">#define　__INCvxWorksh</span><br />
<span style="color: #339933;">#endif</span></div><br/>　　的作用是防止被重复引用。<br/><br/>　　作为一种面向对象的语言，C++支持函数重载，而过程式语言C则不支持。函数被C++编译后在symbol库中的名字与C语言的不同。例如，假设某个函数的原型为： <br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
<span style="color: #993333;">void</span> foo<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> x<span style="color: #339933;">,</span> <span style="color: #993333;">int</span> y<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div><br/><br/>　　该函数被C编译器编译后在symbol库中的名字为_foo，而C++编译器则会产生像_foo_int_int之类的名字。_foo_int_int这样的名字包含了函数名和函数参数数量及类型信息，C++就是考这种机制来实现函数重载的。<br/><br/>　　为了实现C和C++的混合编程，C++提供了C连接交换指定符号extern "C"来解决名字匹配问题，函数声明前加上extern "C"后，则编译器就会按照C语言的方式将该函数编译为_foo，这样C语言中就可以调用C++的函数了。<br/>　试题5：编写一个函数，作用是把一个char组成的字符串循环右移n个。比如原来是“abcdefghi”如果n=2，移位后应该是“hiabcdefgh” <br/><br/>　　函数头是这样的：<br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
<span style="color: #666666; font-style: italic;">//pStr是指向以'\0'结尾的字符串的指针</span><br />
<span style="color: #666666; font-style: italic;">//steps是要求移动的n</span><br />
<br />
<span style="color: #993333;">void</span> LoopMove <span style="color: #009900;">&#40;</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span> pStr<span style="color: #339933;">,</span> <span style="color: #993333;">int</span> steps <span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
　<span style="color: #666666; font-style: italic;">//请填充...</span><br />
<span style="color: #009900;">&#125;</span></div><br/>　　解答：<br/><br/>　　正确解答1：<br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
<span style="color: #993333;">void</span> LoopMove <span style="color: #009900;">&#40;</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>pStr<span style="color: #339933;">,</span> <span style="color: #993333;">int</span> steps <span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
　<span style="color: #993333;">int</span> n <span style="color: #339933;">=</span> strlen<span style="color: #009900;">&#40;</span> pStr <span style="color: #009900;">&#41;</span> <span style="color: #339933;">-</span> steps<span style="color: #339933;">;</span><br />
　<span style="color: #993333;">char</span> tmp<span style="color: #009900;">&#91;</span>MAX_LEN<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span> <br />
　strcpy <span style="color: #009900;">&#40;</span> tmp<span style="color: #339933;">,</span> pStr <span style="color: #339933;">+</span> n <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <br />
　strcpy <span style="color: #009900;">&#40;</span> tmp <span style="color: #339933;">+</span> steps<span style="color: #339933;">,</span> pStr<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <br />
　<span style="color: #339933;">*</span><span style="color: #009900;">&#40;</span> tmp <span style="color: #339933;">+</span> strlen <span style="color: #009900;">&#40;</span> pStr <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">'<span style="color: #000099; font-weight: bold;">\0</span>'</span><span style="color: #339933;">;</span><br />
　strcpy<span style="color: #009900;">&#40;</span> pStr<span style="color: #339933;">,</span> tmp <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div><br/>　　正确解答2：<br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
<span style="color: #993333;">void</span> LoopMove <span style="color: #009900;">&#40;</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>pStr<span style="color: #339933;">,</span> <span style="color: #993333;">int</span> steps <span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
　<span style="color: #993333;">int</span> n <span style="color: #339933;">=</span> strlen<span style="color: #009900;">&#40;</span> pStr <span style="color: #009900;">&#41;</span> <span style="color: #339933;">-</span> steps<span style="color: #339933;">;</span><br />
　<span style="color: #993333;">char</span> tmp<span style="color: #009900;">&#91;</span>MAX_LEN<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span> <br />
　memcpy<span style="color: #009900;">&#40;</span> tmp<span style="color: #339933;">,</span> pStr <span style="color: #339933;">+</span> n<span style="color: #339933;">,</span> steps <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <br />
　memcpy<span style="color: #009900;">&#40;</span>pStr <span style="color: #339933;">+</span> steps<span style="color: #339933;">,</span> pStr<span style="color: #339933;">,</span> n <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <br />
　memcpy<span style="color: #009900;">&#40;</span>pStr<span style="color: #339933;">,</span> tmp<span style="color: #339933;">,</span> steps <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <br />
<span style="color: #009900;">&#125;</span></div><br/>　　剖析：<br/><br/>　　这个试题主要考查面试者对标准库函数的熟练程度，在需要的时候引用库函数可以很大程度上简化程序编写的工作量。<br/><br/>　　最频繁被使用的库函数包括：<br/><br/>　　（1） strcpy<br/><br/>　　（2） memcpy<br/><br/>　　（3） memset<br/><br/>　　试题6：已知WAV文件格式如下表，打开一个WAV文件，以适当的数据结构组织WAV文件头并解析WAV格式的各项信息。<br/><br/>　　WAVE文件格式说明表<br/><br/> <br/>偏移地址&nbsp;&nbsp;字节数&nbsp;&nbsp;数据类型&nbsp;&nbsp;内 容<br/>文件头<br/> <br/>00H&nbsp;&nbsp;4&nbsp;&nbsp;Char&nbsp;&nbsp;"RIFF"标志<br/>04H&nbsp;&nbsp;4&nbsp;&nbsp;int32&nbsp;&nbsp;文件长度<br/>08H&nbsp;&nbsp;4&nbsp;&nbsp;Char&nbsp;&nbsp;"WAVE"标志<br/>0CH&nbsp;&nbsp;4&nbsp;&nbsp;Char&nbsp;&nbsp;"fmt"标志<br/>10H&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp; 过渡字节（不定）<br/>14H&nbsp;&nbsp;2&nbsp;&nbsp;int16&nbsp;&nbsp;格式类别<br/>16H&nbsp;&nbsp;2&nbsp;&nbsp;int16&nbsp;&nbsp;通道数<br/>18H&nbsp;&nbsp;2&nbsp;&nbsp;int16&nbsp;&nbsp;采样率（每秒样本数），表示每个通道的播放速度<br/>1CH&nbsp;&nbsp;4&nbsp;&nbsp;int32&nbsp;&nbsp;波形音频数据传送速率<br/>20H&nbsp;&nbsp;2&nbsp;&nbsp;int16&nbsp;&nbsp;数据块的调整数（按字节算的）<br/>22H&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp; 每样本的数据位数<br/>24H&nbsp;&nbsp;4&nbsp;&nbsp;Char&nbsp;&nbsp;数据标记符＂data＂<br/>28H&nbsp;&nbsp;4&nbsp;&nbsp;int32&nbsp;&nbsp;语音数据的长度<br/>　　解答：<br/><br/>　　将WAV文件格式定义为结构体WAVEFORMAT： <br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
<span style="color: #993333;">typedef</span> <span style="color: #993333;">struct</span> tagWaveFormat<br />
<span style="color: #009900;">&#123;</span> <br />
　<span style="color: #993333;">char</span> cRiffFlag<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">4</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span> <br />
　UIN32 nFileLen<span style="color: #339933;">;</span> <br />
　<span style="color: #993333;">char</span> cWaveFlag<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">4</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span> <br />
　<span style="color: #993333;">char</span> cFmtFlag<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">4</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span> <br />
　<span style="color: #993333;">char</span> cTransition<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">4</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span> <br />
　UIN16 nFormatTag <span style="color: #339933;">;</span> <br />
　UIN16 nChannels<span style="color: #339933;">;</span> <br />
　UIN16 nSamplesPerSec<span style="color: #339933;">;</span> <br />
　UIN32 nAvgBytesperSec<span style="color: #339933;">;</span> <br />
　UIN16 nBlockAlign<span style="color: #339933;">;</span> <br />
　UIN16 nBitNumPerSample<span style="color: #339933;">;</span> <br />
　<span style="color: #993333;">char</span> cDataFlag<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">4</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span> <br />
　UIN16 nAudioLength<span style="color: #339933;">;</span> <br />
<br />
<span style="color: #009900;">&#125;</span> WAVEFORMAT<span style="color: #339933;">;</span><br />
　　假设WAV文件内容读出后存放在指针buffer开始的内存单元内，则分析文件格式的代码很简单，为：<br />
<br />
WAVEFORMAT waveFormat<span style="color: #339933;">;</span><br />
memcpy<span style="color: #009900;">&#40;</span> <span style="color: #339933;">&amp;</span>waveFormat<span style="color: #339933;">,</span> buffer<span style="color: #339933;">,</span><span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span> WAVEFORMAT <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div><br/>　　直接通过访问waveFormat的成员，就可以获得特定WAV文件的各项格式信息。<br/><br/>　　剖析：<br/><br/>　　试题6考查面试者组织数据结构的能力，有经验的程序设计者将属于一个整体的数据成员组织为一个结构体，利用指针类型转换，可以将memcpy、memset等函数直接用于结构体地址，进行结构体的整体操作。 透过这个题可以看出面试者的程序设计经验是否丰富。<br/><br/>　　试题7：编写类String的构造函数、析构函数和赋值函数，已知类String的原型为：<br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
class <span style="color: #993333;">String</span><br />
<span style="color: #009900;">&#123;</span> <br />
　public<span style="color: #339933;">:</span> <br />
　　<span style="color: #993333;">String</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">const</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>str <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">NULL</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// 普通构造函数 </span><br />
　　<span style="color: #993333;">String</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">const</span> <span style="color: #993333;">String</span> <span style="color: #339933;">&amp;</span>other<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// 拷贝构造函数 </span><br />
　　~ <span style="color: #993333;">String</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// 析构函数 </span><br />
　　<span style="color: #993333;">String</span> <span style="color: #339933;">&amp;</span> operate <span style="color: #339933;">=</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">const</span> <span style="color: #993333;">String</span> <span style="color: #339933;">&amp;</span>other<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// 赋值函数 </span><br />
　private<span style="color: #339933;">:</span> <br />
　　<span style="color: #993333;">char</span> <span style="color: #339933;">*</span>m_data<span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// 用于保存字符串 </span><br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></div><br/>　　解答：<br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
<span style="color: #666666; font-style: italic;">//普通构造函数</span><br />
<br />
<span style="color: #993333;">String</span><span style="color: #339933;">::</span><span style="color: #993333;">String</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">const</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>str<span style="color: #009900;">&#41;</span> <br />
<span style="color: #009900;">&#123;</span><br />
　<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>str<span style="color: #339933;">==</span><span style="color: #000000; font-weight: bold;">NULL</span><span style="color: #009900;">&#41;</span> <br />
　<span style="color: #009900;">&#123;</span><br />
　　m_data <span style="color: #339933;">=</span> new <span style="color: #993333;">char</span><span style="color: #009900;">&#91;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// 得分点：对空字符串自动申请存放结束标志'\0'的空</span><br />
　　<span style="color: #666666; font-style: italic;">//加分点：对m_data加NULL 判断</span><br />
　　<span style="color: #339933;">*</span>m_data <span style="color: #339933;">=</span> <span style="color: #ff0000;">'<span style="color: #000099; font-weight: bold;">\0</span>'</span><span style="color: #339933;">;</span> <br />
　<span style="color: #009900;">&#125;</span> <br />
　<span style="color: #b1b100;">else</span><br />
　<span style="color: #009900;">&#123;</span><br />
　　<span style="color: #993333;">int</span> length <span style="color: #339933;">=</span> strlen<span style="color: #009900;">&#40;</span>str<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <br />
　　m_data <span style="color: #339933;">=</span> new <span style="color: #993333;">char</span><span style="color: #009900;">&#91;</span>length<span style="color: #339933;">+</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// 若能加 NULL 判断则更好 </span><br />
　　strcpy<span style="color: #009900;">&#40;</span>m_data<span style="color: #339933;">,</span> str<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <br />
　<span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// String的析构函数</span><br />
<br />
<span style="color: #993333;">String</span><span style="color: #339933;">::</span>~<span style="color: #993333;">String</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span> <br />
<span style="color: #009900;">&#123;</span><br />
　delete <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> m_data<span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// 或delete m_data;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #666666; font-style: italic;">//拷贝构造函数</span><br />
<br />
<span style="color: #993333;">String</span><span style="color: #339933;">::</span><span style="color: #993333;">String</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">const</span> <span style="color: #993333;">String</span> <span style="color: #339933;">&amp;</span>other<span style="color: #009900;">&#41;</span> 　　　<span style="color: #666666; font-style: italic;">// 得分点：输入参数为const型</span><br />
<span style="color: #009900;">&#123;</span> <br />
　<span style="color: #993333;">int</span> length <span style="color: #339933;">=</span> strlen<span style="color: #009900;">&#40;</span>other.<span style="color: #202020;">m_data</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <br />
　m_data <span style="color: #339933;">=</span> new <span style="color: #993333;">char</span><span style="color: #009900;">&#91;</span>length<span style="color: #339933;">+</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span> 　　　　<span style="color: #666666; font-style: italic;">//加分点：对m_data加NULL 判断</span><br />
　strcpy<span style="color: #009900;">&#40;</span>m_data<span style="color: #339933;">,</span> other.<span style="color: #202020;">m_data</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #666666; font-style: italic;">//赋值函数</span><br />
<br />
<span style="color: #993333;">String</span> <span style="color: #339933;">&amp;</span> <span style="color: #993333;">String</span><span style="color: #339933;">::</span><span style="color: #202020;">operate</span> <span style="color: #339933;">=</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">const</span> <span style="color: #993333;">String</span> <span style="color: #339933;">&amp;</span>other<span style="color: #009900;">&#41;</span> <span style="color: #666666; font-style: italic;">// 得分点：输入参数为const型</span><br />
<span style="color: #009900;">&#123;</span> <br />
　<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>this <span style="color: #339933;">==</span> <span style="color: #339933;">&amp;</span>other<span style="color: #009900;">&#41;</span> 　　<span style="color: #666666; font-style: italic;">//得分点：检查自赋值</span><br />
　　<span style="color: #b1b100;">return</span> <span style="color: #339933;">*</span>this<span style="color: #339933;">;</span> <br />
　delete <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> m_data<span style="color: #339933;">;</span> 　　　　<span style="color: #666666; font-style: italic;">//得分点：释放原有的内存资源</span><br />
　<span style="color: #993333;">int</span> length <span style="color: #339933;">=</span> strlen<span style="color: #009900;">&#40;</span> other.<span style="color: #202020;">m_data</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <br />
　m_data <span style="color: #339933;">=</span> new <span style="color: #993333;">char</span><span style="color: #009900;">&#91;</span>length<span style="color: #339933;">+</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span> 　<span style="color: #666666; font-style: italic;">//加分点：对m_data加NULL 判断</span><br />
　strcpy<span style="color: #009900;">&#40;</span> m_data<span style="color: #339933;">,</span> other.<span style="color: #202020;">m_data</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <br />
　<span style="color: #b1b100;">return</span> <span style="color: #339933;">*</span>this<span style="color: #339933;">;</span> 　　　　　　　　<span style="color: #666666; font-style: italic;">//得分点：返回本对象的引用</span><br />
<span style="color: #009900;">&#125;</span></div><br/>　　剖析：<br/><br/>　　能够准确无误地编写出String类的构造函数、拷贝构造函数、赋值函数和析构函数的面试者至少已经具备了C++基本功的60%以上！<br/><br/>　　在这个类中包括了指针类成员变量m_data，当类中包括指针类成员变量时，一定要重载其拷贝构造函数、赋值函数和析构函数，这既是对C++程序员的基本要求，也是《Effective　C++》中特别强调的条款。<br/><br/>　　仔细学习这个类，特别注意加注释的得分点和加分点的意义，这样就具备了60%以上的C++基本功！<br/><br/>　　试题8：请说出static和const关键字尽可能多的作用<br/><br/>　　解答：<br/><br/>　　static关键字至少有下列n个作用：<br/><br/>　　（1）函数体内static变量的作用范围为该函数体，不同于auto变量，该变量的内存只被分配一次，因此其值在下次调用时仍维持上次的值；<br/><br/>　　（2）在模块内的static全局变量可以被模块内所用函数访问，但不能被模块外其它函数访问；<br/><br/>　　（3）在模块内的static函数只可被这一模块内的其它函数调用，这个函数的使用范围被限制在声明它的模块内；<br/><br/>　　（4）在类中的static成员变量属于整个类所拥有，对类的所有对象只有一份拷贝；<br/><br/>　　（5）在类中的static成员函数属于整个类所拥有，这个函数不接收this指针，因而只能访问类的static成员变量。 <br/> <br/> <br/><br/>　　const关键字至少有下列n个作用：<br/><br/>　　（1）欲阻止一个变量被改变，可以使用const关键字。在定义该const变量时，通常需要对它进行初始化，因为以后就没有机会再去改变它了；<br/><br/>　　（2）对指针来说，可以指定指针本身为const，也可以指定指针所指的数据为const，或二者同时指定为const；<br/><br/>　　（3）在一个函数声明中，const可以修饰形参，表明它是一个输入参数，在函数内部不能改变其值；<br/><br/>　　（4）对于类的成员函数，若指定其为const类型，则表明其是一个常函数，不能修改类的成员变量；<br/><br/>　　（5）对于类的成员函数，有时候必须指定其返回值为const类型，以使得其返回值不为“左值”。例如：<br/><br/>const classA operator*(const classA& a1,const classA& a2);<br/>　　operator*的返回结果必须是一个const对象。如果不是，这样的变态代码也不会编译出错：<br/><br/>classA a, b, c;<br/>(a * b) = c; // 对a*b的结果赋值<br/>　　操作(a * b) = c显然不符合编程者的初衷，也没有任何意义。<br/><br/>　　剖析：<br/><br/>　　惊讶吗？小小的static和const居然有这么多功能，我们能回答几个？如果只能回答1~2个，那还真得闭关再好好修炼修炼。<br/><br/>　　这个题可以考查面试者对程序设计知识的掌握程度是初级、中级还是比较深入，没有一定的知识广度和深度，不可能对这个问题给出全面的解答。大多数人只能回答出static和const关键字的部分功能。<br/><br/>　　4.技巧题<br/><br/>　　试题1：请写一个C函数，若处理器是Big_endian的，则返回0；若是Little_endian的，则返回1<br/><br/>　　解答：<br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
<span style="color: #993333;">int</span> checkCPU<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
　<span style="color: #009900;">&#123;</span><br />
　　<span style="color: #993333;">union</span> w<br />
　　<span style="color: #009900;">&#123;</span> <br />
　　　<span style="color: #993333;">int</span> a<span style="color: #339933;">;</span><br />
　　　<span style="color: #993333;">char</span> b<span style="color: #339933;">;</span><br />
　　<span style="color: #009900;">&#125;</span> c<span style="color: #339933;">;</span><br />
　　c.<span style="color: #202020;">a</span> <span style="color: #339933;">=</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span><br />
　　<span style="color: #b1b100;">return</span> <span style="color: #009900;">&#40;</span>c.<span style="color: #202020;">b</span> <span style="color: #339933;">==</span> <span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
　<span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div><br/>　　剖析：<br/><br/>　　嵌入式系统开发者应该对Little-endian和Big-endian模式非常了解。采用Little-endian模式的CPU对操作数的存放方式是从低字节到高字节，而Big-endian模式对操作数的存放方式是从高字节到低字节。例如，16bit宽的数0x1234在Little-endian模式CPU内存中的存放方式（假设从地址0x4000开始存放）为：<br/><br/>内存地址&nbsp;&nbsp;存放内容<br/>0x4000&nbsp;&nbsp;0x34<br/>0x4001&nbsp;&nbsp;0x12<br/>　　而在Big-endian模式CPU内存中的存放方式则为：<br/><br/>内存地址&nbsp;&nbsp;存放内容<br/>0x4000&nbsp;&nbsp;0x12<br/>0x4001&nbsp;&nbsp;0x34<br/>　　32bit宽的数0x12345678在Little-endian模式CPU内存中的存放方式（假设从地址0x4000开始存放）为：<br/><br/>内存地址&nbsp;&nbsp;存放内容<br/>0x4000&nbsp;&nbsp;0x78<br/>0x4001&nbsp;&nbsp;0x56<br/>0x4002&nbsp;&nbsp;0x34<br/>0x4003&nbsp;&nbsp;0x12<br/>　　而在Big-endian模式CPU内存中的存放方式则为：<br/><br/>内存地址&nbsp;&nbsp;存放内容<br/>0x4000&nbsp;&nbsp;0x12<br/>0x4001&nbsp;&nbsp;0x34<br/>0x4002&nbsp;&nbsp;0x56<br/>0x4003&nbsp;&nbsp;0x78<br/>　　联合体union的存放顺序是所有成员都从低地址开始存放，面试者的解答利用该特性，轻松地获得了CPU对内存采用Little-endian还是Big-endian模式读写。如果谁能当场给出这个解答，那简直就是一个天才的程序员。<br/><br/>　　试题2：写一个函数返回1+2+3+…+n的值（假定结果不会超过长整型变量的范围） <br/><br/>　　解答：<br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
<span style="color: #993333;">int</span> Sum<span style="color: #009900;">&#40;</span> <span style="color: #993333;">int</span> n <span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span> <br />
　<span style="color: #b1b100;">return</span> <span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">long</span><span style="color: #009900;">&#41;</span><span style="color: #0000dd;">1</span> <span style="color: #339933;">+</span> n<span style="color: #009900;">&#41;</span> <span style="color: #339933;">*</span> n <span style="color: #339933;">/</span> <span style="color: #0000dd;">2</span><span style="color: #339933;">;</span>　　<span style="color: #666666; font-style: italic;">//或return (1l + n) * n / 2;</span><br />
<span style="color: #009900;">&#125;</span><br />
　</div>　剖析：<br/>　<br/>　　对于这个题，只能说，也许最简单的答案就是最好的答案。下面的解答，或者基于下面的解答思路去优化，不管怎么“折腾”，其效率也不可能与直接return ( 1 l + n ) * n / 2相比！ <br/><div class="c" style="font-family:monospace;FONT-SIZE: 12px; FONT-FAMILY: Consolas, Lucida Console, Courier New; BORDER:1px dotted gray; PADDING: 5px 5px 5px 5px"><br />
<span style="color: #993333;">int</span> Sum<span style="color: #009900;">&#40;</span> <span style="color: #993333;">int</span> n <span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
　<span style="color: #993333;">long</span> sum <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span><br />
　<span style="color: #b1b100;">for</span><span style="color: #009900;">&#40;</span> <span style="color: #993333;">int</span> i<span style="color: #339933;">=</span><span style="color: #0000dd;">1</span><span style="color: #339933;">;</span> i<span style="color: #339933;">&lt;=</span>n<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span> <span style="color: #009900;">&#41;</span><br />
　<span style="color: #009900;">&#123;</span><br />
　　sum <span style="color: #339933;">+=</span> i<span style="color: #339933;">;</span><br />
　<span style="color: #009900;">&#125;</span><br />
　<span style="color: #b1b100;">return</span> sum<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div><br/>　　所以程序员们需要敏感地将数学等知识用在程序设计中。<br/></span>
]]>
</description>
</item>
<item>
<link>http://narmy.cn/linux/read.php/18.htm</link>
<title><![CDATA[程序员面试之葵花宝典]]></title> 
<author>lengyuex &lt;lengyuex@gmail.com&gt;</author>
<category><![CDATA[有用的 &#124;&#124; 有趣的]]></category>
<pubDate>Wed, 15 Apr 2009 06:22:55 +0000</pubDate> 
<guid>http://narmy.cn/linux/read.php/18.htm</guid> 
<description>
<![CDATA[ 
	<span style="font-family: courier new;"><br/><br/>面向对象的特征有哪些方面&nbsp;&nbsp;<br/> <br/>1. 抽象：抽象就是忽略一个主题中与当前目标2. 无关的那些方面，3. 以便更充分地注意与当前目标4. 有关的方面。抽象并不5. 打算了解全部问题，而6. 只是选择其中的一部分，7. 暂时不8. 用部分细节。抽象包括两个方面，9. 一是过程抽象，10. 二是数据抽象。<br/><br/>11. 继承：继承是一种联结类的层次模型，12. 并且允许和鼓励类的重用，13. 它提供了一种明确表述共性的方法。对象的一个新类可以从现有的类中派生，14. 这个过程称为类继承。新类继承了原始类的特性，15. 新类称为原始类的派生类（子类），而16. 原始类称为新类的基类（父类）。派生类可以从它的基类那里继承方法和实例变量，17. 并且类可以修改或增加新的方法使之更适合特殊的需要。<br/><br/>18. 封装：封装是把过程和数据包围起来，19. 对数据的访问只能通过已定义的界面。面向对象计算始于这个基本概念，20. 即现实世界可以被描绘成一系列完全自治、封装的对象，21. 这些对象通过一个受保护的接口访问其他对象。<br/><br/>22. 多态性：多态性是指23. 允许不同24. 类的对象对同25. 一消息作出响应。多态性包括参数化多态性和包含多态性。多态性语言具有灵活、抽象、行为共享、代码共享的优势，26. 很好的解决了应用程序函数同27. 名28. 问题。<br/><br/>2、String是最基本的数据类型吗?<br/>基本数据类型包括byte、int、char、long、float、double、boolean和short。<br/>java.lang.String类是final类型的，因此不可以继承这个类、不能修改这个类。为了提高效率节省空间，我们应该用StringBuffer类<br/><br/>3、int 和 Integer 有什么区别<br/>Java 提供两种不同的类型：引用类型和原始类型（或内置类型）。Int是java的原始数据类型，Integer是java为int提供的封装类。Java为每个原始类型提供了封装类。<br/>原始类型封装类booleanBoolean&nbsp;&nbsp;charCharacter&nbsp;&nbsp;byteByte&nbsp;&nbsp;shortShort&nbsp;&nbsp;intInteger&nbsp;&nbsp;longLong&nbsp;&nbsp;floatFloat&nbsp;&nbsp;doubleDouble<br/>引用类型和原始类型的行为完全不同，并且它们具有不同的语义。引用类型和原始类型具有不同的特征和用法，它们包括：大小和速度问题，这种类型以哪种类型的数据结构存储，当引用类型和原始类型用作某个类的实例数据时所指定的缺省值。对象引用实例变量的缺省值为 null，而原始类型实例变量的缺省值与它们的类型有关。<br/><br/>4、String 和StringBuffer的区别<br/>JAVA平台提供了两个类：String和StringBuffer，它们可以储存和操作字符串，即包含多个字符的字符数据。这个String类提供了数值不可改变的字符串。而这个StringBuffer类提供的字符串进行修改。当你知道字符数据要改变的时候你就可以使用StringBuffer。典型地，你可以使用StringBuffers来动态构造字符数据。<br/><br/>5、运行时异常与一般异常有何异同？<br/>异常表示程序运行过程中可能出现的非正常状态，运行时异常表示虚拟机的通常操作中可能遇到的异常，是一种常见运行错误。java编译器要求方法必须声明抛出可能发生的非运行时异常，但是并不要求必须声明抛出未被捕获的运行时异常。<br/><br/>6、说出Servlet的生命周期，并说出Servlet和CGI的区别。<br/>Servlet被服务器实例化后，容器运行其init方法，请求到达时运行其service方法，service方法自动派遣运行与请求对应的doXXX方法（doGet，doPost）等，当服务器决定将实例销毁的时候调用其destroy方法。<br/>与cgi的区别在于servlet处于服务器进程中，它通过多线程方式运行其service方法，一个实例可以服务于多个请求，并且其实例一般不会销毁，而CGI对每个请求都产生新的进程，服务完成后就销毁，所以效率上低于servlet。<br/><br/>7、说出ArrayList,Vector, LinkedList的存储性能和特性<br/>ArrayList和Vector都是使用数组方式存储数据，此数组元素数大于实际存储的数据以便增加和插入元素，它们都允许直接按序号索引元素，但是插入元素要涉及数组元素移动等内存操作，所以索引数据快而插入数据慢，Vector由于使用了synchronized方法（线程安全），通常性能上较ArrayList差，而LinkedList使用双向链表实现存储，按序号索引数据需要进行前向或后向遍历，但是插入数据时只需要记录本项的前后项即可，所以插入速度较快。<br/><br/>8、EJB是基于哪些技术实现的？并说出SessionBean和EntityBean的区别，StatefulBean和StatelessBean的区别。<br/>&nbsp;&nbsp;&nbsp;&nbsp;EJB包括Session Bean、Entity Bean、Message Driven Bean，基于JNDI、RMI、JAT等技术实现。<br/>SessionBean在J2EE应用程序中被用来完成一些服务器端的业务操作，例如访问数据库、调用其他EJB组件。EntityBean被用来代表应用系统中用到的数据。<br/>对于客户机，SessionBean是一种非持久性对象，它实现某些在服务器上运行的业务逻辑。<br/>对于客户机，EntityBean是一种持久性对象，它代表一个存储在持久性存储器中的实体的对象视图，或是一个由现有企业应用程序实现的实体。<br/>Session Bean 还可以再细分为 Stateful Session Bean 与 Stateless Session Bean ，这两种的 Session Bean都可以将系统逻辑放在 method之中执行，不同的是 Stateful Session Bean 可以记录呼叫者的状态，因此通常来说，一个使用者会有一个相对应的 Stateful Session Bean 的实体。Stateless Session Bean 虽然也是逻辑组件，但是他却不负责记录使用者状态，也就是说当使用者呼叫 Stateless Session Bean 的时候，EJB Container 并不会找寻特定的 Stateless Session Bean 的实体来执行这个 method。换言之，很可能数个使用者在执行某个 Stateless Session Bean 的 methods 时，会是同一个 Bean 的 Instance 在执行。从内存方面来看， Stateful Session Bean 与 Stateless Session Bean 比较， Stateful Session Bean 会消耗 J2EE Server 较多的内存，然而 Stateful Session Bean 的优势却在于他可以维持使用者的状态。<br/><br/>9、Collection 和 Collections的区别。 Collection是集合类的上级接口，继承与他的接口主要有Set 和List.<br/>Collections是针对集合类的一个帮助类，他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。<br/><br/>10、&和&&的区别。 &是位运算符，表示按位与运算，&&是逻辑运算符，表示逻辑与（and）。<br/><br/><br/>11、HashMap和Hashtable的区别。&nbsp;&nbsp;HashMap是Hashtable的轻量级实现（非线程安全<br/>的实现），他们都完成了Map接口，主要区别在于HashMap允许空（null）键值（key）,由于非线程安全，效率上可能高于Hashtable。<br/>HashMap允许将null作为一个entry的key或者value，而Hashtable不允许。<br/>HashMap把Hashtable的contains方法去掉了，改成containsvalue和containsKey。因为contains方法容易让人引起误解。 Hashtable继承自Dictionary类，而HashMap是Java1.2引进的Map interface的一个实现。<br/>最大的不同是，Hashtable的方法是Synchronize的，而HashMap不是，在多个线程访问Hashtable时，不需要自己为它的方法实现同步，而HashMap 就必须为之提供外同步。 <br/>Hashtable和HashMap采用的hash/rehash算法都大概一样，所以性能不会有很大的差异。<br/><br/>12、final, finally, finalize的区别。 final 用于声明属性，方法和类，分别表示属性不可变，方法不可覆盖，类不可继承。finally是异常处理语句结构的一部分，表示总是执行。finalize是Object类的一个方法，在垃圾收集器执行的时候会调用被回收对象的此方法，可以覆盖此方法提供垃圾收集时的其他资源回收，例如关闭文件等。<br/><br/>13、sleep() 和 wait() 有什么区别? sleep是线程类（Thread）的方法，导致此线程暂停执行指定时间，给执行机会给其他线程，但是监控状态依然保持，到时后会自动恢复。调用sleep不会释放对象锁。wait是Object类的方法，对此对象调用wait方法导致本线程放弃对象锁，进入等待此对象的等待锁定池，只有针对此对象发出notify方法（或notifyAll）后本线程才进入对象锁定池准备获得对象锁进入运行状态。<br/><br/>14、Overload和Override的区别。Overloaded的方法是否可以改变返回值的类型?<br/>方法的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父类与子类之间多态性的一种表现，重载Overloading是一个类中多态性的一种表现。如果在子类中定义某方法与其父类有相同的名称和参数，我们说该方法被重写 (Overriding)。子类的对象使用这个方法时，将调用子类中的定义，对它而言，父类中的定义如同被“屏蔽”了。如果在一个类中定义了多个同名的方法，它们或有不同的参数个数或有不同的参数类型，则称为方法的重载(Overloading)。Overloaded的方法是可以改变返回值的类型。<br/><br/>15、error和exception有什么区别?<br/>error 表示恢复不是不可能但很困难的情况下的一种严重问题。比如说内存溢出。不可能指望程序能处理这样的情况。<br/>exception 表示一种设计或实现问题。也就是说，它表示如果程序运行正常，从不会发生的情况。<br/><br/>16、同步和异步有何异同，在什么情况下分别使用他们？举例说明。<br/>如果数据将在线程间共享。例如正在写的数据以后可能被另一个线程读到，或者正在读的数据可能已经被另一个线程写过了，那么这些数据就是共享数据，必须进行同步存取。当应用程序在对象上调用了一个需要花费很长时间来执行的方法，并且不希望让程序等待方法的返回时，就应该使用异步编程，在很多情况下采用异步途径往往更有效率。<br/><br/>17、abstract class和interface有什么区别?声明方法的存在而不去实现它的类被叫做抽象类（abstract class），它用于要创建一个体现某些基本行为的类，并为该类声明方法，但不能在该类中实现该类的情况。不能创建abstract 类的实例。然而可以创建一个变量，其类型是一个抽象类，并让它指向具体子类的一个实例。不能有抽象构造函数或抽象静态方法。Abstract 类的子类为它们父类中的所有抽象方法提供实现，否则它们也是抽象类为。取而代之，在子类中实现该方法。知道其行为的其它类可以在类中实现这些方法。接口（interface）是抽象类的变体。在接口中，所有方法都是抽象的。多继承性可通过实现这样的接口而获得。接口中的所有方法都是抽象的，没有一个有程序体。接口只可以定义static final成员变量。接口的实现与子类相似，除了该实现类不能从接口定义中继承行为。当类实现特殊接口时，它定义（即将程序体给予）所有这种接口的方法。然后，它可以在实现了该接口的类的任何对象上调用接口的方法。由于有抽象类，它允许使用接口名作为引用变量的类型。通常的动态联编将生效。引用可以转换到接口类型或从接口类型转换，instanceof 运算符可以用来决定某对象的类是否实现了接口。<br/><br/>18、heap和stack有什么区别。栈是一种线形集合，其添加和删除元素的操作应在同一段完成。栈按照后进先出的方式进行处理。堆是栈的一个组成元素<br/><br/>19、forward 和redirect的区别forward是服务器请求资源，服务器直接访问目标地址的URL，把那个URL的响应内容读取过来，然后把这些内容再发给浏览器，浏览器根本不知道服务器发送的内容是从哪儿来的，所以它的地址栏中还是原来的地址。 redirect就是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址，一般来说浏览器会用刚才请求的所有参数重新请求，所以session,request参数都可以获取。<br/><br/>20、EJB与JAVA BEAN的区别？Java Bean 是可复用的组件，对Java Bean并没有严格的规范，理论上讲，任何一个Java类都可以是一个Bean。但通常情况下，由于Java Bean是被容器所创建（如Tomcat）的，所以Java Bean应具有一个无参的构造器，另外，通常Java Bean还要实现Serializable接口用于实现Bean的持久性。Java Bean实际上相当于微软COM模型中的本地进程内COM组件，它是不能被跨进程访问的。Enterprise Java Bean 相当于DCOM，即分布式组件。它是基于Java的远程方法调用（RMI）技术的，所以EJB可以被远程访问（跨进程、跨计算机）。但EJB必须被布署在诸如Webspere、WebLogic这样的容器中，EJB客户从不直接访问真正的EJB组件，而是通过其容器访问。EJB容器是EJB组件的代理，EJB组件由容器所创建和管理。客户通过容器来访问真正的EJB组件。<br/><br/>21、Static Nested Class 和 Inner Class的不同。 Static Nested Class是被声明为静态（static）的内部类，它可以不依赖于外部类实例被实例化。而通常的内部类需要在外部类实例化后才能实例化。<br/><br/>22、JSP中动态INCLUDE与静态INCLUDE的区别？动态INCLUDE用jsp:include动作实现 <jsp:include page="included.jsp" flush="true" />它总是会检查所含文件中的变化，适合用于包含动态页面，并且可以带参数。静态INCLUDE用include伪码实现,定不会检查所含文件的变化，适用于包含静态页面<%@ include file="included.htm" %><br/><br/>23、什么时候用assert。&nbsp;&nbsp;assertion(断言)在软件开发中是一种常用的调试方式，很多开发语言中都支持这种机制。在实现中，assertion就是在程序中的一条语句，它对一个boolean表达式进行检查，一个正确程序必须保证这个boolean表达式的值为true；如果该值为false，说明程序已经处于不正确的状态下，系统将给出警告或退出。一般来说，assertion用于保证程序最基本、关键的正确性。assertion检查通常在开发和测试时开启。为了提高性能，在软件发布后，assertion检查通常是关闭的。<br/><br/>24、GC是什么? 为什么要有GC? GC是垃圾收集的意思（Gabage Collection）,内存处理是编程人员容易出现问题的地方，忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃，Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的，Java语言没有提供释放已分配内存的显示操作方法。<br/><br/>25、short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有什么错? short s1 = 1; s1 = s1 + 1; （s1+1运算结果是int型，需要强制转换类型）&nbsp;&nbsp;short s1 = 1; s1 += 1;（可以正确编译）<br/><br/>26、Math.round(11.5)等於多少? Math.round(-11.5)等於多少?&nbsp;&nbsp;Math.round(11.5)==12&nbsp;&nbsp;Math.round(-11.5)==-11&nbsp;&nbsp;round方法返回与参数最接近的长整数，参数加1/2后求其floor.<br/><br/>27、String s = new String("xyz");创建了几个String Object?&nbsp;&nbsp;&nbsp;&nbsp;两个<br/><br/>28、设计4个线程，其中两个线程每次对j增加1，另外两个线程对j每次减少1。写出程序。<br/>以下程序使用内部类实现线程，对j增减的时候没有考虑顺序问题。<br/>public class ThreadTest1&#123;private int j;&nbsp;&nbsp;public static void main(String args[])&#123;&nbsp;&nbsp;ThreadTest1 tt=new ThreadTest1();&nbsp;&nbsp;Inc inc=tt.new Inc(); Dec dec=tt.new Dec();&nbsp;&nbsp;for(int i=0;i<2;i++)&#123;&nbsp;&nbsp;Thread t=new Thread(inc);&nbsp;&nbsp;t.start();&nbsp;&nbsp;t=new Thread(dec);&nbsp;&nbsp;t.start();&nbsp;&nbsp;&#125; &#125;&nbsp;&nbsp; private synchronized void inc()&#123;&nbsp;&nbsp;j++;&nbsp;&nbsp;System.out.println(Thread.currentThread().getName()+"-inc:"+j);&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;private synchronized void dec()&#123; j--;&nbsp;&nbsp;System.out.println(Thread.currentThread().getName()+"-dec:"+j);&nbsp;&nbsp;&#125;<br/>class Inc implements Runnable&#123;&nbsp;&nbsp;public void run()&#123;&nbsp;&nbsp;for(int i=0;i<100;i++)&#123;&nbsp;&nbsp;inc();&nbsp;&nbsp;&#125; &#125;&nbsp;&nbsp;&#125; class Dec implements Runnable&#123;public void run()&#123;&nbsp;&nbsp;for(int i=0;i<100;i++)&#123; dec(); &#125; &#125;&nbsp;&nbsp;&#125; &#125;<br/><br/>29、Java有没有goto?&nbsp;&nbsp;java中的保留字，现在没有在java中使用。<br/><br/>30、启动一个线程是用run()还是start()?启动一个线程是调用start()方法，使线程所代表的虚拟处理机处于可运行状态，这意味着它可以由JVM调度并执行。这并不意味着线程就会立即运行。run()方法可以产生必须退出的标志来停止一个线程。<br/><br/>31、EJB包括（SessionBean,EntityBean）说出他们的生命周期，及如何管理事务的？</span>
]]>
</description>
</item>
<item>
<link>http://narmy.cn/linux/read.php/17.htm</link>
<title><![CDATA[今天突发奇想，整好了双线]]></title> 
<author>lengyuex &lt;lengyuex@gmail.com&gt;</author>
<category><![CDATA[有用的 &#124;&#124; 有趣的]]></category>
<pubDate>Tue, 14 Apr 2009 01:29:24 +0000</pubDate> 
<guid>http://narmy.cn/linux/read.php/17.htm</guid> 
<description>
<![CDATA[ 
	<span style="font-family: courier new;">对于管理先锋网，走学校网，而平时上网寝室用网通，我就得经常换线，换来换去的，<br/><br/>相当麻烦，以前买过一个网卡，今天早上寝室人都上课去了，正好再次试验一下，不<br/><br/>影响他们上网，呵呵。<br/><br/>换了个U口，插上USB网卡，在windows 上开始双线之路。<br/><br/>首先是我做主机，共享给别人的设置：<br/><br/>一.新建一个adsl设为共享，将本地连接3(也就是U口网卡)也设为共享。共享网卡设为本地连接1(即寝室内部局域网)<br/><br/>2.配置本地连接3：<br/><br/><div class="code"><br/>ip:58.154.168.54(这是我用的校园网IP)<br/>mask:255.255.255.0<br/>geteway:58.154.168.254(二舍的默认网关)<br/><br/></div><br/><br/>3.配置本地连接1(寝室内部共享网卡)：<br/><br/><div class="code"><br/><br/>IP:192.168.170.1(根据内部局域网自己设)<br/>MASK:255.255.255.0<br/>GATEWAY:不要设(如果是主机的话)<br/></div><br/><br/>正常连接ADSL。<br/><br/><br/>4.添加路由：<br/><br/>要是不添加路由，数据就不知道你要走哪条线。我们添加路由的目的就是：请求访问学校内部IP的时候<br/><br/>走本地连接3，访问其它IP时就走ADSL。<br/><div class="code"><br/>route add 219.216.64.0 mask 255.255.192.0 58.154.168.54<br/>route add 202.118.0.0 mask 255.255.224.0 58.154.168.54<br/>route add 202.199.0.0 mask 255.255.240.0 58.154.168.54<br/>route add 58.154.160.0 mask 255.255.224.0 58.154.168.54<br/>route add 58.154.192.0 mask 255.255.192.0 58.154.168.54<br/><br/></div><br/><br/>这是我学校的IP情况，根据自己情况设定就行了。<br/><br/>5.重新连接一下ADSL，使Default Gateway变成ADSL的Gateway.<br/><br/>这样就OK了。<br/><br/>二。如果我不做主机，是别人做主机。这样就少了ADSL。<br/><br/>路由就要加上一条，也就是<div class="code"><br/><br/>route add 0.0.0.0 mask 0.0.0.0 192.168.170.1</div><br/><br/>意思就是其它的网站走别人的共享。<br/><br/>其它都一样。省去ADSL一步就OK。<br/><br/>完整的路由添加就是：<br/><br/><div class="code"><br/>route add 219.216.64.0 mask 255.255.192.0 58.154.168.54<br/>route add 202.118.0.0 mask 255.255.224.0 58.154.168.54<br/>route add 202.199.0.0 mask 255.255.240.0 58.154.168.54<br/>route add 58.154.160.0 mask 255.255.224.0 58.154.168.54<br/>route add 58.154.192.0 mask 255.255.192.0 58.154.168.54<br/>route add 0.0.0.0 mask 0.0.0.0 192.168.170.1<br/><br/><br/></div><br/><br/>好了，尽情享受双网卡带来的方便吧。哈哈。<br/></span>
]]>
</description>
</item>
<item>
<link>http://narmy.cn/linux/read.php/6.htm</link>
<title><![CDATA[白领职场必懂得22条潜规则]]></title> 
<author>lengyuex &lt;lengyuex@gmail.com&gt;</author>
<category><![CDATA[有用的 &#124;&#124; 有趣的]]></category>
<pubDate>Tue, 24 Mar 2009 10:14:07 +0000</pubDate> 
<guid>http://narmy.cn/linux/read.php/6.htm</guid> 
<description>
<![CDATA[ 
	<span style="font-family: Courier New;">第一条 必须有一个圈子。无论如何做都是画地为牢：不加入一个圈子，就成为所有人的敌人；加入一个圈子，就成为另一个圈子的敌人；加入两个圈子，就等于没有加入圈子。只有独孤求败的精英才可完全避免圈子的困扰——这种人通常只有一个圈子，圈子里只站着老板一个人。<br/><br/>　　第二条 必须争取成为第二名。名次与帮助你的人数成正比——如果是第一名，将因缺乏帮助而成为第二名；而第二名永远是得道多助的位置，它的坏处就是永远不能成为第一名。 <br/><br/>　　第三条 必须理解职责的定义。职责是你必须要做的工作，但办公室的生存定律是，职责就是你必须要做的工作之外的所有工作。 <br/><br/>　　第四条 必须参加每一场饭局。如果参加，你在饭局上的发言会变成流言；如果不参加，你的流言会变成饭局上的发言。 <br/><br/>　　第五条 必须懂得八卦定理。和一位以上的同事成为亲密朋友，你的所有缺点与隐私将在办公室内公开；和一位以下的同事成为亲密朋友，所有人都会对你的缺点与隐私感兴趣。 <br/><br/>　　第六条 必须明白加班是一种艺术。如果你在上班时间做事，会因为没有加班而被认为不够勤奋；如果你不在上班时间做事，你会被认为工作效率低下而不得不去加班。 <br/><br/>　　第七条 必须熟练接受批评的方法。面对上司的判断，认为你没错，你缺乏认识问题的能力；认为你错了，你没有解决问题的能力——接受错误的最好方式就是对错误避而不谈。最后一条，不准和老板谈公正。 <br/><br/>　　第八条 必须理解“难得糊涂”的词义。糊涂让你被人认为没有主见，不糊涂让你被人认为难以相处——“难得糊涂”在于糊涂的时机，什么时候糊涂取决于你不糊涂的程度。 <br/><br/>　　第九条 必须明白集体主义是一种选择。如果你不支持大部分人的决定，想法一定不会被通过；如果你支持大部分人的决定，将减少晋升机会——有能力的人总是站在集体的反面。 <br/><br/>　　第十条 必须论资排辈。如果不承认前辈，前辈不给你晋升机会；如果承认前辈，则前辈未晋升之前，你没晋升机会——论资排辈的全部作用，是为有一天你排在前面而做准备。 <br/><br/>　　第十一条 必须禁止智力排行。天才应避免得罪庸才，虽然天才一定会得罪庸才——庸才总不太喜欢和天才相处。 <br/><br/>　　第十二条 必须学会不谈判的技巧。利益之争如果面对面解决，它就变得无法解决；如果不面对面解决，它就不会被真正解决。一个最终原则是，利益之争从来就不会被解决。 <br/><br/>　　第十三条 必须理解秘密的存在意义。如果一件事成为秘密，它存在的目的就是被人知道；如果一个秘密所有人都知道，你必须说不知道；同理，如果一个秘密所有人都说不知道，则可以推断，所有人都知道。 <br/><br/>　　第十四条 必须理解开会是一种道。道可道，非常道；名可名，非常名。开会不能不发言，发言不能有内容。如果你的发言有内容，最好选择不发言——开会的目的是寻找一个解决问题的方法，在大部分情况下，这个方法就是开会。 <br/><br/>　　第十五条 必须让婚姻状况成为秘密。隐婚人士在办公室谈情是一场喜剧，单身人士在办公室谈情是一场悲剧。最好的结果是，已婚人士获得一场办公室爱情；最坏的结果是，未婚人士获得一场办公室婚姻。最后一条，不到万不得已，永远不要打老板女秘书的主意。 <br/><br/>　　第十六条 必须掌握一种以上高级语言。高级语言包括在中文中夹杂外语、在怒骂之中附送奉承、在表达保密原则同时揭露他人秘密、在黄段子中表达合同意向。语言技巧高是下乘，发言时机好是上乘。使用高级语言但时机不对，不如使用低级语言但时机正确。 <br/><br/>　　第十七条 必须将理财作为日常生活的一部分。主管在身边的时候，要将手机当公司电话；主管不在身边的时候，要将公司电话当私人手机；向同事借钱，不借钱给同事；陌生人见面要第一个埋单，成为熟人后永远不要埋单。最后一条，捐钱永远不要超过你的上级。 <br/><br/>　　第十八条 必须明白参加培训班的意义。培训班不是轻松的春游，它的目的是学习你工作职责之外的知识；由于学习的知识在你工作职责之外，培训班可以当做一次轻松的春游。 <br/><br/>　　第十九条 必须学会摆谱。如果你很靠谱但不摆谱，大部分人都认为你不靠谱。如果你不靠谱但经常摆谱，所有人都认为你很靠谱。 <br/><br/>　　第二十条 必须懂得表面文章的建设性。能做会议幻灯片的，不能私下讨论；可写报告的，不能口头请示，如果一件事你已经完成，但没有交计划书，你等于没有做；如果一件事你没有去做，但交了计划书，你可以当它已经完成——毕竟所有学过工商管理的老板都固执地认为，看计划书是他的事，执行是下面的事。 <br/><br/>　　第二十一条 必须与集体分享个人成功。所有人都是蜡烛——要点燃自己并且照亮别人，如果你只照亮自己，你的前途将一片黑暗；如果你只照亮别人，你将成为灰烬。 <br/><br/>　　第二十二条 必须遵守规则。要成为遵守规则的人，请按显规则办事；要被人认为是一个遵守规则的人，请按潜规则办事。显规则和潜规则往往相反，故当二者发生冲突，按显规则说，按潜规则做，是为最高原则。 补充：如果具备这22条，估计成为一个合格的打工族问题不大，有所成就可能很难。我的生存法很简单 高标处世 低调做人 坦诚真实多好啊 ( 来源：<a href="http://bbs.51job.com)" target="_blank">http://bbs.51job.com)</a></span>
]]>
</description>
</item>
<item>
<link>http://narmy.cn/linux/read.php/4.htm</link>
<title><![CDATA[主要Linux 平台高可用HA集群软件简介及软件下载]]></title> 
<author>lengyuex &lt;lengyuex@gmail.com&gt;</author>
<category><![CDATA[有用的 &#124;&#124; 有趣的]]></category>
<pubDate>Sat, 21 Mar 2009 15:45:56 +0000</pubDate> 
<guid>http://narmy.cn/linux/read.php/4.htm</guid> 
<description>
<![CDATA[ 
	<span style="font-family: Courier New;">主要Linux 平台高可用集群软件(High Availability Cluster- HA)简介及软件下载<br/>================================================<br/>本文针对Linux平台的集群软件进行简单的介绍.<br/>转载请勿修改 作者: nntp 最后更新:20070704<br/><br/>Linux集群主要分成三大类( 高可用集群， 负载均衡集群，科学计算集群)<br/><br/>高可用集群( High Availability Cluster)<br/>负载均衡集群(Load Balance Cluster)<br/>科学计算集群(High Performance Computing Cluster)<br/>================================================<br/><br/><br/>高可用集群(High Availability Cluster)<br/><br/>常见的就是2个节点做成的HA集群，有很多通俗的不科学的名称，比如"双机热备", "双机互备", "双机".<br/>高可用集群解决的是保障用户的应用程序持续对外提供服务的能力。 (请注意高可用集群既不是用来保护业务数据的，保护的是用户的业务程序对外不间断提供服务，把因软件/硬件/人为造成的故障对业务的影响降低到最小程度)<br/><br/>Linux平台常见的高可用集群 有这些:<br/><br/>1.&nbsp;&nbsp;RedHat 公司 的 开放源代码RedHat Cluster Suite, 简称RHCS . (产品介绍<a href="http://www.redhat.com/solutions/clustersuite/)" target="_blank">http://www.redhat.com/solutions/clustersuite/)</a><br/><br/>- RHCS实际上是一个套件，除了现在提到的高可用集群软件，还包含了一个基于LVS的负载均衡软件.<br/><br/>- RHCS包含的集群软件，是GPL协议下开放源代码的集群系统. <br/><br/>- RHCS目前的版本有 RHCS v3和 v4,分别对应于RedHat 企业版Linux的 3.0家族和4.0家族.<br/><br/>- RHCS是一个独立的产品，不包括在RedHat Enterprise Linux当中，无论是购买还是下载，都是单独存在的.<br/><br/>RHCS的获得:<br/><br/>RHCS的获得有三个途径:<br/><br/>a. 从redhat 的官方销售渠道购买，得到的是RedHat RHCS产品的二进制代码(光盘或直接从RHN-RedHat Network下载)，源代码，以及支持和升级服务.<br/>b. 从redhat 的官方站点下载SRPM包，编译并安装. 无原厂商业支持和升级服务. 这里下载 (<a href="ftp://ftp.redhat.com/pub/redhat/linux/enterprise/4/en/RHCS" target="_blank">ftp://ftp.redhat.com/pub/redhat/linux/enterprise/4/en/RHCS</a>和<a href="ftp://ftp.redhat.com/pub/redhat/linux/enterprise/3/en/RHCS)" target="_blank">ftp://ftp.redhat.com/pub/redhat/linux/enterprise/3/en/RHCS)</a><br/>c. 从centOS官方站点下载RHCS的二进制代码包并安装，无原厂商业支持和升级服务. 这里下载(<a href="http://mirror.centos.org/centos/4/csgfs/" target="_blank">http://mirror.centos.org/centos/4/csgfs/</a>, 请阅读此目录中的README文件)<br/><br/><br/><br/>2. Novell 公司 的 开放源代码高可用集群HA套件<br/><br/>Novell 公司并购了欧洲Linux第一大厂SuSE之后，成为全球能够抗衡RedHat的主要力量. <br/><br/>SuSE企业版Linux 带有一套开放源代码的HA集群软件，包括 HA project的heartbeat, heartbeat-ldirectord, heartbeat-pils, heartbeat-stonith, 集群关联的存储软件drbd, 虚拟IP的 src_vipa软件.和RHCS不同的是，SuSE/Novell 企业版Linux自带的 HA集群软件并非一个独立的软件，如上介绍，而是由不同的开放源代码项目提供的不同部分的程序。<br/><br/>集群软件的获得:<br/>本集群软件组件已经附带在SuSE Linux Enterprise Server 光盘中(SLES9, SLES10), SuSE Linux Enterprise Server(SLES9, SLES10)的光盘，可以免费从download.novell.com获得，并提供2个月的在线网络更新服务. 用户只需要在novell站点上免费注册一个novell 站点账号，就可以下载SLES9, SLES10的所有光盘ISO.<br/><br/>3. Novell 公司的Novell Cluster Service<br/><br/>Novell 在败落前，曾经是一家非常伟大的公司，有着非常雄厚的技术力量。 早在10多年前，Novell公司就在集群领域独树一帜，是当时唯一能够在PC服务器上构建出32节点集群的厂商.<br/>Novell收购SuSE公司之后，将原来在Novell netware操作系统上的大量企业级应用移植和整合到了SuSE Linux Enterprise Linux平台, Novell 当时名震集群领域的Novell Cluster Service 也被整合移植到了Linux平台.<br/><br/>Novell Cluster Service是一个商业系统，并非开放源代码产品<br/><br/>这里可以看到细节<br/><a href="http://www.novell.com/products/openenterpriseserver/ncs.html" target="_blank">http://www.novell.com/products/openenterpriseserver/ncs.html</a><br/><br/>产品的获得<br/><br/>直接从Novell 公司购买.<br/><br/>4. Steeleye Lifekeeper for linux (产品介绍<a href="http://www.steeleye.com/)" target="_blank">http://www.steeleye.com/)</a><br/><br/>steeleye 公司是集群行业非常著名的公司，他们的集群系统最早是AT&T 贝尔实验室开发的，后来被卖给了金融行业的著名IT公司NCR公司。(不少朋友到ATM取钱的时候也许会看到NCR制造的ATM机). lifekeeper集群的历史非常悠久，后来steeleye又得到了几个从当时的巨头DEC跳槽来的核心开发人员.因此lifekeeper的构架和品质是有非常好的口碑的.<br/><br/>产品获得<br/><br/>a. 从steeleye官方渠道申请试用版<br/>b. 从steeleye 官方购买<br/><br/>5. HP MC/Service Guard for linux (<a href="http://h71028.www7.hp.com/enterprise/cache/6468-0-0-0-121.aspx)" target="_blank">http://h71028.www7.hp.com/enterprise/cache/6468-0-0-0-121.aspx)</a><br/><br/>HP在和Compaq合并之前，在HP-UX平台有一套旗舰级的高可用集群系统(MC/SG for HP-UX)，被广泛部署在各种关键业务计算领域。比如银行，电信，金融等等。主要的硬件平台是PA-RISC架构的小型机和中型机系统.<br/>Compaq在和HP合并之前，在Alpha 平台有一套旗舰级的高可用集群,叫做(TruCluster).被广泛部署在各种关键业务计算领域，比如国防，航天，制造等等。主要的硬件平台是Alpha架构的小型机和中型机.<br/>随着两个公司的合并，两套著名的集群系统也完成了合并，新的产品仍旧叫做MC/SG,但是可以跑在PA-RISC, IA, IA64平台.<br/>5年前，HP将MC/SG集群系统移植到了linux平台，并发展至今.&nbsp;&nbsp;HP MC/SG for linux有着非常高的品质和长期在高度关键业务要求的领域发展的背景。<br/><br/>软件的获得:<br/><br/>从HP官方渠道购买并获得技术支持和升级服务.<br/><br/>6. 开放源代码的 HA 项目 (<a href="http://www.linux-ha.org/)" target="_blank">http://www.linux-ha.org/)</a><br/><br/>linux-HA 项目历史悠久, 很多linux 发行附带的HA集群都是采用了linux-HA 的heartbeat系统和相关的组件.需要构建完全的开源，自由而且免费的高可用集群的用户可以选择.<br/><br/>软件获得:<br/>免费下载，没有商业支持和商业升级服务.<br/><br/>7. Turbolinux&nbsp;&nbsp;高可用集群系统<br/><br/>Turbolinux 这几年发展的颇不顺利，从创始人走人到公司在日本的股权变动. 颇让人担忧。<br/><br/>TurboLinux 的高可用集群软件有两个.<br/><br/>a. TurboLinux Cluster HA 3.1 <br/>b. TurboLinux8 ClusterPro<br/><br/>因为都没有在具体的项目中深入用过，不做更多解释.<br/><br/>软件获得:<br/><br/>从Turbolinux 官方购买，并获得技术支持和升级服务.</span>
]]>
</description>
</item>
</channel>
</rss>