行者无疆 始于足下 - 行走,思考,在路上
少即是多——兼谈对SNS的看法
网络的普及,让知识的获取变得空前便利,也让噪音的弥漫变得防不胜防。 ——题记
1 SNS小议
我一直对SNS持踌躇的态度,这里所说的SNS包括但不限于人人、新浪微博、QQ、Facebook、Twitter等。事实上我也有一段时间曾经非常沉迷于校内网(人人网的前身),也会用Nokia 6670在http://m.xiaonei.com 上发表各种各样的生活琐事和所谓的人生感悟,然后强迫症般地不断刷新刷新,等待着盼望着翘首着“朋友”的回复,尽管这些“朋友”可能有30%完全没见过面,另30%仅仅是点头之交,再30%比较熟但谈不上铁,真正熟的知心朋友可能根本就不在乎你这些烂事——“擦,你个SB,别总在老子面前买萌了”。
大二,我生了一场不大不小的病,挂了七八门不小也不大的课,丢了一个爱的深沉的社团,弄得自己半年深居简出,沉迷网络,靠youku土豆,笑傲江湖勉强度日。都说时间是医治伤痛的良药,回过神来,我发现,在你最最痛苦的时候,哪怕是你最亲最铁的朋友,也不一定能够理解你的痛苦,更何况承担? 没有任何人能够对你的痛苦感同身受,更多的时候,我们需要独力承担,尽管有时独立难支,也要咬牙硬挺。 这之后的半年,我删除了自己所有的校内日志,并开始学习linux、开始补课、开始尝试着重新带一些户外活动,培养一下接班人——虽然名义上我深爱的社团由于种种原因挫骨扬灰、烟消云散了。那半年我过得充实、快乐,不但培养了几个户外的新人,新交了几个朋友,交接了自己的责任和工作,也开始学习linux,进入开源软件的精彩世界。我的大学,前两年围绕着户外,围绕着社团和社团的兄弟们运转,后两年围绕着开源和自由的学习精神运转,我经历过单车旅行路上风雨的洗礼,看过东极岛的日出,矮拉山的彩虹,挂了十几门课,但也学会了linux命令行下运指如飞键如舞蹈的畅快淋漓。
我渐渐的发现,校内上一方面有我很多不大不小的朋友,我想要去的地方和想拍的照片,另一方面这也充斥了各种诸如“萌翻了、美爆了、雷坏了、感动得一塌糊涂了”的所谓放松娱乐甚至是”不分享不是xx人“的垃圾信息。更可怕的是,我逐渐发现,一方面,我在这些网站上,浏览垃圾信息的时间大大超过了”关心朋友“的时间,另一方面,我也许并不需要特别关心绝大多数的朋友,即便是最铁的朋友,他今天吃过什么饭、去了哪些地方,这些也与我没啥大关系。最后的最后,我发现,大量的垃圾式的快餐化的娱乐分享、视频和照片会造成两个极其严重的后果:
-
思考浅薄化。
- 现在的我们,再也难以想象,在某个美好的阳光四溢的午后,合上笔记本,沏壶菊花茶,转一支钢笔,抽一页书签,在一本书上写写画画。更多的时候,我们是坐在书桌前,玩玩游戏、刷刷微博、浏览一篇又一篇的吐槽八卦日志。谈到这里,我不得不说,微博的存在使得思考浅薄化变得愈发严重1。我们没有生活在诗词曲赋的唐宋时代,这个事实使得140字很难表达出某种深刻的思想,更多的是一些日常生活中乌七八糟的文字碎片,这些文字碎片就像肯德基麦当劳里面的薯条一样,蘸上西红柿酱(不蘸也行)就可以吃,随便什么人都可以吃,吃这个东西也不需要什么锅碗瓢盆、烹饪调味。只是这些东西吃完了就是吃完了,没有营养,也没有回味。纵观社会化网络的发展,从Telnet、BBS,到个人Blog,再到微博,我们可以发现,人们想在网络上发表信息变得越来越容易,这也造就了这两年来微博的井喷以及进一步的信息爆炸2。可是无论网络怎么发展,信息怎样爆炸,在我看来,高质量的正面有益信息所占的百分比并没有提高,简单来讲,就是信噪比没有发生大的波动3。我认为Wikipedia是网络时代首屈一指的超高信噪比的网站,但是除了Wikipedia,我还能想起哪些网站,这些网站上的信息都是对我有益而无害的呢?我想不起来。人人不是,FaceBook不是,微博不是,QQ更不是。如果诸位高朋能够找到类似于Wikipedia这样的宝库,请不吝告诉我,我将不胜感激。
- 思考浅薄化的间接后果就是你很难再去花几个小时连续的时间去阅读一本书了,你很难再去花几个小时连续的时间去想一道题的不同解法了。你也很难写出大段的具有逻辑性的精彩文章来,你所剩的只有只言片语,文字碎片。
-
时间碎片化。
- 如果你稍微懂点计算机操作系统原理,你就是知道Context Switch(上下文切换)这个名词,它说的是计算机CPU在切换不同进程时的一种开销。所以分时系统计算机的效率理论上永远也不会达到100%,因为肯定有一部分资源耗费在进程切换中了。说得更通俗一点,我们可以用初中生都知道的有用功和总功的概念来阐述这个观点。比如你想把一桶水从一楼提到十楼,当你耗费了三个包子的体力(这个是总功)终于把水提上来的时候,你会发现,如果不提桶,只提水,只需要耗费两个包子的体力(这个是有用功)就可以了。因为你真正目的是提水,而不是提桶。读者可能说,老兄你这不是废话吗,这么简单地道理还用你磨叽?想提水的话当然需要桶喽。别急。之所以打这个有点荒谬的比方,是因为从吃喝拉撒睡的角度上看,我们的人生就是如此。我们都知道,人的一天24小时(这个是总功),平均有8个小时(这个是无用功)是要耗在床上的(别想歪了哈,我说的是可是正常的睡觉),但是人生下来不是为了睡觉的。人的一辈子可能会干很多事情,比如读书写字画画演讲办企业下馆子,但每个人生下来都不是为了睡觉的。而睡觉又是必不可少的,正如你想提水,水桶是必不可少的一样。在此基础上,我们再来思考,互联网,尤其是SNS,到底怎样使我们的时间支离破碎?为什么大块的无人打扰的时间如此重要?
- 有一个非常著名的理论,叫做一万小时天才理论。这个理论讲的是,一个人,如果想成为某一领域的专家权威,需要至少一万小时的刻苦专业训练,即便这个人是莫扎特、高斯一样的天才,一万小时也概莫能外。为什么你不是下一个马克·扎克伯格4?因为当人家已经编写了几万行代码考虑软件架构的时候,你还在骑着自行车绕着院子转圈;当人家已经在考虑大规模网站的可靠性可扩展性的时候,你还在纠结要不要去听明天早晨八点的课;当人家已经在考虑怎样透过自己的网站改变世界的时候,你还在犹豫着是要考研还是要找工作,找工作是要找外企呢还是体制内的呢。我们已经谈到,我们整个人生的三分之一要耗在睡眠上。而几乎可以肯定的是,对于一般人而言,剩余的16小时时间里,吃喝拉撒至少要占用3个小时的时间。剩下的13个小时,我们的大脑还要进行各种各样的Context Switch,效率肯定也是要大打折扣的。有一个理论讲的是,人同一时间内最多只能关注七件事情5。 深入的思考是容不得别人打扰的,一旦中断,思考的大厦就会崩塌,重建的过程往往循环往复、困难重重。 这就是为什么聪明人只想和更聪明,至少是和自己一样聪明的人一起工作的原因,资深的Hacker更是如此,他们才没有耐心告诉你Apache该怎么配置呢6。
为什么深入的思考如此重要?因为人类的文明已经到了如此的境地,如果没有深入的思考,你就不可能识他人所不识、知他人所不知。大到一项科学理论的创立,小到一项发明的完成,想要影响世界,make a difference, 没有少则几年长则半生的苦苦思索,就想把人类已经发展到如此高度的文明再向前推进哪怕一小步,几乎是不可能的事情。那么,为什么大块的无人打扰的时间如此重要?因为没有大块的无人打扰的时间,就不会有深入的思考。 而微博、QQ、360以及最普通的桌面上搜狐、迅雷新闻首页弹出窗口的存在,弥漫在电脑LED上各种各样的名叫distraction的东西,会让你的思考深度曲线像正弦函数一般,摇摆不定,上下颤动7。
以上讲了这么多,诸位读者可能会觉得我这个人太偏激了。毕竟”世界潮流,浩浩荡荡,顺之者昌,逆之者亡“,发端于第三次工业革命末端的互联网终将引领整个第三次工业革命的潮流,被我这么一说,倒好像成了吞噬人生毁灭梦想的洪水猛兽了。其实我不是这个意思,我热爱互联网,也热爱互联网行业,以及互联网行业的底层设施——开源自由的软件,和互联网行业的高尚品德——自由、分享的精神。任何事情都是一把双刃剑,网络如此,读书也是如此。而我采取的策略就是“取我所需,防我所恶“,核心精神就是本文的题目——“少即是多”。由此这四字箴言延伸而来,具体到生活中(不仅仅是对待互联网),就是:
- 少见些人
- 少说些话
- 多读些书
- 多做些事
2 少见些人
“她们都老了吧,她们在哪里呀,我们就这样,各自奔天涯” —— 朴树《那些花儿》
大学伊始,我非常幸运地加入了旅行者户外。这里有一群人,他们猥琐、腐败、自虐,他们行走、思考,他们始终在路上。他们是行者,而行者是无疆的。就好象命中注定一般,我庆幸来到浙大而没有选择去上交,庆幸提前半年过来上预科,碰巧就看到了这群人,碰巧就加入了这个组织,从此释放了深埋于我血液中骨子里十八年的流浪旅行的冲动。这之后的两年,靠着一辆单车,我几乎走遍了浙江省的各个城市,在中国的版图上画了几条长长的线圈。我热爱这里的人,热爱这里的坦诚相待,热爱这里的无拘无束。我感觉我找到了组织,沉迷其中,不可自拔8。
这之后的两年,我接受了社团的工作,当上了社团的会长,带领着一群人山山水水并和学校团委保守派做不朽的抗争,见识到了比我早四年的学长和比我晚四年的学弟,见证了一个社团由巅峰到低谷到在我手中彻底除名毁灭最后又凤凰涅磐浴火永生的全过程,这期间当然免不了人员的去留摩擦,以及日久天长的隔阂和疙瘩。有的时候我常常分不清楚,我究竟是热爱这个组织多一点还是热爱这个组织里的人多一点,又或是,我两者都不爱,我只爱旅行,爱组织爱人只是因为爱屋及乌?
什么是真正的行者?行者最宝贵的精神是什么?行者仅仅是骑着单车去拉萨吗?仅仅是搭车去柏林吗?仅仅是十年不变的背包旅行吗?我无法回答,因为我至今也没有一个明晰的答案。所以我已经很久没有出去骑车了。因为在没有想明白这个问题之前,户外和骑车对于我来说,差不多只是重复劳动罢了。
到了大三,当我交接了手上的工作开始全身心地投入到计算机科学的学习之后,我开始越发明白一个道理:人与人之间的交往和感情是靠缘分的。没有什么特别的道理,有的人就能和你贴的很近,即便你们物理上远在天边;而有的人,即便是出去旅行睡一个帐篷,也难免会有隔阂。我曾经天真的幻想,大家一起去旅行是一种极好的交友的方式,因为热爱旅行的人一定是坦荡的、诚实的、热爱自然的、激情澎湃的。这不正是我欣赏的人吗?可是很奇怪,一场旅行过去,大家回到自己的生活轨道上,各自依旧。其实对于绝大多数人来讲,所谓旅行,不过是逃离烦恼、暂时放松,给自己打一针麻醉针的好方法而已。是我看得太重了。
这之后我一个人,对,就一个人,踏着一辆单车走了几千公理的路,抛洒了一路的汗水。有人问,为什么不找个伴?会不会感到孤单?也许吧。也许人生的基调就是孤独的,而你要独自习惯这种孤独。史铁生说,“没有什么能证明爱情,爱情是孤独的证明9”。
真正的朋友不需要保持频繁的联系,需要频繁的联系才能保持朋友关系的人,也许并不是真正的朋友。70%的社交(包括饭局)都是很无聊的10。 所以,亲爱的朋友,如果你生日时没有收到我的礼物,并不代表我的心里没有记挂着你。下次我们再次见面的时候,我相信,亲切依旧,我会亲自为你下厨,做几个小菜,然后给你讲一讲我最近在做的事情、看的书籍、开发的自由软件(如果你感兴趣的话)。
缘起缘落,让我们顺其自然。云卷云舒,片刻的相聚并不能代表永恒,也许我们的友情会化作雨水,飘飘然的,润物于无声。原谅我好久没有和你打招呼,原谅我好久没有向你告知我的近况吧。我最近很好,但愿你也一样。
3 少说些话
"Talk is cheap. Show me the code." – Linus Torvalds
3月份的时候很幸运领到了WPS for Linux的邀请码,做了一些小事,也参与了一些论坛讨论。但是讨论的过程中,还是发现了一些令人忍俊不禁的帖子。比如有人建议金山出个操作系统、有人建议金山出一款输入法,更有甚者,还有人要求金山放弃QT,直接用Xlib编程,原因是他想要获得原生的界面效果;还有人要求金山出一款类似Office的VBA的中文扩展编程语言,注意,是中文编程语言。对于后面两位天外来客,我只能说,你们实在太高估我们地球人的能力了,仿佛软件中的QT就像积木一样,拔下来就可以换的。我劝你们还是多读读我们地球人的书,对我们地球人的能力有更深入的了解之后,再来说这说那。
所以我现在说话有些诚惶诚恐,因为我不知道,是否有朝一日,我的言论就像两位天外来客的言语一样,幼稚无知,却不自知。Talk is cheap。每个人都可以豪言壮语,但不是每个人都能信守承诺,坚持到底。所以要少说,多做,因为你不知道什么时候,你说错了话,却不自知。
我们还谈到,互联网的井喷式发展并没有改变互联网本身的信噪比,相反,我倒觉得互联网的发展是不断在降低互联网本身的信噪比,换言之,互联网上的噪声会越来越多,而真正有价值有营养的言论会越来越少。 如果把互联网比作海洋,那么现在的互联网,水面上水体里已经充满了各式各样大大小小的文字碎片和信息垃圾。 而这种趋势恰恰又是互联网繁荣发展必不可少的动力。因为互联网若想发展,就必须从阳春白雪的APRANET ——只给学校、教授和国防部用的网络,逐渐变成平等、开放、自由、信息获取和制造愈发方便的INTERNET。所以你会发现,从Telnet到BBS,从个人Blog到MicroBlog,我们制造信息的流程越来越简单,分享信息的方式越来越扁平,获取信息的手段也越来越迅捷。这极大地满足了劳苦大众唠叨猎奇和八卦的本性,使得原先在路灯下大叔旁棋盘边上的家长里短转移到了互联网上,特别是微博上。而事实上是,这些“碎碎念”般的文字碎片对你个人而言,不仅无用,而且有害。因为它会使你的思维和时间变得“碎碎念”化,这点我前面已经阐述过的。
我们没有办法改变互联网“碎碎念”化的这种趋势,但是一方面可以从自身做起,少给互联网制造一些垃圾信息(事实上我也会碎碎念,只不过我的主战场在豆瓣,看得人少,所以我也就不必担心会过多干扰他人的思维和生活);另一方面,可以想办法给互联网制造一些有营养的东西,恬不知耻的例子,比如这篇博客^_^ 。
4 多读些书
“求知欲是治疗无聊的良方,求知欲本身无药可治11。”
大二大三的时候,我曾经苦苦思索,人为了什么而活?最后得到的答案是两个字:快乐。具体说来,活着一是为了让自己快乐,二是为了给他人带去快乐。这几乎也可以推导出另一个重要的命题——人生下来就是要受苦的12。我们常常讲,人生之不如意,十有八九。不可选择的出身,无法追回的时间,聚散离别的亲友,独自一人的落寞,无可避免,无法选择。但我们这代人是幸运的,我们没有经历恐怖的文革,却享受了改革的成果。所以我相信,在这篇文章的众位读者里,95%的人都没有也不会有过饿肚子的感觉。 那么归结起来,我们活着就是吃饱了撑的,没事找事,反正得找点乐子,否则会无聊,会空虚,再之后就是碎碎念了^_^ 。
找乐子的方式各种各样,找到的乐子也不一而足。 乐子有深浅之分、长短之别。 读书所带来的乐趣,深邃而持久,远比饱餐一顿、高歌一曲更能满足人类的精神需求。可悲的是,人们已经不再阅读了,连乔布斯都这么说。有人说,使人毕业后拉开差距的,不是8个小时的工作时间,而是8小时外的业余时间。我承认这句话很有道理也很精辟,一针见血地指出了业余时间看书学习的重要性,但是我并不是100%赞同这种说法。因为在我看来,读书应该是很纯粹的活动,就是为了读书,完全不是为了什么拉开差距,更不要妄谈钱权地位影响力了(这可能是很多人对于差距的定义吧)。越是为了“拉开差距”而去读书的人,其往往会越走越偏,领会不到读书的真谛。
这或许也是当今中国教育的一大弊病和恶果吧。
5 多做些事
“用勇气去改变可以改变的事情,用胸怀去接受不能改变的事情,用智慧去分辨二者的不同。” ——李开复
我相信,如果李开复老师不是童年就移居美国,今天的创新工厂可能未必存在;如果陈士骏先生不是童年就移居了美国,也未必会有Youtube。有些东西是无法选择的,比如出身。一个农民的儿子和一个教授的儿子起点是不一样的;一个贵州山区的孩子和一个北京的孩子,出路也是不一样的。因为世界上本来就没有绝对的公平。
常有人讲,Your time is limited, you must follow your heart13。可是很多人连明白这个道理的机会都没有,一辈子就那么过去了。我很庆幸,在我二十岁出头,还不算太晚的时候,就已经明白"follow my heart(我随心动)"的这个道理了,所以我是个不循礼法、不懂屈服、特别能折腾的人。因为我明白,生命有限,如果我可以在有限的时间里做更多的事情,那么我就是在变相延长着我自己的生命。
我有一个观点,人生在于有目的地折腾。
我现在还有一个烦恼,就是始终无法克服起床困难综合症。
6 生命的维度
如果你看过Dimensions: A Walk Through Mathematics,你就会理解在艾舍儿的画作《爬虫》中的蜥蜴的困境,它生活在二维空间,因而几乎永远无法得到直观的三维认识。三维空间对二维动物的想象力而言,就如四维空间的相对论之于绝大多数人类的认知一样(我也不理解相对论),就是一个彻头彻尾的悲剧。
既然如此,为什么还要谈维度?什么是生命的维度?
我以为,人的生命是有维度的,读书是生命的一个维度,旅行是生命的另一个维度,写作画画也可以是生命的一个维度,搞科研发论文也可以是生命的一个维度。更多的维度需要由你自己来定义。之所以借用Dimensions的引用,是想说明一个观点,那就是人要勇于尝试。因为你永远无法预料,什么样的尝试会给你打来什么样的机遇、会给你的生命增加怎样的维度。生命的维度越高,人判断事情的本领也会越强,正如三维空间的人类比之于二维空间上的蜥蜴,可以看懂正立方体,但是比之于四维空间的人(假设有这样的生物),我们又几乎无法理解超立方体的存在了。但是你不理解,并不代表它就不存在。它一直在,只是你无法领略它的美。
旅行就是这样。在我上大学之前,我从来无法想象,一个人,可以盯着烈日、冒着风雨、背着行李、踏着单车冲上青藏高原,但后来我做到了,其实也远没有那么难。一旦你意识到外维空间的存在,你就会像影片中那只爬出二维空间走进三维空间的蜥蜴一样,领略高维空间的美,并看着自己的同伴在低维空间力徘徊迷茫,不知所措。旅行带给了我很多财富,它让我更淡定地面对惨淡的人生,并且去尝试在各个角度上寻找突破,不断地想办法给自己的生命拓展出新的维度。
7 求于至简,归于永恒
在所有的SNS网站以及所有的中国互联网公司中,我最喜欢的是豆瓣。它没有微博的喧闹,也没有校内的八卦无聊。它不跟风,却坚持自己的理念,做一家慢公司14,通过对产品和用户体验的绝对专注和持续改进,不断的改进用户体验,给用户创造价值。虽然这个过程难免一波三折,并且并不是所有人都能理解(绝大多数是因为狗日的中国网络审查制度),但是不可否认,豆瓣网的整体用户素质绝对是各大SNS中数一数二的。单凭这点,就足以让我抛弃所有其他的SNS,投身豆瓣了。更可贵的是,豆瓣是一个高信噪比的网站,我在上面的所得,包括高手的书评影评、一些颇有质量的博文订阅,以及对自己学习历程的记录,都让我受益匪浅。
顺便说一句,中国互联网公司的惯用手法就是耍流氓,不光对美帝耍,对国内用户也毫不客气。鉴别这类流氓网站有一个最简单的一个评判标准——看看能不能方便的注销账户。 以此标准,百度、新浪、人人都是流氓网站,操着为用户服务的口号,背地里却耍着请神容易送神难的手段,就是不让你注销、就是不让你离开、就是要不断地发邮件骚扰你、就是想让你“多回头看我两眼”、就是想让你的时间思考碎碎化。他娘的,如果不是有GFW的存在,我会用人人、百度?
少即是多,试着使自己的生活简单化、心灵单纯化,给自己留出点时间看看书、写写字,哪怕做做白日梦也好的。
只有求于至简,才能归于永恒。15
--
Footnotes:
1 我没有说微博不好,事实上我认为微博和BBS、博客一样,是网络信息源平民化过程中的一个自然而然的必要产物。
2 同时也造就了一批打着“云计算”、“云存储”、“大数据”的创业的和非创业的公司企业^_^ 。
4 参看这篇 《Facebook效应》 的书评
5 未鹏的《暗时间》这本书里,有关于语言、思维、大脑、时间非常精彩的论述。
6 阮一峰翻译的的《软件随想录》 里面有一些非常精辟的关于聪明人、Hacker的论述。
7 如何避免这些分散注意力的东西,这是我写作这篇文章和《打造高效的工作环境》系列文章的主要动因之一。
8 沉溺其中、不可自拔是改变世界、成就梦想的必由之路。
9 感谢Wooooonderful告知我这句话。
10 70%…这个是俞敏洪老师微博上的观点,这里再次郑重推荐下俞敏洪老师的"创业传记", 会让你对人生、中国的人情社会,以及朋友关系有很深的思考。
11 豆瓣上的一句话,忘记出处了
12 这也是俞敏洪老师的观点。
GAS汇编(1):起步
百度离职后,随着递归式学习的深入,我的涉猎从Lisp/Scheme/SICP,到APUE,最近又转入到了汇编语言上。老实说,汇编这种文物级的东西,在一般的计算机编程中是绝难碰到的。但是计算机工程学到一定层次,瓶颈所在,就会发现,总是有那么几样东西,诸如汇编、C、算法、编译原理、体系结构、操作系统、网络数据库等,这些基础知识绕不过,躲不开,而能否跨越这些坎,从某种意义上决定了一个程序员能否从合格到优秀、从优秀到卓越。
最早接触汇编还是在大一上一门计算机硬件基础的导论课上,我原以为这课既然叫计算机硬件基础,讲的应该都是软驱硬盘主板鼠标等如何拆卸组装选购的科普杂事。要知道,那个时候的我刚刚学会在Windows XP控制面板里面装卸软件。给我们讲课的是一个老头,用的是自己编写的教材。老头最津津乐道的事情是在90年代中期自己花了400块钱买了一个32M的U盘,却因为U盘容量太大而束手无策,不知道该存些啥东西。这课开始几次讲得确实是硬盘、鼠标组成科普原理啥的,后来讲着讲着就拐到了16bit DOS下的debug汇编编程,mov ax, bx这种,结果可想而知,我们全班同学一下子就晕的不行,弃考了一小半,剩余勉强坚持到最后的,又挂了好几个。
大二下又上了一门汇编语言的通识课,仍旧是16bit DOS,仍旧是不得要领。直到大三,上了专业的汇编课,硬着头皮,在Linux+Dosemu+masm5.0的环境下编了一个300多行的软件模拟浮点数算数指令的汇编程序,这才对16bit汇编中的一些基本概念诸如段、寻址方式、中断等等, 有了一个初步的了解。不过说实话,大学里的汇编学习和实际脱节太远,多数的汇编教育还停留在16bit DOS环境下,用得教材以清华的那本《IBM》居多,做得实验也都是Window 98DOS子系统下步进电机、控制电灯明暗这种实验,一到实际编程,32bit和64bit的保护模式下编程,加上复杂的MMX指令,浮点数指令,就傻眼了。
本文介绍Linux平台下32bit的GAS汇编语言编程,GAS是GCC编译器的汇编器。之所以采用这套工具,主要的原因在于GCC工具链非常成熟,GAS配合Emacs、GDB,加上Shell命令行,和objdump、od等工具,对于我这个Linux fans和命令行控有莫大的吸引力,工作效率自不必说,谁用谁知道。
x86汇编编程有两种截然不同的语法风格,我们常见的是Intel语法风格,类似这种:
mov eax, 32
而GAS汇编采用的是AT&T的语法风格:
movl $32, %eax
讲GAS汇编的书籍并不多,以下两本都是好书:
- "Professional Assembly Language"
- "Programming From The Ground Up",此书还有一个非常好的配套的网站,http://savannah.nongnu.org/
我粗略的看完了第一本,第二本正在进行中,这样的学习已经让我对C语言中很多高级的概念,诸如指针、编译连接过程、内存布局和分布有了比较深入的理解。
不过对于计算机的学习,光说不练是远远不够的。书本上看懂并不代表就能快速写出准确、实用、高效的程序来。我学习一门计算机语言,往往都会去找一本评价较好的书籍,把书上所有的示例代码看懂,自己亲自敲一遍。这不,刚刚起步,就碰到了两个小问题,记录下来,作为GAS汇编学习的起点。
首先是Emacs编辑器的问题。Emacs本身对汇编语言编辑功能的支持远比不上对其余高级编程语言的支持。一个内建的ASM Mode,乃是ESR的大作,粗略看了下,两百多行的代码,功能有限,要命的是还有个小bug,那就是默认的注释符号为';',而不是gas汇编接受的'#'。恰好这个月花费了大量精力研习了emacs manual和elisp manual,因此不自量力写了两个小函数,专门用于gas汇编语言的注释,(代码很初级,elisp高手轻拍):
(defun gas-comment-region (start end)
"comment region for AT&T syntax assembly language
The default comment-char for gas is ';', we need '#' instead"
(interactive "r")
(setq end (copy-marker end t))
(save-excursion
(goto-char start)
(while (< (point) end)
(beginning-of-line)
(insert "# ")
(next-line))
(goto-char end)))
(defun gas-uncomment-region (start end)
"uncomment region for AT&T syntax assembly language
the inversion of gas-comment-region"
(interactive "r")
(setq end (copy-marker end t))
(save-excursion
(goto-char start)
(while (< (point) end)
(beginning-of-line)
(if (equal (char-after) ?#)
(delete-char 1))
(next-line))
(goto-char end)))
希望随着学习emacs和elisp的深入,自己能够写出一个稍微好一点的gas汇编的major-mode(顺便,前两天给emacs的包管理工具el-get提供了一rcp被接受了,这是我认真学习计算机以来第一次为开源项目做出点实际的贡献,开心)。
第二个问题是64位下写32位汇编程序的问题。这其中涉及到两个问题。其一是32位汇编和64位汇编的内在区别问题,包括语法层面上的,和机器层面上的,这个我还没有发言权,这里有一篇文档,详述了x86下64位汇编和32汇编的区别。而由于我上面提到的两本好书中,采用的都是32位的汇编,而32位向64位的迁移并不是无缝的,外加上我现在对64位汇编了解有限,因此如何在64位平台下编写、汇编、连接32位汇编,就是我们要解决的第二个问题。
要解决这个问题,就要对c程序的整个编译流程有一个稍微详细点的了解,光靠编译器点击一个按钮自动编译,是解决不了这个问题的。这个我不再具体展开,《程序员的自我修养》是这方面难得的一本好书,我粗略看过一遍,但一直不敢在豆瓣打上“看过”的标签,因为没有对计算机体系结构、汇编语言和C语言的深刻了解,是不可能深刻理解并“看过”此书的。
下面给出一个示例程序,来自于《Professional Assembly Language》
.section .data
output:
.asciz "The processor Vendor ID is '%s'\n"
.section .bss
.lcomm buffer, 12
.section .text
.globl _start
_start:
movl $0, %eax
cpuid
movl $buffer, %edi
movl %ebx, (%edi)
movl %edx, 4(%edi)
movl %ecx, 8(%edi)
pushl $buffer
pushl $output
call printf
addl $8, %esp
movl $4, %eax
movl $1, %ebx
movl $output, %ecx
movl $33, %edx
int $0x80
pushl $1
call exit
这个程序很简单,主要是调用cpuid指令得到CPU本身的一些信息,然后调用C标准库中的函数打印出来,之后利用linux系统调用write打印出一个字符串,最后再次调用C标准库中的exit函数,状态码为1。我们来验证下此程序的编译、连接和运行过程,主要的汇编、连接指令是:
-
sudo pacman -S gcc-multilib binutils-multilib gcc-libs-multilib lib32-glibc
- 安装必须的32位编译器和运行库
-
as -g -o cpuid2.o cpuid2.s –32
- –32: 生成32位的.o文件
- -g: 生成gdb调试信息,便于程序的调试
-
ld –dynamic-linker /lib/ld-linux.so.2 cpuid2.o -o cpuid2 -m elf_i386 -L/usr/lib32 -lc
- –dynamic-linker /lib/ld-linux.so.2: 采用动态连接
- -m elf_i386: 生成32位的程序
- -L:讲lib32-glibc的库加入库搜索路径
- -lc: 连接标准c语言库,printf必须
% uname -m x86_64 % as -g -o cpuid2.o cpuid2.s --32 % file cpuid2.o cpuid2.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped % ld --dynamic-linker /lib/ld-linux.so.2 cpuid2.o -o cpuid2 -m elf_i386 -L/usr/lib32 -lc % file cpuid2 cpuid2: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), not stripped % ./cpuid2 The processor Vendor ID is 'GenuineIntel' The processor Vendor ID is '%s' % echo $? 1 % ls -l total 24 drwxr-xr-x 2 lox users 4096 Mar 24 12:07 . drwxr-xr-x 19 lox users 4096 Feb 29 20:08 .. -rwxr-xr-x 1 lox users 2675 Mar 24 12:07 cpuid2 -rw-r--r-- 1 lox users 1464 Mar 24 12:07 cpuid2.o -rw-r--r-- 1 lox users 414 Mar 23 18:18 cpuid2.s -rw-r--r-- 1 lox users 348 Mar 23 10:46 cpuid.s %
OK,就这么多,至于Makefile、gas程序调试等话题,容我后续再叙。
打造高效工作环境(2): 高效的文件管理
Table of Contents
1 为什么Windows的文件系统混乱、低效?
让众位久等了!上篇Why Windows Sucks的吐槽文中,我曾谈到,Windows文件系统几点令我非常不喜欢的地方:
- 文件系统多盘拼,文件命名大小混
- 权限控制小烦躁,命令终端很废柴
本篇我们稍微深入探讨一下这个话题,并由此引入我们接下来系列文章的主角,*nix。
上小学的时候我们就知道,Windows的第一个盘是C盘。如果你稍微研究下所谓“Windows提速优化”这类的教程,你就会知道C盘是所谓的系统盘,非常重要。如果你足够细心,并且有足够的耐力,那么你可能会学到:
- 程序尽量不要装在C盘,影响系统运行速度
- 可以用工具将C盘里的"My Documents"(中文名是“我的文档”)里面的东西转移到别的盘里,这样可以节省很多系统盘的空间,“有可能”使得系统运行更加畅快
- 定期整理下磁盘碎片,清理下注册表,杀杀毒,可以提高系统运行速度
但是你有没有想过:
- A盘和B盘哪里去了?
- 为什么我的系统有C、D、E三个盘而别人的系统除了C、D、E还有F,甚至还有Z盘?
- 为什么一个电脑的文件系统要分为多个盘呢?
- 苹果系统需要整理磁盘碎片吗?
- 注册表到底是干嘛用的?
- ……
事实上这个世界上本不该有这么多个为什么,一切的一切,源于Windows蹩脚的设计:
- Windows的文件系统是多根的,这导致你几乎没有办法控制你的移动硬盘的挂载点,几乎没有办法进行chroot高级实验,几乎没有办法制定规范化的类似于*nix下的FHS标准
-
Windows的文件系统目录结构是极其混乱而不统一的,我引用一张表格1来对比说明下*nix和Windows两种文件系统的目录结构,你可以看到,*nix系统目录的命名都非常简洁规律,便于脚本自动化处理,而Windows的文件命名和目录结构像是一层层的石头胡乱堆砌的
Function Linux Microsoft Kernel root "WINNT" or "WINDOWS"another page on this site /boot Executables /usr/bin "Program Files" /usr/lib /usr/share /usr/doc /usr/apps Drivers /dev Win…/System32 hosts file /etc Win…/System32/Drivers/Etc One for each User /usr "Documents and Settings" /user Log files /var - Temporary work files /tmp Temp Optimizing Utilities /opt - -
Windows的系统文件命名非常混乱,不堪入目,正如“一千个读者心中就有一千个哈姆雷特”一样,一千个Windows C盘就有一千种的文件命名和目录结构,下面是我的正版Windows 7系统下的C盘目录:
-
Windows 7下的C盘:
- autoexec.bat
- b7e61efa43ef263f987f6b2dbfe5b362
- Boot
- bootmgr
- BOOTSECT.BAK
- bootsqm.dat
- Config.Msi
- config.sys
- Documents
- Download
- found.000
- Intel
- IO.SYS
- LLabs
- mfg
- MSDOS.SYS
- PerfLogs
- ppsvodcache
- ProgramData
- Program
- QQDownload
- $RECYCLE.BIN
- RRbackups
- swshare
- System
- Temp
- Users
- Windows
-
linux下的根目录:
- bin
- boot
- dev
- etc
- home
- lib
- lib64
- lost+found
- media
- mnt
- opt
- proc
- root
- run
- sbin
- srv
- sys
- tmp
- usr
- var
-
Windows 7下的C盘:
- 合理的文件结构组织和文件命名,对于自动脚本处理是非常重要的,譬如,如果一个文件名称为"My Documents",那么在脚本处理中,如果不小心编码,这个文件就会被当成"My"和"Documents"两个文件处理。
1.1 历史原因
当然,这种混乱是有一定历史原因的。细细讲来倒是很有意思的一件事情。话说MS80年代初只是主打做Basic语言解释器小的软件公司,后来IBM需要发展PC机,最开始找的是DEC公司的人,但是DEC的老总据说是非常忙,而私人飞机好像出了问题,于是就错过了和IBM的谈判,让MS拣了个大大的便宜。而MS呢,手头是没有成型的操作系统的,就从一个不知名的小公司里面花了5万刀买来了一个系统,并重新命名为MS-DOS,联合Intel和IBM做起了合伙生意,只是IBM没有想到的是,你来我往,几番周折,两个小弟弟MS和Intel成长了起来,在90年代中期其风头甚至盖过了IBM自己。其实谈起计算机的水平和资历,全世界也没有几个敢和IBM叫板的公司,当年IBM 360系统的横空出世,不仅开创了软件工程中众多的“人月神话”,更让无数黑客在360系统的熏陶下成长起来。扯远了,话说回来,MS-DOS呢,是一个非常蹩脚的操作系统,甚至连美国大学里的学生都瞧不惯,说微软是做小儿科系统的公司2。你想一想,90年代的时候,Richard Stevens的APUE都出第一版了,而MS-DOS大概才刚刚摆脱8个字符以下长度文件名的限制。后来呢,苹果抄袭Xerox,搞出了漂亮的GUI,这样一来,微软压力甚大,因为系统底层比不过Unix,表面层GUI又被苹果占了先机,危矣。怎么办好呢?微软开始一面搞Windows,一面联合IBM搞OS/2,同时明修栈道、暗度陈仓,从老的DEC公司挖来一批人开始默默地搞NT(号称"New Technology"的操作系统)。这样一直多战线并存的搞到了Windows 2000的横空出世。话说Windows 2000之所以叫Windows 2000,一方面是因为它是在2000年推出的,另一方面恐怕是搞出Windows 2000确实动用了MS 2000个以上的人力(我猜的,不过几千人的人力是有的)。至此呢,Windows开始一心搞NT。其实这样也好,美中不足的是NT为了兼容以前蹩脚操作系统,背上了很多沉重的历史包袱,这也导致Windows系统更新换代的速度特别的慢。Ubuntu半年推出一个新版本,Mac OS自动X后,10年光景,已经到了X.7的版本,每个版本都有大的提升,而微软闭门造车耗时五年的Vista,还有新进推出的Win7,奋战了这么多年,还是没能将XP第一的宝座纳入囊中,我看MS的系统是江郎才尽,再难突破了3。
而在微软系统的代代更新中,最苦命的算是一直追随MS的程序员了,掏着升级系统和硬件的银子不说,就连自己费尽力气学到的知识,从BASIC、到MS-DOS、到VC++、到MFC,到ASP,到ASP.NET,到C#,也随着微软系统的更新换代灰飞烟灭了……殊不知,*nix下的程序员,纵历风雨,我心永恒。靠着vi+gcc,我就能闯天下。
2 *nix文件系统的优势
相较Windows,*nix的文件系统相对要规范的多,究其根源,在于*nix有一条非常重要的设计哲学,那就是:Everything in Unix is a file:
- linux的文件系统是单根的,具有一种逻辑意义上的美感。可能有人会问,如果我们新插入一个移动硬盘,我没有盘符,怎么访问?这就是Windows的惯性思维。在Linux中,我们可以随意创建一个目录,然后通过mount命令将起挂载在这个目录点上。事实上有一个叫做fuse4的东西,允许你mount你想得到想不到的很多东西:
- linux的文件命令和文件存放是很有规律的,稍微学习下,你就会知道/bin、/etc、/usr、/home目录的作用,并且,在所有的*nix环境下,都有这些统一规范的目录。
-
linux为每个用户建立一个单独的/home/user主目录,所有用户相关的配置都存放在这个目录下,结合linux下所有几乎所有配置文件都是纯文本这样的特点,带来的好处就是极其简单实用的用户数据迁移过程 ——当你系统崩溃重装的时候,只需要保留/home分区,不用做太多的配置,一切都在:
- 原先的软件快捷键几乎保持不变
- vim和emacs的配置不变
- 甚至连桌面的壁纸都不会变
- linux中大量采用纯文本的配置文件,相比较于中央集权的注册表方式管理的配置文件, 纯文本文件的好处在于通用性、直观性、可见性和易读性 。虽然文本配置格式多样,但是你已然可以使用你最擅长的工具(哪怕是OpenOffice也行)来查看甚至修改配置文件,并且可以根据个人需要讲这些配置文件放到诸如bitbucket这类SCM系统里面;而对于Windows的注册表,一旦损坏,除了少数几个专有的工具,你就只能双手一撒,重装系统,或者给微软打电话了。
3 一些个人的关于文件组织和管理的Tips
以上,都是关于Windows不好的吐槽以及*nix好的赞扬,没兴趣的看客可以直接忽略,因为下面的内容才是本篇文章的核心所在。
我曾经无数次在学校教室、宿舍和公司的办公桌上,看见各式人等电脑中,一个可怜单薄的桌面上,存放着从txt、doc、docx、ppt,到jpg、png,到rm、mkv,到rar,到"xxxx的快捷方式"等等五花八门的没有八十也有一百个之多的文件。那感觉就像是看到了五湖四海的人们睡到了一张星级宾馆的床上,令人心头一紧、后背发凉。我甚至可以感觉得到他们盯着屏幕、挪着鼠标、眯着双眼寻找某年某月某日的一份word文件的焦躁与辛苦。我甚至还能联想到,这样的人在生活中也多数是邋遢的,他们会随手丢弃东西,经常翻箱倒柜的去寻找某个久远的日子里的一个小物品。
不是这样的,正确高效的文件组织管理绝对不该是这样的。我相信,即便你没有洁癖,但是看着电脑桌面上那么一坨乱糟糟的东西,心情也会不好的。所以我的电脑桌面上向来都是清清爽爽,一个图标都不放。我个人总结了一些粗浅的文件组织管理的小技巧,经过两年多的实战,效果还是不错的:
3.1 规范同一的文件命名
- 尽量使用小写的文件命名
- 尽量使用英文单词命名(良好的英文水平是优秀Coder的必要条件)
- 如果文件名是多个单词,用下划线_将多个单词连接起来,千万不要留有空格,对脚本化的文档处理非常不利
3.2 良好和谐的目录结构
- documents:主要存放各种文档,包括但不限于各种工作简历啊、考试进度啊、学校通知啊,诸如此类,定期删除过期文档,将有学习价值的文件转移到study文件夹下
- downloads:主要存放Firefox等Internet软件的下载资源,有价值的资源及时转移,没有价值的资源及早删除
-
media:主要存放各种多媒体资源,重点用户轻松娱乐,三个子文件夹:
- musics: 存放喜欢的音乐,将这个文件夹导入Amarok或者你喜欢的播放器软件即可
- pictures:主要存放个人照片和网上的一些有趣有意义的图片
- videos:各种电影,我非常喜欢看电影哈,可惜电脑硬盘空间不够,加上我决定要逐步完善自己的版权意识,所以存量有限
- mnt:用于临时挂载一些U盘的目录
- programming:用于自己学习编程的目录,我现在用BitBucket管理自己的代码,每个bitbucket上的repository都对应于这个文件夹下的一个子目录
- software:用于存放一些有用的软件,其实这个没啥必要,因为linux主流distribution的软件库一般都非常完善,只要有好的网络环境,想装什么软件(哪怕同时装几十个软件)只是一条命令或者一次鼠标点击的事情
- study:存放自己有电脑以来收集到的各种学习资料和自己大学里的各种作业、ppt、文档等等,分门别类,定期整理删除
- tmp:我自己的tmp目录,用于临时创建一些不重要的测试文件,常见场景是我需要测试一些C语言或者TeX或者Python里面的某个特性,因此临时创建一个小文件,编译运行下,看看效果
- tools:用于存放自己写的一些系统管理的小工具,比如我自己写的SSH翻墙脚本、设定笔记本电池充电阀值的脚本等等
4 接下来
按照原本的写作计划,在本篇文章的基础之上,我将在接下来的三篇文章中谈到三个主题:
-
Just Find it: Findutils,介绍*nix的小工具,帮助你在文件的海洋中傲游穿梭,包括但不限于:
- 如何迅速而准确的定位你想要的寻找的文件
- 如何迅速而准确的在历史的目录树中进行切换穿梭
- 如何仅仅借助Shell工具,在一个Open Source的代码库中,寻找一个变量的出现位置,并且能够找出到底是哪个文件包含了这个变量的使用
- 如何删除某个目录下所有以.bak结尾并且修改时间在n天内的所有文件
-
细谈文本配置,文本配置是"Everything in Unix is a file"的一个重要体现,对应于Windows的注册表,文本化的配置文件大大简化了*nix系统管理工作,这篇主要会介绍:
- *nix系统中一些重要的配置文件
- 以及相关的配置文件的配置格式
- 配置文件跨系统的迁移和保存
- 以XML/JSON/YAML为例介绍下常见的几种文件配置格式,有可能的话,初步介绍下Lisp中"Code is Data"的扩展概念
- Shell之道,初步介绍下*nix Shell编程的一些入门要点,并直接转入Shell编程的精华——管道。可能的话,会在此基础上展开探讨下进程间通信的一些思考。
敬请期待!
--
Footnotes:
1 参考Operating Systems & Commands,这篇文章详细对比了*nix和Windows两种系统之间的差异。
2 参考《软件随想录》(阮一峰译),P65,《在耶鲁大学的演讲》。
3 以上言论,多有戏谑成分,众位看官一笑而过,切莫当真。
4 关于Linux中FUSE模块的设计思路,可以参考徐宥写的编程珠玑番外篇-K. Plan 9 的故事(修订版),徐宥写的这一系列文章水平很高,趣味盎然,强烈推荐。
闲谈MapReduce(1): Hadoop初探
Table of Contents
1 缘起
MapReduce是这几年IT界很热的一个名词,从某种意义上讲,MapReduce引领了当代海量数据处理的趋势和潮流。与IT界的其他名词一样,MapReduce听起来也是个很玄乎的名词,MapReduce?Map?Reduce?如果你是一名初级Coder,那么你可能从某处知道,Map的翻译是映射,Reduce的翻译是归约。MapReduce就是映射归约,是一种数据并行处理的一种编程模型。如果很不幸,你不是一名光荣的Coder,只是中国网民大军中的五万万分之一1,那么没关系,MapReduce离你并不遥远,有一个名词你一定很熟悉,那就是——云计算。关于云计算,互联网上有一个经典笑话,“中国一留学生去美国打工的当过报童,不带计算器,习惯动作抬头望天时心算找零。顾客大为惊讶,纷纷掏出计算器验证,皆无误,也抬头望天,惊恐问:“云计算?”不过云计算的真正含义,用工程师的语言,准确地定义,应当是“超大规模的,可扩展的,低成本,但是高可靠性的服务器集群系统”2。
从大的层面上来讲,云计算并不仅仅是MapReduce,MapReduce只是云计算的一个技术性开端,或者说,是互联网的发展需求推动技术的发展进步,最后由Google临门一脚创造出来的一种处理海量数据的并行编程模型。真正的云计算包含诸如IDC建设、海量存储、网络规划、商业模式、网络安全等等诸多技术的难题,还有很多被一些所谓的专家炒作起来的社会意义。不过本系列文章并不打算探讨这些过于宏大的主题,我本人也没有这样的水准和资格来说三到四。本系列文章的目的只有一个,那就是搞明白,MapReduce中的Map和Reduce,到底源自何处3?
我第一次听说MapReduce这个名词,是在2010年9月,那时百度来浙大宣讲,顺带开了一个技术讲座,主讲人徐串曾是Google中国编程挑战赛冠军。当然,讲座内容我是听不懂的,随心记下来的几个技术名词,至今为止,还能记住的,只剩下MapReduce了。后来面试百度运维部,期间和面试官聊到我暑期实习在华数淘宝做的一个视频转码入库系统,面试官大概觉得这个系统有点分布式的意思,因此题目结束的时候给了我一个建议,就是让我学习下MapReduce。再后来,阴差阳错,我进入了百度的分布式运维小组学习Hadoop运维,学习MapReduce就成了一个身不由己的任务。
在百度的半年,我初步接触了大规模Hadoop集群(3000个节点的规模)的运维工作。但比较讽刺的是,运维Hadoop集群的我,自身并没有写过多少真正的MapReduce程序,对Hadoop的理解也浅尝辄止。而我也始终没有搞明白,好端端的一个程序,为什么要按照MapReduce这样别扭的模型重构运行?
大概是看了Paul Graham的《黑客与画家》后,我开始正式认真学习Lisp这门语言,至今已有小半年时间,这期间我利用业余时间,和最近一个月的休假时间,基本上看完了Paul Graham的《ANSI Common Lisp》和《On Lisp》,《SICP》太难,我穷尽脑力至今也只窥得前面三章,做了100道习题左右,不过即便如此,也令我受益匪浅4。半年Lisp的学习让我搞明白了MapReduce中,Map和Reduce的来龙去脉。这个问题我Google了很久,但是始终没有一个满意的答案,现如今,我自己找到了满意的答案。
2 抽象漏洞(兼谈数学和计算机工程)
在正式开始我们的探险之旅前,我们还面临这一个问题,那就是,这次探险的必要性在哪里?既然MapReduce已然为我们提供了成熟的理论编程模型,Hadoop生态圈也给我们提供了一整套成熟的工程实现,我们为什么还要纠缠这些学究般的历史问题?我的解答是, 一个学科的历史往往就是这个学科的本身 。无论是一门编程语言、编程范式、编程模型,或者IT业的任何一项新技术新名词,在学习的过程中,一定要搞明白:
- 它解决了什么样的技术问题?当时的历史背景是什么?还有没有类似的(可能没有流行起来的)解决方案?
- 它的引入带来了哪些新的问题?
- 它的优点是什么?什么样的问题一定会手到禽来?
- 它的不足是什么?什么样的问题是它解决不了的?
这就好比解一道很难数学题,如果光告诉你一个正确的数字,那么这个数字对你来说一点意义都没有;如果进一步,告诉你标准的解题过程,那么你可能会对这个题目有一个粗浅的认识;如果有那么一个白痴,不但告诉你正确的答案和解题过程,还把他的演算纸送给了你,并热切地给你讲解他在解题过程中碰到了哪些问题和陷阱,是怎样解决怎样解决问题怎样规规避这些陷阱的,那么你对这道题目的理解则会大大加深,日后再碰到同样类型的问题就会轻车熟路,手到拈来。 从某种意义上而言,一个完整的解题的探寻过程才是一个题目所具有的全部信息价值,扔掉这些而仅仅记住一个解题结果或者一个标准的解题证明,无疑是买椟还珠 5 。但是比较可悲的是,计算机是一个年轻的学科,所以专门讲述计算机历史的书籍并不像数学史书籍一般汗牛充栋。
从另一个角度上讲,计算机和数学的都是一座不断分层的抽象大厦。数学是从基本的整数,到数系的扩充,到微积分的诞生,到非欧几何等等宏大的诗篇;而计算机则是从最基本的与非门,到bit、byte、word,到汇编、c、高级语言,到设计模式、分布式等等现代工业的大厦和基础。“计算机科学领域的任何问题都可以通过增加一个间接的中间层来解决6”,不过很不幸, 计算机的抽象和数学的抽象有一个本质的不同,那就是计算机的抽象是有漏洞的 ,这就是抽象漏洞法则:All non-trivial abstractions, to some degree, are leaky。在数学领域,我们从来不用担心说某个定理“因为空调故障的原因宕机了,或者因为内存吃紧运行特别缓慢,似乎是发生内存泄漏了”,等等诸如此类的各种各样令人头疼的问题。这条法则深刻的影响了计算机软件和数学定理的生产过程——在计算机中,我们不可能找到一个能困惑世间智者358年的谜7;在数学领域,我们也不可能找到一个耗费人类5000万人年人力的定理8。 如果说,基于抽象的数学,考验的是人类大脑思考深度的极限,那么同样是基于抽象,并且脱胎于数学的计算机工程,挑战的就是人类大脑思考广度的极限 ——软件工程中瓶瓶罐罐的细节太多了,所以大凡软件开发,走的都是兵团作战的策略;而数学就不一样,“10个产妇无法在一个月内生出孩子9”,数学领域中辉煌定理的产出,往往依靠少数几个,甚至单个天才数学家的苦苦思索和灵感涌现。
3 Let's Go
以上,废话了这么多,所要强调的无非就是,了解MapReduce的来龙去脉,对于写出更好的MapReduce程序,甚至将来拨开层层抽象,解决MapReduce的底层问题,乃至改善MapReduce,都是大有裨益的。不过,在正式踏上我们的探险旅程之前,我们需要检查一下手头的“装备”是否合格,很简单:
- 你需要一台*nix系统,最好是GNU Linux,苹果也行,如果实在不方便,Windows下装个Cygwin也还能凑合;
- 你需要有一定的编程经验,包括但不仅限于C、Java、Bash、Python,如果再对Lisp或者Scheme有一定了解就更好了(别急,本系列文章对Lisp做一个简要的介绍);
- 你需要了解一些常见的*nix软件开发工具,包括但不限于Vim的使用、Ant和Make构建工具、Git和SVN版本控制软件;
- 你需要对POSIX系统标准有一定了解,包括但不限于*nix的文件系统结构、用户属组、文件权限、管道等等。
Now, Let's Go!
4 Hadoop
行文至此,相信众位读者已经知晓了云计算的一些基础概念,最起码知道了所谓Google技术的三驾马车是什么,如果能看过Hadoop代码中WordCount的例子并能看懂的话,那你简直是太天才了。为了保证我们的探险顺利进行,我们需要一套开源的MapReduce平台实现来验证我们的学习成果,Hadoop是不二选择。关于Hadoop本身有太多太多的资料,因此我在这里就不再劳心劳力的copy别人的劳动成果了。推荐以下三本书,作为Hadoop的入门:
我们所要做的,就是在本机的*nix系统下,搭建一个demo的伪分布式运行的Hadoop平台。我采用的Hadoop版本是Hadoop 0.20,这个版本比较稳定,最新的Hadoop 1.0添加了很多新的特性,这些特性对于我们的探险并没有特别的作用,而且我也不甚了解。当然,本文的重点并不是Hadoop,所以我并不会带你去分析HDFS的源代码,告诉你如何打Patch(我也不会,嘿嘿)。本文的重点在于MapReduce的来龙去脉。
- 首先本机*nix上存在jdk和ssh,并找到相应的$JAVA_HOME
- 首先是建立本机用户到自身的ssh信任关系,步骤大致如下:
➜ ~ ssh-keygen Generating public/private rsa key pair. Enter file in which to save the key (/home/lox/.ssh/id_rsa): /home/lox/.ssh/id_rsa already exists. Overwrite (y/n)? y Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /home/lox/.ssh/id_rsa. Your public key has been saved in /home/lox/.ssh/id_rsa.pub. The key fingerprint is: 19:3f:55:84:99:d2:1e:c6:42:d0:39:6f:3e:83:84:21 lox@lox-pad The key's randomart image is: +--[ RSA 2048]----+ | .+.+ =o | | E . * O. | | ..o B.. | | .+..+ | | S.o+ | | ..+ | | o | +-----------------+ ➜ ~ cp .ssh/id_rsa.pub .ssh/authorized_keys ➜ ~ chmod 700 .ssh ➜ ~ chmod 600 .ssh/authorized_keys ➜ ~ ssh lox@localhost
- 下载hadoop v0.20,解压缩到一个目录,我的目录结构如下,其中tmp/hadoop-data作为hdfs数据存放目录(包括伪分布式运行的namenode和datanode的数据),tmp/hadoop-v20作为$HADOOP_HOME
➜ ~ tree -L 1 tmp/hadoop-data tmp/hadoop-v20 tmp/hadoop-data tmp/hadoop-v20 ├── bin ├── build.xml ├── CHANGES.txt ├── conf ├── conf.origin ├── conf.pseudo ├── conf.standalone ├── contrib ├── docs ├── hadoop-0.20.3-dev-ant.jar ├── hadoop-0.20.3-dev-core.jar ├── hadoop-0.20.3-dev-examples.jar ├── hadoop-0.20.3-dev-streaming.jar ├── hadoop-0.20.3-dev-test.jar ├── hadoop-0.20.3-dev-tools.jar ├── ivy ├── ivy.xml ├── lib ├── LICENSE.txt ├── logs ├── NOTICE.txt ├── README.txt ├── src └── webapps
-
修改hadoop的配置文件分别如下:
- hadoop-env.sh,重点修改下$JAVA_HOME,指向SUN JDK或者OpenJDK的目录,Hadoop官方建议采用SUN(现在是Oracle啦)的JDK。
- core-site.xml
- hdfs-site.xml
- mapred-site.xml
hadoop-env.sh ... ... # The java implementation to use. Required. # export JAVA_HOME=/opt/java export JAVA_HOME=/usr/lib/jvm/java-7-openjdk ... ...
core-site.xml
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<!-- Put site-specific property overrides in this file. -->
<configuration>
<property>
<name>fs.default.name</name>
<value>hdfs://localhost:9000</value>
</property>
<property>
<name>fs.trash.interval</name>
<value>1440</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/home/lox/tmp/hadoop-data/tmp</value>
</property>
</configuratione>
hdfs-site.xml
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<!-- Put site-specific property overrides in this file. -->
<configuration>
<property>
<name>dfs.replication</name>
<value>1</value>
</property>
<property>
<name>dfs.name.dir</name>
<value>/home/lox/tmp/hadoop-data/name</value>
<final>true</final>
</property>
<property>
<name>dfs.data.dir</name>
<value>/home/lox/tmp/hadoop-data/data</value>
<final>true</final>
</property>
</configuration>
mapred-site.xml
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<!-- Put site-specific property overrides in this file. -->
<configuration>
<property>
<name>mapred.job.tracker</name>
<value>localhost:9001</value>
</property>
<property>
<name>mapred.tasktracker.map.tasks.maximum</name>
<value>5</value>
</property>
<property>
<name>mapred.tasktracker.reduce.tasks.maximum</name>
<value>5</value>
</property>
<property>
<name>mapred.child.java.opts</name>
<value>-Xmx512m</value>
</property>
</configuration>
- 启动hadoop,如果能用Hadoop FS Shell做一些常规的mkdir和ls操作,Hadoop搭建就算大功告成了:
➜ ~ hadoop namenode -format 12/02/15 00:07:23 INFO namenode.NameNode: STARTUP_MSG: /************************************************************ STARTUP_MSG: Starting NameNode STARTUP_MSG: host = lox-pad/127.0.0.1 STARTUP_MSG: args = [-format] STARTUP_MSG: version = 0.20.3-dev STARTUP_MSG: build = http://svn.apache.org/repos/asf/hadoop/common/tags/release-0.20.2 -r 916569; compiled by 'lox' on Wed Nov 9 23:40:01 CST 2011 ************************************************************/ Re-format filesystem in /home/lox/tmp/hadoop-data/name ? (Y or N) y Format aborted in /home/lox/tmp/hadoop-data/name 12/02/15 00:07:25 INFO namenode.NameNode: SHUTDOWN_MSG: /************************************************************ SHUTDOWN_MSG: Shutting down NameNode at lox-pad/127.0.0.1 ************************************************************/ ➜ ~ start-all.sh starting namenode, logging to /home/lox/tmp/hadoop-v20/bin/../logs/hadoop-lox-namenode-lox-pad.out localhost: starting datanode, logging to /home/lox/tmp/hadoop-v20/bin/../logs/hadoop-lox-datanode-lox-pad.out localhost: starting secondarynamenode, logging to /home/lox/tmp/hadoop-v20/bin/../logs/hadoop-lox-secondarynamenode-lox-pad.out starting jobtracker, logging to /home/lox/tmp/hadoop-v20/bin/../logs/hadoop-lox-jobtracker-lox-pad.out localhost: starting tasktracker, logging to /home/lox/tmp/hadoop-v20/bin/../logs/hadoop-lox-tasktracker-lox-pad.out ➜ ~ jps 21061 JobTracker 20852 DataNode 21255 Jps 20977 SecondaryNameNode 20764 NameNode 21156 TaskTracker ➜ ~ hadoop fs -mkdir /tmp/this-is-a-test-dir ➜ ~ hadoop fs -ls /tmp Found 1 items drwxr-xr-x - lox supergroup 0 2012-02-15 00:08 /tmp/this-is-a-test-dir ➜ ~
好了。基础工作已经准备好,在接下来的旅程中,我会初步讲解一下Hadoop的基本概念和使用方法,进而转入Lisp(Scheme)函数式编程的美妙世界,带你逐本溯源,领略一下原生态的Map和Reduce到底是什么模样,并且会顺带谈到一些我在Lisp学习过程中领略到的别样风景,包括但不限于Java的反射、序列化等一些高级特性,XML、JSON的数据语言的特性特点等等。敬请期待!
--
Footnotes:
1 第29次中国互联网络发展状况统计报告显示,2012年初,中国网民共计5.13亿。
2 关于这个定义的出处可以参考弯曲评论上一篇非常好的关于云计算的科普文章“云里雾里云计算”,本文不打算探讨云计算的社会意义、产业变革、安全等过于宏大的主题(其实我对这些一点都不了解)。
3 MapReduce的第一篇论文"MapReduce: Simplified Data Processing on Large Clusters"曾写到:"Our abstraction is inspired by the map and reduce primitives present in Lisp and many other functional languages."可见,MapReduce的思想来自于古老的Lisp语言。
4 广告一下,在我有限的阅读经历中,《SICP》是我读过的计算机书籍中最棒的一本,没有之一。如果能认真做完这本书里面的356道题目,绝对会让你对编程本质的理解有一个脱胎换骨般的提高。这里有我个人的部分习题解答代码和学习笔记。
5 关于这一点,刘未鹏的《知其所以然》系列文章里有更好的解读,我就不再重复了。
8 据《Unix编程艺术》的序言里的脚注:“从1969年到2003年,35年世间并不短。以这期间众多Unix站点数量的历史曲线来估算,人们在Unix系统的开发方面投入了约5000万人年”。
9 这原本是Brooks's Law的一种观点。
打造高效的工作环境(1):Why Windows Sucks
Table of Contents
1 缘起
这两天我的ArchLinux系统碰到了一个十分诡异的问题,就是电脑无法待机、关机,也无法重启,更令人拍案叫绝的是,电脑在关机重启的过程中,当硬盘停止转动后,整个系统就Hang住了,而屏幕终端还在,只是不再响应任何请求。解决这个问题的唯一办法就是强制关机,但是这种方法实在有失水准,有伤大雅。在尝试了增删内核模块、更新驱动的等多种方法后,我终于在ArchLinux BBS上找到了解决方案。
Google了几个来回,再看一些关于操作系统IT历史的八卦,半个下午就耗掉了,从某种意义上来说,这是在浪费时间。而事实上,如果不算辞掉工作更换电脑被迫地系统调优的那次,我已经至少半年没有进行过OS和软件层面的Tweak工作了。这其中的缘由,大概是由于电脑折腾久了,就会折腾出一套适合自己口味的解决方案,这套解决方案,就是接下来一系列文章的主题——打造高效的工作环境。
打造高效的工作环境,Wow,多么宏大的一个主题啊,不过我见识有限,就这个话题,我只能谈谈电脑相关的知识,和我个人的理解,我不会讲到:
- 桌上要放几盆草
- 要不要听轻音乐
- 开放式的办公空间
等与电脑毫不相关的话题。除此之外,还有一个前提,那就是我的文章主要针对Linux和Mac用户,对Windows用户的参考价值不大。
Why Not Windows?Why Linux?Why Mac?
我100%地相信,在中国,100%的人是通过Windows系统进入电脑的世界的,我也是。但是我也100%地相信,如果你是一个程序员Geek,用Linux或者Mac,会让你的生活变得更美好;如果你只是一个普通的电脑使用者,用Mac或者Linux,至少不会让你的生活变得更差。
说到这里,很多人会跳出来争辩,多数论调是:
- Linux的驱动如何如何不好
- Linux的桌面如何如何烂
- Linux下的软件如何如何不完善
- Linux下的游戏如何如何匮乏
我的回应是,对于一件事情,对于一件事情,我认为,人的认知有四种状态,分别是:
- You know you know.
- You Know you don't know.
- You don't know you know.
- You don't know you don't know.
"You know you know"说的是类似于1+1=2这类的常识,首先是你知道"1+1=2"这个知识点,进一步讲,你知道"1+1=2"这个知识点是一个认知事实,而你自己对于这个认知事实也是知晓的,所以归结下来是"You know you know",说的通俗点,就是“你是知道‘你本人是大学文化,所以会算1+1=2’这个事实的”。
"You know you don't know"说的是我这样的Coder,知道自己水平不够,功力尚浅,不懂得AI,不懂得数据库,不会算法,但好在还有自知之明,所为“吾生而有涯,而知也无涯”,"You know you don't know",学吧,学到白头学到老。
"You don't know you know"的情况很少见,这种情况常见于某些天赋异禀而不自知的人,就好比练成了九阳神功的张无忌,明明已经武功盖世,却不自知,见到阿猫阿狗也会心底害怕。
"You don't know you don't know",这句话用来形容那些狂妄自大目中无人之辈真是再合适不过。不过对于常人,我们能否从这句话中得到一些启示呢?当然可以。 事实上,小到一个生活常识,大到一门学科领域,如果你对它不甚了解,甚至完全不知,那么这种"You don't know"有很大的概率是"You don't know you don't know",而不是"You know you don't know"。仔细想想,这句话揭露了一个可怕的事实,那就是,随着知识爆炸的进行,人类在自己探索创建的辉煌文明成果面前,变得越来越无知;另一方面,人类的的知识再以指数级别的速度增长,但是培养人才的方式却没有本质的进步,这也就意味着现代人才的培养会越来越难1。
扯远了,说了这么多,就一个意思,在你对一个领域、一个知识有充分的调研学习之前,审行慎言。这也是“为什么上帝给了我们两只耳朵却只给了一张嘴巴2”。我个人曾经有过3年的用Linux做主力桌面的经验,其中有50%的时间是整个电脑上只有一个Linux系统,其余双系统并用的时间,98%的时间也是在Linux上,所以对于Linux桌面的情况,我还算有些发言权:
- Linux的驱动确实是一个软肋,不过情况较2000年左右Redhat 9.0横行的年代已经改善了很多,在这方面,Ubuntu绝对是一个集大成者,现在已经很少找到装上Ubuntu驱动不能用的电脑了,其余的发行版,经过简单配置,也完全可以搞定驱动问题。
- Linux的桌面已经非常完善了,Linux 并不是只有一个黑黑的令人敬畏的终端。KDE 4.8的设计和整合已经非常完美,各种软件的集成性比Mac有过之而无不及。
- Linux下的软件如果不比Windows多,至少不会比Windows少。很多优秀的软件诸如Amarok、Digikam、Emacs等等,都是以Linux为首要支持平台的,甚至有的软件只支持Linux,很多工业级别的软件,诸如Hadoop、MySQL、Apache等等,无一不是以Linux为最佳运行平台。
- Linux下的游戏比较匮乏,这点是不争的事实。
So,说了这么多,信也好,不信也罢,接下来谈谈:
2 Why Not Windows?
作为一个Coder,每次用Windows,我都有一种想要砸掉电脑的冲动。所以毕业设计时,在Windows上运行VMware里面跑着Mac OS X,启动Xcode写Win32 Style风格的程序,那可真是痛不欲生、终身难忘的事前黑暗时代。我搞了首打油诗:
- 文件系统多盘拼,文件命名大小混 :Windows是多根文件系统,每个根称作一个盘,而*nix的系统是单根文件系统,新来磁盘只需要在文件系统树上新增个挂载点即可;Windows文件的命名和组织从来没有任何规律,而*nix的文件系统则有一个统一的FHS标准,并且,在Linux下,几乎所有的文件名都是小写字母,并且不含有空格,这对脚本批处理是一个大大的方便之处。
- 权限控制小烦躁,命令终端很废柴 :Windows下的文件权限很困惑,我从来没搞明白,好像获得一个文件的某种特殊权限,还要去点击属性窗口;用户权限就更加混乱了,一个Administrator,后来Vista和7又加入了貌似“家长模式”等等,太乱了;*nix下的权限控制则非常简单明了,三条命令如chmod, chgrp, sudo就可以全部搞清楚;Windows下的传统cmd.exe简直废柴的不能再废柴了, 谁能告诉我为什么cmd窗口无法最大化? 真不明白这到底是哪门子的设计。
- 弹出窗口满天飞,后台进程到处藏 :在Windows下还有一点非常让我难受,就是无论是搜狗输入法、迅雷下载,还是QQ、360等,这些软件无一例外,都有一个爱好,就是首先把自己加入系统的启动项,然后呢,在你写代码看片练葵花宝典乾坤大挪移到了关口的时刻,“啪!”的一下给你整几个弹出窗口,放几条八卦新闻……还有那废柴的任务管理器,从来都是杀不掉进程,自己倒先莫名其妙地卡死了,哪里像*nix上的killall -9,手起刀落,快刀展乱麻,痛快痛快。
- 一家独大搞垄断,格式兼容已败北 :在格式兼容方面,从来都是*nix下的软件想尽办法兼容Windows的软件,但是Windows一家独大,对于兼容别的系统的软件,从来不屑一顾,举例?OpenOffice,ntfs-3g,数不胜数啊。
- 病毒木马禁不止,杀毒软件赚钱忙 :每次我去帮别人修理Windows系统,别人的第一想法都是让我先替他们杀杀毒,可见,病毒和Windows故障一样,在人们的心中难解难分。
- 硬盘整理除碎片,系统臃肿找管家 :Windows系统有一个特点,那就是任何系统装好后,都需要“深度优化”,然后才能用得比较舒畅,其中的优化包括但不限于硬盘碎片整理、软件增删、装机必备等等,这也是 为什么各种优化大师、超级兔子、碎片整理等软件“屡禁不止”的原因吧。
- 万年IE不升级,银行网商耍流氓 :IE 7.0+新增加了多标签的特性,但是呢,这个多标签特性默认情况下是只启动20%的——除非手工指定,否则点开的链接依然是在新窗口中。退一步讲,就算是手工新开个标签页,但是这个空白标签页的打开简直比乌龟还慢,至少要5秒钟,正是让人“屎可忍,而尿不可忍啊”。至于万年不变的IE6,已经国内众网商网银流氓们的ActiceX插件,我已经无力吐槽了,历史会证明,一个不支持跨平台浏览器的银行网商,绝对会是软件史上的一个笑话,或者说,这是中国银行业的奇耻大辱。
- 多情自古空余恨,聪明反被聪明误 :Windows下的很多软件都喜欢自作聪明,典型例子就是Microsoft Word。且不说各种软硬回车,最简单的一个列表,回车之后默认又是一个列表项,但是如果我想新开段落呢?很多人就不知道怎么办了,于是就各种暴力手段地搞排版,排出来的东西,可想而知。我只能说,这种自作聪明,有时候不是真的聪明,是蛮横的自作主张,是对用户意志赤裸裸的强奸啊。
个人吐槽到此结束,详情请进一步参考:
- http://www.antiwindowscatalog.com/
- https://sites.google.com/site/imterry/computer/windowssucks
- http://en.windows7sins.org/
- Google: "Why Windows Sucks"
- Google: "Anti Windows"
3 Save your life
在接下来的系列文章里面,我会分门别类地介绍我在Linux桌面使用上的一些日常经验,分享自己的一些心得。这些经验之谈对于刚刚踏入Linux大门的同志,以及对于初级Mac用户,甚至部分喜爱折腾的Windows用户,都有很大的参考价值。我觉得,在信息时代,电脑将伴随着我们的一生,高效地使用电脑,就能够在更短的时间内处理更复杂的事情,从而为自己节省出宝贵的时间,去做更有意义的事情,这是一种正向循环;而如果每天纠结于杀毒、木马、弹出窗口、软件破解,则会使你的思维受阻、降低你的工作效率,这是一种负向循环。
这一系列的读者群将以Linux用户为主(重点是Coder),高级Mac用户可以作为参考,对于Windows用户,理解起来可能会有些困难。不过话又说回来,“不经一番寒彻骨,哪得梅花扑鼻香”。我给自己定下如下两个目标:
- 在键盘上舞蹈
- 思维不会受阻
至于主题,我初步想了分为如下几个
- 高效的文件管理
- Just Find it:Findutils
- 细谈文本配置
- Shell之魂:管道
- Screen:it not a screen
- Zsh:终极Shell
- VIM:键盘上跳舞
- CLI Tools:把玩终端
- 时光机:版本控制
- 抛弃Office:LaTeX
-
KDE系列:
- Kwin
- Dolphin & Konqueror
- Konsole & Yakuake
- Krunner
敬请期待!
–