能力值:
( LV2,RANK:10 )
|
-
-
51 楼
复制回去看看,看到这么多人顶应该不错的啊
|
能力值:
( LV2,RANK:10 )
|
-
-
52 楼
不过瘾等待中!!!!!!
|
能力值:
( LV2,RANK:10 )
|
-
-
53 楼
看楼主的文章如旅3秋啊,期待下篇.
|
能力值:
( LV2,RANK:10 )
|
-
-
54 楼
怎么没有了~~~~期待下篇~~~
|
能力值:
( LV2,RANK:10 )
|
-
-
55 楼
看楼主的文章如旅3秋啊,期待下篇.
|
能力值:
( LV2,RANK:10 )
|
-
-
56 楼
下面没有了。。
|
能力值:
( LV2,RANK:10 )
|
-
-
57 楼
没有了?????
|
能力值:
( LV2,RANK:10 )
|
-
-
58 楼
好文章,很贴切我们这帮毕业的孩子啊。。
|
能力值:
( LV8,RANK:130 )
|
-
-
59 楼
下篇就这接书上的介绍就差不多了哈!
|
能力值:
( LV2,RANK:10 )
|
-
-
60 楼
不错
顶一下
|
能力值:
( LV2,RANK:10 )
|
-
-
61 楼
牛人的小说必折射着自己所经历的辛酸历程啊,支持
|
能力值:
( LV2,RANK:10 )
|
-
-
62 楼
期待下篇!!呵呵 挺好看的!!
|
能力值:
( LV3,RANK:20 )
|
-
-
63 楼
lz写的很好哈,受教了
|
能力值:
( LV2,RANK:10 )
|
-
-
64 楼
写的不错,顶一下
|
能力值:
( LV2,RANK:10 )
|
-
-
65 楼
狂人兄怎么不更新了?
|
能力值:
( LV2,RANK:10 )
|
-
-
66 楼
Mark下.期待后续...
|
能力值:
( LV2,RANK:10 )
|
-
-
67 楼
很希望国内能拍出一部关于程序员成长方面题材的影视作品!
|
能力值:
( LV2,RANK:10 )
|
-
-
68 楼
都是牛人啊!
|
能力值:
(RANK:350 )
|
-
-
69 楼
楚狂人可能最近工作繁忙,或者在泡mm
期待更新......
|
能力值:
( LV2,RANK:10 )
|
-
-
70 楼
从头看到尾,感谢狂人楚的优秀小说。
本人觉得,相比之下,文笔更胜《疯狂的程序员》一筹。
从书中可以看到作者自己的影子,不知对否?
|
能力值:
( LV2,RANK:10 )
|
-
-
71 楼
从书中可以看到作者自己的影子,不知对否?
你没认真读,请再读一遍..........
|
能力值:
( LV2,RANK:10 )
|
-
-
72 楼
我本楚狂人,凤歌笑孔丘
|
能力值:
( LV2,RANK:10 )
|
-
-
73 楼
怎么不写了呀
|
能力值:
( LV4,RANK:50 )
|
-
-
74 楼
四 入套
那一年的第一场雪,因为刀郎的流行而被铭记。同年七月,我去杭州就职。我以为会碰到久违的楼先生,但是他却已经跳槽了。数月之前,他还在积极向我表述到Z公司就职的好处。而另一方面,他却在准备跳槽,这是我离开学校之后,第一次碰到我觉得不可思议的事情。
楼先生是精明人。一个七八十余人的中小型民营企业,有无HR根本就是一件无关紧要的事情。那时候Z公司效益尚不错,除了楼先生之外,另外还有一个HR汪。但是当资金捉襟见肘的时候,自然先拿HR之类的人员开刀。以至于后来很长时间都是副总经理管财务兼HR。楼先生龙游浅水,自然不玩了,一溜烟的去了欧洲,自此再无音讯。
我第一天去上班时,入职手续还没办,被前台小姐阻挡在会客厅。说要我等一会儿,但这一会却等了好几小时,无聊极了。
一会有个人过来,这人很年轻,文绉绉的穿着白裤子白T恤,却又黑社会似地戴着墨镜,剃了个光头。看着极不协调。他一过来就开了一瓶饮料递给我,然后指着角落处的沙发说:
“那边有报纸杂志。”
对这人我极为感激,心想滴水之恩当涌泉相报,何况一瓶饮料,已经数不清多少滴了。不过君子报恩,十年不晚。等在这里混熟之后,再徐图报答。
最后HR汪终于元神归位,给我办了手续。所谓的手续只是把我介绍给部门经理认识罢了。这时还没有签劳动合同 ,说是先试用半年。
办完手续,HR汪指着旁边豪华办公室里说:“你看,我们老板年轻吧?”
我一看,原来就是白衣服光头墨镜那人。怪不得如此怪异,原来这人就是大老板。他姓图。图什么呢?当然图钱。不过我们不能这么叫他,一般叫他图总。
我的部门经理姓张,背地里我们都叫他张老大。张老大的座位就在我对面。他的四周都是电脑,他自己则端坐中央,活像一尊佛像。他一般都始终端坐在那里,比我上班来得早,并比我下班更晚。所以对我来说,他始终都在哪里。他不断敲击键盘,表情却永远不变。
我虽然就坐在对面,但是并没有一个人主动来和我交代我需要做点什么。开始虽然有一阵子忙,但是都是安装电脑、配置软件之类的琐事。而且完了之后就完全无事可干了。我只好坐在那里上网。这是一种令人窒息的空闲。我本以为我既然已经开始工作了,自然会懂得该干点什么,但是非常惊恐的是,我完全不懂我应该做什么。
其实后来这种惊恐始终伴随着我的职业生涯。直到现在,它也依然偶尔出现,依然是我工作中最感觉不安的大问题。
我旁边坐了一个只比我大概稍微早来半个月的黑脸大汉。他姓陈,我和他平级,我决定叫他陈兄弟。根据我的观察,在应该做点什么方面,这位仁兄并不比我懂得更多。他一直在全力的开发一个网络代理程序,仅仅是为了让他能够穿过公司的防火墙用QQ聊天。
窒息了两周之后,我无法再忍受了。我决定采取行动。我故意加班到很晚,直到几乎所有的同事都已下班。然后我走到佛像面前。
“张Z……”我犹豫了一下,说:“我已经熟悉了一段时间。什么时候可以给我安排实际的工作呢?”
张先生正在电脑堆里编码编到兴奋,忽然才发现我还没有走,回过神来,想了一下。显然他并没有想好应该怎么回答我的问题。不过他采用了缓兵之计,他说:
“明天吧。”
我心中大喜,我要的就是这个。
二十四小时之后,又到了同样的情形。他写代码写得很high,我却依然是无事可干。我照样走到他旁边,和他说:“张Z,昨天您说我们今天会安排任务……”
他醒悟过来,回想起了昨天的事。缓兵之计已经用过一回了,今天当然不能再用了。
他终于给我分配了任务。不过我认为他分配这个工作完全是突然的。在我的突然袭击之下,他随手就把他手头最困绕的问题交给我了。
我的任务依然是上网。而且这次得更加疯狂的上网了。本质而言,问题是这样的:那时他们为金融公司的办公室里,大量的安装了无盘的计算机。这倒不是为了安全,而是因为那时硬盘还比较昂贵。竞争对手也提供了类似的无盘站。无盘站是没有硬盘的计算机。但是,计算机还是需要外存才能正常工作呀。所以,就是用网络上的服务器共享出来的硬盘。通过虚拟成本地硬盘,让无盘站可以像有盘站一样正常的运作。所以,这些电脑保存文件或者读取文件,实际上是通过网络来进行的。也就是说,这些数据穿过了网络,直接保存到了服务器的硬盘上。所有的电脑那时都清一色的安装着Windows98。他们出售的就是小型的工控机,里面安装着一种简化的UNIX系统。
这些无盘站本地既然没有硬盘,当然也不可能安装着Windows98。实际上他们通过插在网卡上的固化存储芯片中的小程序启动。这个小程序一启动就通过网卡向服务器请求数据,服务器就将Windows 98通过网络传递过来,并使计算机就像有盘电脑一样正常的启动起来。
那时所有的竞争对手都是互相抄袭,所提供的功能和性能都是大同小异。而且连毛病都是类似的。就是Windows启动之后,自己开发的Windows的虚拟磁盘驱动所产生的硬盘有问题。如果在上边保存普通的文件,那是一点问题都没有。但是如果把分页交换文件放在上边,则当系统内存消耗巨大的时候,会出现死机 的现象。
分页交换文件是一个特殊的文件。硬件的内存数量是依赖于机主的钱包的。但是Windows总是认为系统中的内存为4G,即使主板上实际只插了一根32M的内存条。这样一来,一部分内存数据就必须放在硬盘上,才能满足超越硬件内存数量的使用。当需要新的空间时,就把一部分物理内存的数据写入硬盘,然后将腾出的空间挪作他用。当要使用已经写到硬盘上的内存数据时,就将他们重新调入物理内存。相应的物理内存的一部分就被写入硬盘上。这看起来像是一个交换过程。而容纳这些内存数据的硬盘空间就是一个文件,被称为分页交换文件 。这个文件看上去和其他文件没什么区别,就很简单的放在硬盘上。当它放在通过网络虚拟的硬盘上的时候,问题出现了。
这个问题倒是很容易重现 。后来在我的职业生涯中我碰到过很多极难重现的BUG。相比而言,这个应该算容易解决。只要疯狂消耗内存,就可以很快重现死机。如何消耗内存呢?这要看哪个网站能耗内存了。那时候的门户网站一个比一个花里胡哨(当然,现在也好不到哪里去)。最早我们是打开新浪的主页,后来我更推崇搜狐。那一个页面成百上千的的flesh绝对不是吃素的。根据我的经验,搜狐开到10个左右,系统就已经慢得不行了。此时虽未必就死,但13个必死无疑。我还没有成功的开到过第14个。
如果没有用虚拟磁盘,而是用本地磁盘的话,Windows98也不是能无节制的开搜狐的。估计能开到15个吧。之后系统变得很慢,有异常现象出现:比如按钮变得很大,字体不对了,比如窗口的底色消失了,变成一个纯白的空窗口。但是不会死机。如果小心的把这些搜狐关掉,最后还能恢复正常。
有趣的是,市面上提供给金融公司使用的无盘系统,全是一样的毛病。当然,如果我们能首先攻克这个问题,毫无疑问就能取得竞争优势。当客户犹豫不决时,我们就可以毫不客气的给用户演示开搜狐了,就可以高下立判。
至于如何解决这个难题,对我而言,这确属一个难题。
老实说,除了一遍又一遍的打开搜狐,然后看着Windows98死掉,然后重启电脑之外,我几乎什么都做不了。这个死机是奇特的。开始的时候是失去响应,但是鼠标还能动。但是动一动鼠标之后,马上鼠标也不能动了。
死机和蓝屏不同。蓝屏一般都是系统知道有异常发生。会在天塌地陷之前,用一个文件记录下崩溃之前的情景 ,以供后来者研究这次事故。但是死机不会。一般的说,死机之后,系统依然在运行。只不过陷入某种死循环之类的状况了。
如果有调试器的话,会很有帮助。但是死循环的话,以我后来多年的经验,用调试器去看往往是看不出什么端倪的。除非运气特别好。因为Windows的一个死循环可能运行上万条指令,一步一步的跟过来,跟了后边又忘记了前边,最多也只知道Windows跑了一大圈又回来了,完全不知道这是为什么。
网络虚拟磁盘的代码是有的。不过这似乎没有太大的用处。因为死机的是Windows本身,死机似乎并不是在网络磁盘的驱动中发生的(我花了几乎一周的时间去证实这一点)。或者说,因为我们加入的网络磁盘,导致了Windows发生死机。这其中当然存在某种联系。但是,网络磁盘和Windows其他的组件之间的联系千头万绪,什么才是导致死机的根源呢?而且Windows也并没有代码。一切只能蒙。
我坐在我的座位上。现在我有事可干了,但是情况并没有好转。我依然在开网页。而且总是开搜狐。
开累了我就喝喝水,喝完水上厕所。总之我不能闲着,我必须产生价值才行。我不能整天望着天花板下面的日光灯发呆。而且这是我的第一个任务。如果第一个任务就玩不成,别人有什么理由交给我第二个任务呢?
我要冷静——喝水——思考。
确实,我读过很久的书。也做过很多项目。我碰到过很多很多的问题。而目前的这一个,它的确,是和内存有关。因为它发生的条件有两个,一个就是分页交换文件放在网页上。而另一个条件,就是内存极度耗竭。
我在以前也见过内存枯竭的现象,不用开那么多搜狐。如果我写的程序有内存泄漏,迟早都会导致内存耗竭。所谓的泄漏,是指分配过的内存忘记释放。因为计算机程序中一般存在许多的反复行为:比如一个函数被反复的调用无数次。即使这个函数中“泄漏”了很少的内存,因为反复的被调用,也会迟早导致内存资源的耗光。
有许多服务程序需要长期稳定的运行(比如运行数年)。一旦程序中有微小的内存泄漏,就可能带来巨大的困绕。因为程序可能每隔几天、数月或者更长时间因为内存枯竭而崩溃。留下这样的BUG是轻松惬意的事,查找这样的疏忽却需要付出巨大的努力。
这甚至导致一些项目的领导拒绝使用C语言。他们改使用java。他们认为,C语言或者C++无法避免内存泄漏,因此大型服务程序项目不能使用C系列的语言。
当然,这样的想法实在是贻笑大方。用某人的话说,也就是所谓“拉不出屎怪马桶不好”。
java使用垃圾回收机制自动回收内存。这一机制用C语言也完全可以做。当然,一般我们不做。那是因为,高明的猎手,是没有必要扛着导弹去打兔子的。一把精准的猎枪就足矣了。
那时刚步入社会。一个深刻的感受就是:命背不要怪社会。真的什么事情都可能发生。
本来Z公司已经安排了住宿。我只管自己买床,兴冲冲搬进去住就是了。但是到了之后却发现进不了房间,只能停在客厅里。
原来分配给我的房间是有别人住着的。只是那人已经被调到广州分公司去了。人走了,东西还没搬,钥匙却带走了。
于是我只能睡客厅。客厅实际就是一个宽阔的杂物间,因为每个人多余的东西都堆在客厅里。而且又没有纱窗,时值盛夏,半夜蚊虫叮咬,苦不堪言。大概因为空间广阔,点了蚊香也不起作用。说是等调走的人把钥匙寄来。但是这一等就是二十多天。不要说从广州寄,就是从月球寄,也应该到了。
我醒悟过来,在这样的公司,切莫听信低级职员的承诺。大小事务,非去找领导哭诉不可。
我只好写邮件给主管杂务的副总经理。副总很生气,后果非常严重地打电话给那人说一周之内必须把钥匙寄来。
不过我之所以能忍受差不多一个月睡杂物间,也是因为我平时根本就没多少时间呆在宿舍里。晚上九点多下班,回家随便洗洗就睡了,脑子里还在想着死机的事情。为什么死机呢?脑子里一片混乱,想着想着就做梦了,梦里也是死机的事情。四处下里除了蚊子嗡嗡的声音之外,就剩下无数个死着的搜狐了。而早上一清醒过来的时候,往往就能有新的念头,赶紧擦把脸就往公司里赶,恨不得马上坐在电脑前开始试验。
我想了很多方法。比如说排除。因为我们自己装了个虚拟磁盘的驱动,Windows98才会死机,那么死机要么就是在虚拟磁盘的驱动里死机的,要么就不是。当然“是”的情况是是最好的。这样至少就知道了死机的来源,手里又有代码,可以慢慢修改去避免死机。另一种情况就是不是。这个结果虽然不那么理想,但是至少缩小了范围。在这个无奈的状态下,范围缩小一点是一点。
我花了差不多一周的时间才确定死机确实不是发生在虚拟磁盘驱动中。后来总结出一个虽然看似很蠢,但是却确实有效的方法。就是定义一个全局变量,作为计数器。
所谓的全局变量就是不定义在任何函数内的变量。这样的变量任何函数都可以访问。比如我在所有的函数外边定义一个调试用的计数器:
unsigned long dbg_counter = 0;
这是一个被初始化为0的无符号整数。之后我在每个函数中访问它。无论这个虚拟磁盘的驱动多么复杂,它总是由一系列的函数组成的 。我可以在任何函数进入的时候,将这个变量加1,在任何函数返回的时候,将这个变量减1。这使我不得不修改每个函数,大致都修改成下面这个样子:
void my_function()
{
// 这里加入计数器自增
dbg_counter ++;
……
// 返回前减1
dbg_counter --;
return;
}
实际上只增加两句话,这对函数本身原有的功能并没有什么影响。但是这是探测死机的一个好办法。如果执行这些函数的过程中有一处发生了死机,那么dbg_counter一定会大于0。如果死机和这些函数没关系,那么dbg_counter一定会是0。这个变量就在内存中,用调试器看一下就可以了。
当然,如果探测结果表明dbg_counter不是0,我们可能希望进一步能确定死机发生在哪个函数中。这也有办法:就是把这些添加在函数中的测试代码一个一个的去掉即可。一定会有这样一个函数:去掉测试代码之后,死机的时候发现dbg_counter是0了。那么死机就是发生在这个函数中的。
在程序的流程很熟悉的情况下,用不着用这么笨的地毯式轰炸的方法。如果清楚程序从A执行到B,中间死机了,要寻找死机的地点,显然可以用二分法 。不过驱动程序往往不是单路流程,很多函数都可能随时被操作系统调用。
不过我一周的调查结果是:死机的时候,dbg_counter绝对是稳定在0上边了。
按部就班已经失去了方向的情况下,唯一的办法就是先入为主的赌一把了。这样的方法和排除法刚好相反。排除法是找出所有不正确的路径,直到只剩下正确的。而现在我是像福尔摩斯一样,从已有的线索中,先构思出整个事件的来龙去脉,然后再去寻找证据证实它。
死机一般都是死循环、死锁之类的事情。这其中有什么逻辑会造成死循环呢?因为我们的虚拟网络磁盘已经把分页交换文件放到了网络上。也就是说对分页文件的使用已经必须通过网络进行。而且实际上它是用TCP协议来通信的。
如果有这样的情况:
首先可用的物理内存已经很少了,这时候应用程序要求继续分配内存。此时,系统为了满足这次分配,只能访问分页交换文件。
其次,访问分页交换文件是通过虚拟磁盘进行的。虚拟磁盘调用系统中的TCP网络通信功能对网络上的分页交换文件进行访问。
这其实已经隐含了一个问题。就是虚拟磁盘通过网络访问分页交换文件的过程,到底需不需要再次分配内存呢?
从虚拟磁盘一路调用下去到上层的网络驱动程序、还有下层的网卡驱动,一直到数据包被真的发送出去,这些都是由Windows和它的驱动程序一手包办,它可没有说过:“我保证这个过程不分配内存”。
如果这个过程中有内存分配,而此时物理内存确实很紧张,根本分配不出来的话,似乎就有可能导致系统再次必须访问分页交换文件了。
当然,再次的访问必定也面临一样的情况,这样就变成了一个先有鸡还是先有蛋的问题,如此往复循环。
这个死机的原因从理论上是可以说得通的。但是一直到我解决了问题,我都没有去证实过这个过程。程序员毕竟不是侦探,无需向法院控诉肇事者。只要问题能解决就行了。
|
能力值:
( LV2,RANK:10 )
|
-
-
75 楼
mark....
|
|
|