我的外骨骼,诺基

我的外骨骼,诺基

发表于《新科幻》 2013年6月

作者:杨贵福

我从小生活在金厂镇,一个半废弃的小行星上。金厂镇并不出产黄金,之所以叫这个名字,是因为我们当地人把所有金属都称做"金"。当初发现矿脉,附近几个星系的人都向金厂镇迁,顶峰的时候达到过30万人口。不过,我出生的时候富矿基本采光了,居民外迁,人口锐减。没走成的人里,主要成份除了官员、士兵、恐怖份子,就剩下两类人,土里刨食的人和土里刨食的人。这是个笑话,你们外地人不能理解。前一种土里刨食的人是农民,虽然暖棚的成本很高,不过本地生产的作物还是比其他行星运来的要便宜;另一种土里刨食的人就是我的父母这样的,挖矿为生。

士兵和恐怖分子也很难区分。一个原因是他们的铠甲看起来都差不多,全都很酷,穿上以后力大无穷,行动如飞。另一个原因是他们还经常互换身份。当时泛银河系刚刚接触河外文明,它们一个比一个强,而且都想要侵略人类。各种外星人团结一致,很快把人类打得分裂成两派,其中一派认为应该学习先进文明,融入河外星系,另一派认为应该保持自己的特色,奋战到底。所以,后来的战争主要是在人类和人类之间展开的,跟外星人关系不大了。这两派争夺所有可能得到的资源,当然也包括金厂镇的矿,所以他们交替在这里进进出出。占优势的一方,我们称为士兵,占劣势的一方,被士兵称为恐怖分子。前面我说了,其实他们穿上铠甲看起来都差不多。

遇到诺基的时候,我12岁。诺基是我的外骨骼的名字,这名字我也不知道是什么意思,不是我起的,是它身上写的。我的父母也不是什么矿主,他们才买不起那种奢侈品。我当时只认识一个矿主,就是莉亚的爸爸,不过连他也买不起外骨骼。

那天我跟着大孩子们去采矿菌。采到以后密封运回,可以跟莉亚爸爸换几根烟卷。在家长看不到的地方,几个人靠在墙上,放松肌肉抽上一根,吞云吐雾,那才叫带劲。回家的时候被问到,"又抽烟啦?",就表情木讷地摇头,这是更刺激的时候。这种刺激跟采矿菌那时候的感觉一样。明知道要摘的伞盖随时可能爆炸,可是还是我们小心翼翼地把手伸过去。下一刻,要么又多得了几根烟卷,要么,伞盖刷地爆裂,里面凝结的金矿孢子像子弹一样贯穿宇航服打进身体,血被真空吸出来,喷溅得面前的地面上满满一片。其实别的事情也充满了风险。莉亚爸爸如果被查到非法收购矿菌,会被抓去打个半死,附带损失一大笔资本。如果莉亚爸爸少了资本,安全设施就会更陈旧和短缺维护,我们这些穷小子的父母可能哪天就埋在矿洞里了。我们都是这样的,家长,青少年们,莉亚的爸爸。我们都希望下一刻运气不赖,这些好运气积累起来,我们就有钱离开金厂镇。这就像把垃圾站里捡到的零件拼吧拼吧,只要你活得够久而且够有耐心,最后总可能拼成一台能对付工作的铠甲。

选矿菌的时候,我专挑那些不那么成熟的,虽然金含量低,莉亚爸爸还会骂我是胆小鬼,压低收购价,但是它们爆炸的机会也小得多。同行的大孩子已经开始发育,他们身强力壮,胆大包天,还经常为谁先发现快熟透的矿菌而大打出手。他们好像既不怕被矿菌炸死,也不怕对方下手狠了把供气管打断。我比他们都矮小瘦弱,宁可离他们远些,他们也不喜欢靠近我这样的懦夫和我挑选的下等货。

因此,我遇到诺基的时候是独自一人。我正全神贯住地伸手探向一株矿菌,身子斜斜着,嘴里嘟嚷口诀,"幺幺洞九,九幺洞幺,哈里路亚,千万别炸",脚下突然一绊。你要是正集中精力拆炸弹的时候,旁边突然有人弄出点动静来,哪怕是放个屁,都能把你吓尿了。我当时就是这感觉。等感觉到汗顺着脖子后面淌下来的时候,我的手和身体还保持原来的姿势没动。低头一看,一只机械手从地底下冒出来正攥着我的脚脖子。

那是一个士兵,或者恐怖分子,受了重伤。他身穿铠甲,把自己埋在土里伪装起来,可能是在等救援。可是小行星周围满天卫星,他一点无线电信号也不敢发送。

他哑着嗓子对我说,"我是一个战士。"

我点点头。这句话没有半点信息含量。从铠甲上我就能看出来他是个打仗的,不过,士兵和恐怖分子都称自己为"战士",所以无法分辨他是哪伙的。

"你别低头看我,假装在采矿菌,听我说。"

其实我看他也是白看,他大半埋在土里,露出来的部分涂满了迷彩,头盔标记属于哪一方的铭牌早就磨得一片模糊了。

"你给我一些氧气,再给我一些水。"

他穿着铠甲,能轻松捏断我的脖子,我根本不敢不给,但是不得不犹豫。这些给养都是要花钱买来的,如果父母知道我被一个半死的士兵或恐怖分子抢了,说不定会把我打个半死。

"我把这身外骨骼送你。"

酷哇。虽然铠甲这么大号,也不能开着下矿,不过,有了这铠甲,我就是朋友圈子里第一个有车辆的人啦,连莉亚她爸爸也没舍得给她买呢。而且,我刚刚知道,原来这东西叫做外骨骼,不叫什么土了吧叽的铠甲。氧气和水换这么一身装备,而且叫做外骨骼,真是不赖。我点点头。

"你现在把氧气和水分我一些,"声音从地下传出来,指挥我把管子顺下去接上,"好,再来一些,再来一些。"

"再给你,我就没命回镇里了。"我切断输送。

"小兄弟,放心吧。"他的手在我的脚腕上又加了一分力量,我疼得直咧嘴。他说,"我给你留了足够的份,因为你还得回镇替我办件事。"

他让我去找镇民兵三队典少尉,单独一个人见他,就说"李记者"在这里等他。

我问,"你是个记者?我怎么看不出来。"

他粗声粗气地说,"你照着说就是,快去吧。"

我怀揣着将拥有这身埋在土里的外骨骼的梦想,向镇里跑。那位士兵或者恐怖分子,他骗了我。镇民兵三队里没有叫做典的少尉军官,更没有认识李记者的人。但他骗我最厉害的事不是这个,而是给我留下的氧气不足以支撑我回到镇里。所以,在能看到镇门的时候,我疲惫不堪,本想坐一会儿,却摔下山路,醒过来的时候面罩裂了两道纹,气流吱吱往外冒。右腿跟健断裂,不疼,但是完全不能用力,站不起来。爬了两步,又担心把宇航服磨破透气。我躺下来等死,星斗满天,银河暗涌。

那些同行去采矿菌的朋友们回来发现我的时候,我已经不能说话。我穿着宇航服,他们抬不动我,一起凑了点氧气让我先活着。我面罩的裂纹谁也不敢碰,只好让它继续往外漏气。有几个家伙跑去镇里找人,来的是莉亚的爸爸,开着他那辆在平地上也咯吱咯吱响的破车。

"小伙子,你真有种,摔成这样还没把矿菌扔了呐。"莉亚他爸一边用胶把我的面罩裂纹堵上,一边哈哈大笑说,"回去你抽烟管够,今天算我请的。"

烟不是白抽的,人不是白救的。今天所有的矿菌,所有人的所有的矿菌,都免费归了莉亚爸爸。他说,就这样,他也是稳赔不赚,才没有占我们这些孩子的便宜。

几天以后,有新闻说又抓到恐怖分子,已经处决了。抓获的时候他伪装成矿工,正准备进入金厂镇。没有提到他哪里来的氧气,没有提到他那点氧气怎么撑过了这么多天,也没有提到他的外骨骼。

我能一瘸一拐走动的时候,又去采矿菌。父母说,"你怎么这么不懂事,要是再伤了,又得花钱治。"

我当然得小心,莉亚爸爸帮助粘上的面罩把我的视野划成了几个象限,无论看星空还是行星表面的时候,无时不刻不在提醒我,"要小心"。

我的外骨骼还半埋在那里,里面已经空无一人。我挖到它的肩膀,擦一擦灰土,想看清它的原主人的阵营和阶级。铭牌已经不知什么时候磕碰掉了,露出下面原来出厂的钢印,"始于1865,NOKI",后面似乎还有什么印记,不过早就磨损得一塌糊涂了。

"NOKI,你的名字叫诺基。"我说,"你听到了,你的主人把你送给我了。"

"确认,待命。"那个躺在半截土里的大家伙一动不动,只发出低沉的语调。

"这就是我的外骨胳了啊,"我绕着它转了半圈,根据它的手的大小猜测整个机器的尺寸,"这得什么时候才能挖出来。"

我感到脚下的大地震动,烟尘四起,大机器像是植物一样从土里面伸展出来。低重力,而且没有空气,尘土飘起很高才在远处坠落。我连连后退,诺基就在我面前直立起来,比金厂镇防护门还要高。烟尘褪尽,我俩就这样站在小山丘上,我仰头望着它,他仰头望着远方。

这么庞大的外骨骼,与其说是被人穿戴起来,不如说是人钻进机械中去。不过我没有找到入口开关,也不敢在镇外贸然脱掉宇航服,只隔着手套抚摸这大机械。是核动力的,电池不知道在哪里,但是诺基的通体都是温暖的。

"哈哈,外骨骼,我的啊。"我大声地喊出来,"诺基,指令,蹲下!"

我做好准备这家伙又要激起多少烟尘和地震,但是什么也没有发生。"蹲、下!"可能无线电系统有问题吧,我一字一顿地重新下指令。它还是像是锈住了一样傻站着。

"开步走,向左转,向右转,原地起跳",都没有反应。"原来是个坏的,比莉亚的机器狗还不如。"我暗想,那个士兵还是恐怖分子又多骗了我一件事。

没用的东西就是没用的,开回去弃置的时候还要交费。我扔下诺基,专心采矿菌,贴补家用或是换烟卷,才是正事。这边采着矿菌,那边发现诺基似乎在偷看我,斜着眼睛,仍然骄傲地昂着头。我跟着矿菌的分布,渐行渐远,听到背后沉重的脚步声,是诺基始终跟着我,刚好能看到我,却保持着距离。这倒是跟莉亚的机器狗有点像了。我跑过去再试,"蹲下,开步走,原地起跳。"没有任何反应,诺基居高临下地斜睨着我。

我继续采矿菌,心想,今天可以多采些,至少这个大个儿可以帮我运到镇外。我只盘算着自己的心思,却忘记了这片山丘上的矿菌在我养伤的这几天里继续生长,更近成熟。当接近其中的一株的时候,我看到桔红色的光星星点点在几处菌褶里闪烁,瞬间扩散覆盖了整个伞盖下方。我下意识抬手挡往刺眼的光芒,心想,这下完了。

矿菌爆裂,在这个距离上,我会被飞溅的孢子射成筛子。我看到纯白的光弥漫充满整个视野,鼻子里似乎闻到了金矿特有的死亡气息。我心里最后的念头是,至少,父母迁离金厂镇,又少了一个负担。

我没有死,不然又怎么有命给你讲这个故事。诺基救了我,他以我不能想像的速度冲过来,精确地打飞了正在喷射的矿菌,而我毫发无损。矿菌拖曳着流光溢彩的长尾巴划出一条完美的曲线,照亮了大半个天空,沉到小行星的地平线下面去了。过了许久,矿菌从地平线的另一端显现出来,升得更高了,光彩也黯淡许多。当它再次沉下和升起,已经融入群星之中。

我张大了嘴盯着矿菌消失在星空里,好半天才想起来说,"谢谢你啊。"虽然我也不清楚对机器是不是也要说谢谢,但是我还是忍不住说了。

诺基依然昂着头,俯视着我,轰隆隆地说,"不客气。"

那个时候,我还不懂很多年以后自己讲给别人的道理:所有的机械都是骄傲的,有尊严的,可以指令,而不可以驱使。当你驱使它如牛马,它就蠢如牛马;当你与他心灵契合如挚友,他就待你如知己。

我打开诺基的背板,把采的矿菌都装进去货舱。他载着这许多财富,毫不费力。我钻进诺基胸板后的驾驶舱,兴致勃勃地操纵,嘴里大声复述着指令,准备隆重地把诺基介绍给大家。开到半路的时候才发现,我并没有真正地操作诺基。或者说,它只是允许我接触控制台而已,根本没理采我的指令,自顾自地行动,只是有些时候行动与我的指令一致而已。即使在驾驶舱里,而不是不在货舱或者它的肩膀上,我也更像是个乘客,在仿真训练系统里学习,而他是任性的司机,想走就走,想停就停。很遗憾,如果我获得操作权,就能卸下它的武器装备,说不能能卖个好价钱。不过即使这样,大家也都对诺基的到来非常高兴。

莉亚爸爸看着诺基这大家伙和今天的收获,笑得合不扰嘴。我今天没有要烟卷,而是换成了钱。不同于以前每次的零碎,因为我有了希望,这么多的钱,也许可以帮助父母,早晚有一天可以离开金厂镇。

我的父母很高兴,他们把诺基敲得叮当响,"真是能节省不少燃料呢,能搬运,还能取暖。"他们唯一担心的是诺基报废以后怎么才能偷摸地非法弃置不被罚款。不过这个担心可能有点早,看诺基健硕的样子,会比我们每个人活得都久。

大孩子们也很高兴,我每次都免费帮他们运矿菌。只是如果希望在采矿菌的时候受到诺基的保护,他们就得离我近一些。因为诺基从来不跟着别人走,他一直置我于他的保护范围,对别人只是顺便救助。而且,诺基不听从别人的指令,无论是命令还是恳求。

莉亚也很高兴,她和她的同学每半个月往返天梯,去附近的大行星上学。现在不再是坐莉亚爸爸那辆叮当作响的破车,每次诺基都把莉亚他们装在背板的货舱里奔跑,这样在山间跋涉的时候就快捷舒适多了。我经常一个人在驾驶室里装模作样地操作诺基,好像真的成了它的主人。也有时,我骑在诺基的肩膀上,山影和群星扑面而来,然后飞一般掠到我的身后。当诺基飞奔的时候,我能听到隐约的风声。莉亚爸爸说的对,小行星的表面的确有微量的气体。虽然小行星的引力不足以形成大气层,但是矿脉里不止歇地有气体逸出,在它们消散在宇宙里以前,在地表形成了稀薄的一层。诺基飞速冲击这称薄的一层,就形成了隐约的风声。还有的时候,我也挤进货舱里,昏黄的灯光下,大家都低着头蜷在一起,脸上蹭着机油或者泥污,带着笑。莉亚有时坐在我的对面,有时就坐在我的旁边。她总是那么干干净净的,不吱声,安静地坐着。很多年以后当我回想起骑在诺基肩上风驰电掣的时候,我有时也会后悔,那个时候应该在货舱里多坐一会儿。外面是寒冷的无尽的宇宙荒漠,身边是坚实的诺基的,或者柔软的莉亚的,温暖。

所有这些,再也感受不到。

莉亚他们有一次准备去天梯的时候,战士和恐怖分子们又激战起来了。他们执着于哪一方先开火,进行过旷日持久的争论。其实那不重要,因为对于我们来说,无非是一方与另一方打起来了。也许战争以后战士更名为恐怖分子,也许不,又有什么区别。

对我们这些孩子有影响的是,没有人敢去采矿菌了。莉亚他们也只好搁置去天梯,虽然他们心急如焚,说是学校里有重要的课程。金厂镇外有几座山被轰平了,与外界的所有通道都成了军事无人区。矿工们也都停工了,虽然矿井入口在镇内,但蔓延到镇外的坑道有几处被钻地的炮弹炸塌了。

当然,生活还要继续,我们开始习惯野炮引起的地震。桌椅会摇晃,房屋会摇晃,但是没有人担心。我们没有什么可以失去的,炮火带不走矿脉,也轰不塌金厂镇的天顶。通往其他小行星的轨道也每天被炸上七八十回,士兵和恐怖分子都担心对方从外界得到给养和更多的弹药。也因此,他们都不攻击金厂镇,士兵和恐怖分子都需要金厂镇供给食物。

我们的农业还在继续。从金矿中提取能源,点亮人工光源照射四季收获的作物。虽然收成一季不如一季,不过总还能凑和。战争双方都派了专家研究为什么收成会越来越差。这些敌对方的专家坐下来心平气和地画很多公式,讲很多术语,有时争得面红耳赤摔门而去,然后又在镇中心的酒馆搂着肩膀喝得酩酊大醉抱头痛哭。酒馆老板悄悄说,这样下去收入暴涨,他也许可以早几天离开金厂镇了。

除此以外,镇内的生活也一如既往,连天空的星座都依然耀眼。小行星表面没有大气层,镇外的灰尘不会悬在天空,而是很快就尘降到地面上。所以,无论地面上打得多么惨烈,星空依然如洗清澈。我们都是尘埃,只是过客,留下很多暂时的印迹,而星辰一直在这里。

莉亚爸爸带我和诺基去给士兵或者恐怖分子送过一次食物,差点出事。

见到他们以前,我一直以为士兵和恐怖分子都一定长相可怖,语气粗野。没有想到,我所见到的都是比采矿菌的大孩子年长不了几岁的青年,有一些还会微笑地摸我的头。只是他们大多数身上带着各种伤疤,还有一些干脆就血迹未干还没有结痂。我跟莉亚爸爸提到这一点,他哈哈大笑,说,"你以为他们是哪来的,不就是你们长大了吗,也都是血肉之躯。"

要平安无事离开时,莉亚爸爸正在数着钱,一个家伙看中了诺基,说是军事管制,理应征用。我哭着去求他,他甩手就把我推倒在地。这位士兵或恐怖分子,也一样是大不了几岁的青年,脸上长着青春痘,只是此刻表情狰狞。

他的军官救了我们。军官说,"这种老旧的型号抢它还有个屁用。"

那位军官前后总共只说了这一句话,哑着嗓子。听声音,我觉得像是诺基以前的主人,那个被处决了的李记者。但是我没敢跑过去确认,万一他后悔了把诺基要回去呢。我又想,也许他就是典少尉?我不认识他们一天三变的军衔肩牌,所以连他的阶级也不能说准,更不敢问名字。

这位无名军官的话还是帮了我们。青春痘恢复成小青年,说,"也是,不够维护成本的,不定哪天就散架了。"他挥挥手让我们离开,还算和气,好像刚刚只是想开个玩笑。

在路上,莉亚爸爸让我也喝一口酒压压惊,他说,"要是征用了诺基,咱俩怎么回镇里还真成了问题。"

我们平安回到金厂镇那天,莉亚病倒了。她已经少量咳血一段时间,镇卫生所的赤脚医生说大家都咳,查不出毛病,估计没啥大不了的,养养就能好。我们回去那天莉亚咳血喷了一地。

莉亚爸爸动员了关系,把血样送到军队医院检查,结论是呼吸系统严重受损,来源是空气中的辐射。矿井坑道被炸断以后,小行星表面的气体开始逐渐扩散到金厂镇的天顶内部。专家也终于能够解释作物的收成为什么每况愈下,因为空气里渗透进了小行星矿脉中的金,作物的种子发生变异。变异细胞的最主要表现,就是死亡。金厂镇的人没有全病成莉亚那样,也只是变异的概率不够高,假以时日,生病的人和作物会越来越多。

"瞎扯淡,"莉亚爸爸说,"空气里怎么可能有放射性重金属。"

莉亚说,"氡气就有放射性啊。"她的声音很小,好像自己生病或者知道这些知识都是犯了什么错误。

莉亚爸爸变卖了不少家产,准备把莉亚送到附近大行星上的好医院去,据说那里有先进的设施能治这病。但是战事不止,双方都担心对方从金厂镇获得食物,开始加紧封锁金厂镇对外的交通,由金厂镇到天梯的山地拓展成了军事无人区,每天轰炸,人车禁行。

有人劝他,"就算你上了天梯,也可能在轨道上被打下来啊。拖到打得不那么厉害的时候吧。"

莉亚爸爸怕莉亚拖不到那天,他拿出一半家产,说谁能把他和他女儿送到天梯,就给谁。没有人敢应征,这是拿命赌。他找到我,说只有我有这么一架外骨骼,说不定能通过炮火封锁。我说"好"。他说,"我知道你从来没有真正驾驶过诺基,我们也就是碰碰运气,不行我就认命。"

我知道他想说的是,"没有人工驾驶的细致操作,想通过无人区万难成功。"他没有说,我也没有提。他说的对,不行我就认命。

大家都说我们疯了。他抱着莉亚进了货舱,我骑上诺基的肩头。我对诺基说,"去天梯",诺基沉默着开动,他没有说我疯了。

在无人区外,诺基卸载掉所有的武装,包括弹药、火炮,还有重装甲。莉亚爸爸说,"这是精明的减负准备。通过无人区需要的是速度,我们又不可能打赢军队。"

无人区地形复杂,山势起伏。满山遍野布满了士兵或恐怖分子掘进的坑道,还有连绵的单兵坑和炮兵阵地。所有这些,都是后来我才知道的,当时只知道我们飞奔着越过一个个山头,身后激起的烟尘还没等落下,我们就已经冲进下一个阵地。

士兵和恐怖分子都以为我们是敌对的一方,在试图切割他们的阵地,纷纷射击。但是,我们快到他们来不及反应。诺基开足马力,像一把烧热的快刀,从黄油之中劈出一条急速划过的线条。炮兵来不及校准射角和装药量,我们就已经脱离了他们的射程。步兵还没能解读完雷达传来的信息,我们就转到了另一个山谷。就这样,我们通过了大半段行程。

但是后来,我们开始与越来越密集的军队遭遇,他们显然为拦截我们而提前集结起来。我们尽可能避开军队,不断变更路线,但还是被几组步兵火线阻击。我钻进货舱,诺基的轻装甲保护了我们。

我们不停地突进,通天塔一样的天梯遥遥在望,诺基却停了下来。我们被火炮阵地包围了,他们算准了我们在围追堵截之下铁定会一头钻进这个口袋。他们不知道我们是谁,为了什么,但是他们要阻止所有他们没有掌控的事物。我们不是他们的人,这就是拦截的充足理由。

望着远处天梯的剪影,莉亚爸爸直拍大腿。莉亚抱着爸爸,不知道该如何安慰。包围我们的,不知是士兵还是恐怖分子,反正他们都拥有相同的火炮。他们的火炮第一轮齐射过后,我从昏厥中醒过来的时候,莉亚在我的怀里,她咳出的鲜血染红了我整个前胸。

诺基说,这样的火炮齐射几分钟之后会再来一轮,然后是下一轮和再下一轮,他的轻装甲不知能再承受几次打击。莉亚爸爸的头抵在货舱内壁,表情松驰,还在晕厥中。我没有唤醒他,反正第二轮炮击还是要震晕过去,何必多一次痛苦。

第二轮炮击之后。我朦朦胧胧恢复意识的时候,发现自己仍然抱着莉亚,她的身体轻得就像没有重量,好像我用力就能把她抛到天梯那去。我紧紧地搂住她,生怕她会在炮击中震得飞起来。

还没等我完全清醒,紧接着就是第三轮炮击,整个小行星和我的脑壳都要炸裂开了。但是我努力保持不晕过去,因为我想起了诺基第一次救我的时候,把矿菌击打出小行星的引力场范围。我必须要告诉诺基,我嘶喊,一遍遍重复着。炮声里,我听不到自己的声音,但是我大喊,"把我们扔过去。"最终,我晕了过去。

我醒过来,莉亚爸爸说,"扔过去,你想得倒是很好。但是那边也没有海绵垫子,我们会在那头摔死。"

谈话就到这里中断,然后是第四轮炮击。从这次炮击中醒过来以后,我问诺基它能跳多高,他的历史记录是跳起几米。我摇醒莉亚,"你帮我算,这些数据。我想知道,这样的力量在金厂镇小行星,能跳多高。"

炮击。我不知道在诺基的轻装甲破裂前是否来得及完成计算,是否来得及脱逃,但是我知道,在地球上能跳起几米的诺基,在金厂镇小行星这样的低重力环境下,可以跳得更高,更远。只是诺基可能从来没有设置成这样的模式,它不知道,对于它,在小行星上的最适合的行动方式不是奔跑,而是飞翔。

莉亚没有醒过来告诉我数据,莉亚爸爸清醒的时候完成了计算。不过他说,"你要求的轨道精度必须人工操作,还得有熟练的技术。"

又一轮炮击即将开始,我们能看到天空划过一排排闪亮的影子。我大喊回答他,但是炮声随即掩盖了一切声音。

我看了一眼昏睡的莉亚,然后在剧烈的震动中爬出货舱,外面是地狱之火的海洋,夹杂着金色的矿菌孢子漫天飞舞。我非常害怕,但是听不到牙齿撞击,我颤抖着祈祷,期待无论哪个神能在这样的炮击轰鸣中听到我的声音。

我在火光里钻进诺基的护胸板,关上舱门,炮声渐弱。我一边复述指令一边操作,我大声喊,虽然知道它根本听不清我的哭腔,我说,"关机,手工操作,手工操作。"

我的指令是要告诉诺基,不惜失去它对我的所有记忆,我要莉亚活下来。

然后,我无法呼吸,又在炮击的巨震中晕了过去。我醒来的时候,听到诺基低沉的声音,我知道它还活着,没有关机,不知道是应该高兴,还是悲伤。

"不必关机就可以切换为手工操作。"诺基平静地说,"手工操作需要成年男人的责任和技能,恭喜你都已经具有。"

在下一轮炮击开始前,我操作诺基从弹坑斑驳的土地上起跳,在星空里划一条漫长而平滑的抛物线,掠过脚下正飞向目标的飞蝗般的炮弹。急速扑向天梯前我最后一眼看到的,是远方金厂镇的天顶在矿脉蜿蜒的群山环抱下闪闪发光。

诺基在空中翻转和调整姿态,弯腿缓冲平稳落地。我跌跌撞撞地从驾驶舱中爬出来,正看到近在咫尺的天梯塔身在慢慢倾斜,它的下方烟尘四起,紧接着大地传来剧烈的抖动和轰鸣。他们炸毁了天梯,为了彻底断绝敌人与外部的交通。也断绝了莉亚活下来的希望。我的全身抖个不停,没有力量从驾驶舱滑下来,就坐在那里放声大哭。诺基处于手动模式,比平时更加沉默,只用微温的机壳拥着我。

那一天剩下的时光,我们一直躲在天梯的废墟里,听四周火炮不时轰鸣。莉亚感到非常冷,我和莉亚爸爸轮流抱着温暖她。莉亚没有活着回到金厂镇,她死在了我的怀里。我永远记得最后温暖和柔软的感觉。

当战事不那么惨烈的时候,不知哪一方修复了天梯,另一方没有制止。金厂镇的人弹冠相庆,说矿能运出去,收入好一些,日子可以不那么紧巴。对我,这没有什么变化。有些需要就像降落伞,当你渴求它的时候,如果它不出现,以后出现与否,那也没有什么意义。

我们从天梯回来以后,莉亚爸爸迅速衰老了。他老得那么快,你正跟他喝着酒,就能看到他的腰慢慢地变弯了,脸上的皱纹刀刻一样生长出来。他总是一声不吭地喝完酒,然后拍拍我的肩膀就走了。

他不再收矿菌,矿厂也关掉了。他花了很多钱喝酒,喝到最后几乎所有的财富都变成了酒精,只剩下只身一人离开金厂镇的钱。他拒绝我和诺基送他,执意要徒步去天梯。我说,"你这得什么时候才能走到啊。"他说,"总能走到吧。"这是我听到他说的最后一句话,以后再也没有见面。

我目送莉亚爸爸的背影,突然发现自己想不起来莉亚年轻的面孔。她如何微笑,她的头发是怎样弯曲披散,我以为会永远铭记清晰得触手可及,如今却只剩模糊的印象。我一直以为自己在日夜思念着她,却再也想不起来她的样子。

我跳进诺基,大声叫喊着指令让它在旷野上奔跑,就像失去莉亚的那天晚上。诺基还是微温的,一如既往。这样能让我稍微想起莉亚在我怀里最后的温度。我和诺基在每一个军事无人区狂奔,炮火就在我们身边接连炸响。在整个小行星上放眼望去,是一直曼延到地平线的燃烧的群山。

雷霆轰鸣中,我们被抛起在半空,然后重重地砸在地面上。这是我最后的印象。我以为我和诺基会死在这次鲁莽的奔跑中,但是我们伤痕累累却活了下来。我们落在了士兵或恐怖份子的手里,我和诺基都被征用了。被哪一方征用了,又有什么区别,反正我和诺基受命杀光另一方。

我们经常就在金厂镇的附近战斗,但是我一点也不想逃回去。在这里,或者在那里,又有什么区别?有时我们被这一方俘虏,有时被那一方抓获,我和诺基一声不吭,支持他们所有的政策和理念,伤痕累累地跟他们去杀另一方。

杀光了其中一方,我和战友们就离开金厂镇所在的小行星,被打包成捆一样发送到别的星系。但是诺基没有走成。他型号老旧,体积庞大,不再适合日新月异的战术需求了。

我提出过异议,这是我的个人物品,应该归还金厂镇转交我的父母。只是诺基拒绝跟随任何人,不听其他人的指挥,这很令我犯难。军需官说,"首长,这有什么难的,看我的。"

他熟练地给诺基输入几条指令,诺基突然僵住不动,慢慢变冷。再启动的时候,它不再认识我,但是变得对所有人都温驯和服从,可以留在金厂镇作为有用的设备了。

"你看,标准的老式工业机器人。"军需官说。

"很好,有你的。赏。"我拍拍他的肩膀。

我和我的战友们征战了整个泛银河系,我的战友和外骨骼不断更新,我的阶级不断上升。能一直活着并且升阶级的原因非常简单,别的那些人的运气都非常地不好,他们或者死于我们,或者死于敌人的炮火之下。

他们说,我操作外骨骼似乎有天生的灵性,无论是攻击,还是从溃败的战场下撤,总能得心应手。其实,他们只是不相信我的可以告诉每一个人的秘密。所有的外骨骼都是诺基的亲戚,他们全都血肉相连。每当我更换新的外骨骼,我总是先给他们讲一遍诺基的故事。然后,它就和我成了朋友。这些朋友,后来大多战死了,只有我活了下来。有战友开玩笑,说我会一直这样活下去,不断升阶级,直到只有皇帝或总统一个人可以杀了我那天。

这么长的生命里,终于有一天我又见到了诺基。或者说,我认为见到了它。

那是一次扫荡的超小型战役,几乎没有纠缠,是上级赏给我们的肥肉。在攻击中,我与一台外骨骼狭路相缝,一看它就是老旧笨重的型号,虽然漆得焕然一新。本来没有悬念,无论是我的技术还是我的外骨骼的性能。我的战刀毫不犹豫地斜劈下去,对方奋力一闪,居然躲得半条命在。刀锋无坚不摧,却只切掉了它肩上的铭牌,露出下面陈旧的底子。

我从后面扼住它的脖颈,让它暴露出胸甲且无法行动,召唤旁边的战友,"来,捅一刀。"就在战友驾着他的外骨骼冲过来的时候,我突然看到对手肩上露出的模糊不清的钢印,隐约可以读出厂商的标识"始于1865,NOKI"。

我大喝一声,"诺基!"它正挣扎着的动作一滞,然后瘫软在我的怀里。

我的战友指给我看,"嗨,你也太大意了。这个家伙的肘刀已经刺中你外骨骼的护胸板,我再晚半秒,你就被它从前往后扎透啦。"

操作诺基的家伙束手就擒的时候满嘴血沫子,他对我喊,"如果不是外骨骼突然卡住了,你早就成了我的刀下鬼。"这个勇敢的青年由于信仰坚定被准许弃暗投明,后来在泛银河系不知道哪个角落的拉锯争夺里英勇战死。

那次战斗结束以后,没有人想要这样老旧的型号作为战利品,只是围过来看热闹,看敌人已经破落到何种程度。大家哈哈笑着从列队摆好的机器前走过,指指点点。

有一个说,"居然连这样的型号也拉出来献宝了,诺基A型,你听说过吗?"

我站在诺基的影子里,费力地仰头才能看到它的面孔,用不屑一顾的语气说给我的战友听,"那些老古董,谁又知道。"

诺基的背后,陌生的星座无声地闪烁着布满太空。我问,"战争已经漫延到什么星系了,这里离金厂镇有多远。"

没有人回答我。诺基静立不语,我的战友也已经走远了。

Disptach系列谈1:branch table

Disptach系列谈1:branch table

就disptach这一意义而言,branch table与很多技术都是相同的,包括虚函数,中断向量,symbol

table,dispatch (SICP中提到),call back, windows消息响应,MFC消息响应,CPU的指令执行循环。

如果这一篇对大家有意义,那么,我以后就继续写下去,把后面的技术挨个介绍了。不然,就仅只 branch table吧,它本身也够强力了。

1. 追求解析解之无望,然后呢?

童话的最后一句说,"从此王子与公主过上了幸福的生活",好像前面的一切铺垫啊痛苦啊斗争啊,到此结束,从现在开始就风平浪静再无矛盾,可以无忧无虑了。我们知道,指望找到万能良药或者银弹,一了百了地解决工程上的需求是不可能的。现实世界不是这样美好的,甚至存在这种幻想都有害无益。

不过另一方面,是不是可以归结为虚无主义,这世界就没有规律可循,工程中的所有需求必须每次都找个牛人解决,不然就束手无策呢?我以前问过本科的导师李老师,工程师这一辈子要一直追赶新技术,是不是就没个头,没有希望了呢。后来,我在博客里提到,答案不是那么悲观的,解析解也许并不存在,但是局部的优势偶尔还是有的。对于某些问题,我们确实可以找到足够好的方法。

比如branch table所代表的思想,就是其中的一个有效方法。

2. 从刘邦说起,任务与执行者的关系

刘邦,太祖高皇帝。得势以后有人问起他为什么这么牛,我们可以想像他洋洋自得地谦虚的神态,他说:我啥啥不如萧何,啥啥不如韩信,啥啥不如张良,那为啥单只我刘邦能统一天下呢,因为我能用人呐。

批判略过。

刘邦所做的,叫做"dispatch",中文翻译为分发。有的书中翻译为调度,我们所不取也。因为调度还有另一个英文词与之对应,就是

schedule,表示计划在以后的某个时间段去做事,而dispatch的意思大抵是现在马上就做。有牛人可能说,这不明明是delegate么。是的,比喻的故事么,你也可以强调那个方面,不过,我想讨论的方向,就只是

dispatch,delegate还是dispatch以后的事。

Dispatch的作用在于,"我"并不知道应该如何完成某项工作,但是"我"知道"谁"可以胜任这一任务。今天讨论的重点,不是完成这个任务的是"谁",而是"我"所知道的重要信息,即"我"知道任务"谁"之间的对应关系。重点就是这一关系。

任务与执行者间的关系如何记录在程序中呢?最直接的想法就是用代码来记录吧。从冯・诺伊曼体系结构以后,代码与数据分开来存储,分别另眼看待,所有的信息如果想存储起来,就要先选择它是数据,还是逻辑。

如果任务与执行者的关系用代码 (逻辑)来记录,那么应该是什么样呢?

3. switch-case

可以用switch-case,或者if-else来写,这二者无甚区别。如下:

(代码片断1)

1 switch (任务)

2 {

3 case 适合张良:

4 张良do();

5 break;

6 case 适合韩信:

7 韩信do();

8 break;

9 case 适合萧何:

10 萧何do();

11 break;

12 }

在以上代码中,第一行的意思是:根据任务的情况 (或其中的信息) 而进行选择(转发)。

以后每一行的case,代表一种情况,case后的 适合张良,是个逻辑表达式,返回结果是个逻辑上的真假,而本身是个谓词的表达式。

以上代码也是很多年轻程序员和年轻的其他人类的长久困惑,"活儿都是俺们干的,经理或者老板到底做了什么。"刘邦做了什么呢,他的责任就是分发--决定把什么样的任务派给谁。

换句话说,上面的代码"记录"了刘邦的功能。在计算机的世界里,刘邦就是用上面的代码实现的,每当来个任务,刘邦就run起来,直到把任务转交给某个人。

4. branch table

switch-case实现了记录disptach的任务和执行者的关系,不过它也有些毛病。如果刘邦可能还能把任务转给很多别的人,那么这个switch-case就要变长了。每个可转发的人,会使switch-case增加3行,只需30个人,一屏80行就容纳不下了。也就是说,看后面的某个case的时候,你看不到前面的switch。无疑地,这让你在编程时得留一个心眼想到"有case,前面肯定得有switch,而且...对了,这个是给刘邦分派任务用的"。如果你心眼多还好,如果心眼少,再多些别的需要关注的,很容易就整得缺心眼了。

工程方法之所以存在,就是为了让心眼不那么多的人,也能做心眼非常多之牛人能做的事,甚至做得更好。按萨特的观点,如果你能完成牛人做的事,那你就也是牛人。

除了switch-case可能变长,刘邦还可能在开始disptach之前和结束之后,还要做初始化和清理的工作,而那些,与任务和执行者的关系没有任何关联。软件工程追求的目标之一:高内聚低藕合。凡是无关的,我们希望它们能离得远一些。初始化和清理工作,它们与任务和执行的关系关联较小,我们因此希望它它们与这些switch-case离得远一些。

更关键的是,我们意识到这个switch-case结构是不会随意人员增加而发生变化的。人员与任务的对应关系会变,但是这个关系的存在、我们利用switch-case结构实现这个关系的对应,这些是不会改变的。不变的东西在人类历史上具有特别重要的意义,中流砥柱和海枯石烂的精神正是因此而受到赞扬的。虽然现在不流行了...另外,这些不变并非原来就存在的,而是人们创造或者发现出来的。有人问到,宇宙定律为什么适合于很多别处。那是因为我们把那些恰好也适合于很多别处的事件总结为了定律,那些变化的,都被我们抛弃了。即使大河奔流,世界变化莫测,人不能再次时踏入同一条河流,而河流的奔流这一变化本身--正是不变的。

扯远了,再拉回来。有人可能争辩,他可以这么写,就解决了上述问题:

(代码片断2)

1 switch (任务)

2 {

3 case 适合张良: 张良do(); break;

4 case 适合韩信: 韩信do(); break;

5 case 适合萧何: 萧何do(); break;

6 }

事实上,插一句,除了这种优秀写法与我们的第一种写法,还有更不符合软件工程原则的写法,把每个case都写得很长--那里不是 张良do()

这样的函数,而是 张良do()的函数体本身,长达三五十行或者更长。当然,这种方案逞一时之快(或者叫牛人的匹夫之勇?)尚可,但是长此以往,后面修改的难度可就大了。每个case都这么长,再加上如果switch是第一级缩进,等缩到张良do()的函数体,就是第三级,如果张良do()的函数体本身再有if-else或者for循环呢?

代码片断2这种写法,每增加一个case只增加一行,case的条件与执行者的对应关系一目了然。那么,我们为什么不再进一步,按下面这样写呢?

(代码片断3-1)

1 适合张良 张良do()

2 适合韩信 韩信do()

3 适合萧何 萧何do()

没错,这不是C代码,所以不行。那么像下面这样呢?

分发条件类型的数组 cond = {适合张良, 适合韩信, 适合萧何};

执行人的数组 worker = {张良do, 韩信do(), 萧何do()};

这样,我们把任务 (的适合发布条件)

与执行人的关系,从用代码记录改为了用数据记录。这有什么好处?最大的好处是,switch-case这个稳定的结构可以不变,可以在工程接下来的迭代中,不需要变化。无论是增加新的人和任务的对应关系,还是修改初始化和清理的动作,都不需要触碰switch-case这个结构。当然,这个结构已经不再是上述的样子,而变成了:

(代码片断3-2)

1 for( 每一个 current_cond)

2 {

3 if(current_cond == 任务)

// 原始代码为:switch (任务) - case (适合某条件),

// 这里的current_cond就相当于"某条件"

4 执行与cond相同下标的worker;

5 }

5. 实例

下述实例是C语言的,电分析化学设备的一部分,为方便阅读进行了剪裁。

为了定义 执行者 表方便,我们用到了函数指针,先简单复习一下。

类型定义的时候:

(代码片断4-1)

1 typedef int (*func_ptr)(float*);

这表示所有的执行者的函数都具有这样两个相同点:参数是float指针,返回值是int。它们唯一的不同,就是名字不同。函数签名一共就三点,它们有两点一样。

函数指针的实例定义的时候:

(代码片断4-2)

func_prt foobar=某个函数指针;

调用的时候:

(代码片断4-3)

int a = foobar(2.0);

以上是函数指针的复习,下面是 branch table 的一个实例。

(1) 条件 表

(代码片断5-1)

1 int method [MAX_METHOD_NUM]={CV , OCV, ITC, LSV, SWV, NPV};

CV,OCV等都是宏定义,代表一种电化学方法。对于 branch table 而言,这些电化学方法就是

适合执行某个函数的条件,也即任务--不同的任务,用不同的函数执行。

(2) 函数 表(执行者表)

(代码片断5-2)

1 typedef int (*func_ptr)(float*);

2 func_ptr func_array[MAX_METHOD_NUM]={

3 CV_Config, OCV_Config, ITC_Config, LSV_Config, SWV_Config, NPV_Config};

这里的CV_Config和OCV_Config等都是函数名。在别的地方,声明和定义着它们,像这样: int

CV_Config(float*); int

OCV_Config(float*)。它们就是适合于某个条件时要执行的函数。对应的条件和函数,它们的下标是相同的。

(3) 查找函数

(代码片断5-3)

1 func_ptr lookup(float task)

2 {

3 int i=0;

4 for(i=0;i<MAX_METHOD_NUM;i++)

5 {

6 if(method[i]==task)

7 {

8 return config_funtor[i];

9 }

10 }

11 }

其中的lookup的本意是"查找",这里的用意是查找哪员大将符合执行这个任务的条件。

(4) 执行部分

(代码片断5-4)

1 func_ptr foo = lookup(task);

2 int a = foo();

其中 lookup 以 task 为参数,返回值是查找到的适合于task的函数的指针,这

一指针赋值给foo (相同基类型的指针) 。在第2行执行这个函数foo,返回值赋值

给a。

或者,更简单的写法:

(代码片断5-5)

1 lookup(task)();

有人可能会抱怨,(代码片断5-5)这样的写法太逆天或者残忍或者诸如此类的形容词。为什么可以这么写呢,除了受到C的训练以后,你得习惯读这样的代码,另一个更重要的原因是--这一段代码,你根本就不会再去改它。事实上,除了条件表和函数表以外,在以后的迭代中,无论天翻地覆,只要不需要触及灵魂深入的switch-case这一结构,其他的部分是不需要修改也不需要阅读的。

当把继续维护的任务转交给别人时,你也只需要告诉他,

a. 我们用了 branch table,

b. 条件表和任务表分别在哪里,

c.函数原型 (即函数表中元素的类型,本例中是 int (foo*) (float*),

d. 任务的类型 (即任务表中元素的类型,本例中是 int)。

你完全不需要告诉它"这个switch-case可别改坏了","这两个case之间其实没有任何变量藕合"等等,如果担心,你可以把除任务表和函数表以外的东西都放到某个头文件里,甚至编译成静态库或动态库。这样,你给续任者的就是一个框架,而不是一堆容易冒错的规范。C++之父有云,如果你不查让别人做的,不是告诉他,而是让他无法那么做,而不是小心翼翼提心吊胆地一边替你卖命一边担心你的评价。

然后呢?我们把刘邦流放了,让随便一个什么人坐在那里,来一个任务,就到任务表里查一下,然后分派给适合的人。从此,王子和公主过上了幸福的生活。

--------------------

博客会手工同步到以下地址:

[http://giftdotyoung.blogspot.com]

[http://blog.csdn.net/younggift]

怀念的东西:Pirka咖啡,芬兰的味道

怀念的东西:Pirka咖啡,芬兰的味道

前一段收到了小牛同学从芬兰托人寄来的咖啡。拿着提货单的时候,我满脑子问号。这寄货人是谁的呢,我完全没有印象。而且写的是食品。我又想起了最近报道的诈骗消息,给你寄去一堆什么酒,你签收了以后派黑社会找你要钱,死拉贵。

我当时完全忘了小牛同学提到要寄给我咖啡的事,把包裹拿在手里的时候也没想起来。拆开的时候,突然就看到了包装上的字样。我叫道:咖啡啊。

包装上印着"Pirka"。他们教我的,不按英语的读法,应该读作 毕若咖

这样的,每个字母都发音,P和K都要发硬音。这家公司似乎还生产鸡腿鸡翅,泡好作料的,放炉子里烤……有说明书的,照着操作就行了。

在芬兰的时候钱挺紧的,但是咖啡我没少买。实验室的习惯是如果你把自己的咖啡送去了,就也可以参与喝。我知道自己喝得多,隔三差五的买一包送去。记得有一次有个家伙看我在那喝,特意又告诉我一次规矩,我正估计那会儿正陶醉呢,顺口就说"恩纳"之类的,他又告诉我一次,我又说"恩纳"。他诧异地看了我几眼,走了。现在想想,估计他以为我白喝,又担心我听不懂,或者就是所谓歧视吧。歧视之类的,这二三十年我才逐渐明白,所以很多个当时都懵懂,凭空多了不少幸福。现在想明白即使牙根痒痒,也只好作罢,总不能冲回去找到这家伙质问,你哪只眼睛看俺们中国人买不起。更何况,我脸盲,那位仁兄长啥样完全没有印像了,到哪里去找。

可能因为地处寒冷地带,芬兰人嗜烟酒。咱们也差不多,和南方相比,东北人的烟酒要重很多。芬兰的咖啡有五个档,从最淡到最浓。最初的时候,即使最淡的咖啡一开包,我闻起来也跟雪茄味差不多,后来,我每天喝最浓的那种刚滤出来的,一天三杯--早中晚各一杯,喝到下一杯开始为止,基本能接上。直到有一天去赫尔辛基,傍晚的时候头疼得不行,勉力支持到实验室赶紧整上一大杯浓的,渐渐好起来。这才知道大事不好,瘾已经很重了。后来就是戒咖啡,戒断反应伴随了半年左右,每天因为低血压而头疼得不行。再后来,戒了有两年吧,我又恢复喝咖啡了。不少同学同事见我喝的时候就问,你不戒了吗?我就笑。其实我心想,人生苦短,就这么两年,咖啡的损害来得及吗。

寄给我咖啡的小牛同学身材高大得很,在芬兰人面前也需要半弯着腰才平等。我们是怎么认识的来着,想不起来了。也许是先在谁家吃饭,然后我就和老刘同学去小牛同学家包饺子了。也许,我和小牛同学在锻炼中心附近那马路上遇到了,然后打招呼确认对方是中国人。再不然,在实验室楼下的大厅或走廊里吧。之后很多事情,听他八卦芬兰人,讲打工和美女的故事,讲学习。他后来替我们订了好几次芯片,然后寄给我们,我都没有给过他邮费。有时他就在沈阳,我也没有时间去探望一下,殊为遗憾。对了,当年帮他搬家扭了脖子,第二天本来要去赫尔辛基,已经订了车票。我正哀声叹气这车票钱算白瞎,好几十欧元呢,实验室一个大胡子哥们说这个能退吧。我说,哪哪的规定上写着不能的啊。他就路见不平带我去售票点那儿把票退了。我问,你跟他说的啥啊,他就给退了。他说,我就说你扭了脖子去不了啦啊,然后他就给退了。此时此刻,我想像着我站在这哥们后面,歪着脖子,一脸茫然看他们对话。这哥们还带我去校医院,看能不能便宜治脖子来着。其实,他也不怎么认识我,我都不记得他的名字,估计他也读不出来我的名字。我说要请他吃顿饭庆祝一下,没有成行,要送礼物来着,一直一直拖着。

Pirka咖啡比我磨得精细,味道也强劲得很。当此夏日,半夜的时候天空仍然不会黑透,呈现出深沉的暗蓝,端一大杯,不加糖和奶,看窗户外渐渐黑下去,灯光渐次亮起再渐次熄灭。如果是芬兰,接下来将是更长的白昼,晨昏线徘徊在天际迟迟不退,新的一天转眼就又来了。是时候想念一下芬兰的朋友们:小牛同学,老刘,小刘,关同学,师姐,炒茄子的牛老师,Johan

Linus教授,教授的两位牛学生Johan第二和Andreas...你们还好吧

--------------------

博客会手工同步到以下地址:

[http://giftdotyoung.blogspot.com]

[http://blog.csdn.net/younggift]

怀念的东西:魔方

怀念的东西:魔方

最近一段做 usb slave,痛苦的gadgetfs时期,包师弟指导帮助,总算见了亮。这一段拍的照片在[http://www.douban.com/photos/album/103192366/]。有很多云,晚霞、卷层云、积雪云,有比平均距离近3万公里的大月亮,有ACM通化赛,有2013毕业季等。各种生活。

以前跟你说过吧,我小学转学了好几次,其中一个堪称贵族小学。反正现在看,当年同学的家长及当年同学的现在都过得跟贵族似的。有一次在王某同学家蹭书看,第一次见到魔方。我在王同学家还看到平生第一本计算机书,讲基本原理的。还第一次看到手持的游戏机,单元液晶屏幕的。王同学的妈妈一直说,一块儿吃点饭吧,我一直拒绝,直到把游戏机玩没电,屏幕完全不亮了。走的时候,我死皮赖脸地借到了那本魔方教程,拿回家去抄下来。

抄书这事,是不学自会的,也不需要先贤启发。如果有本书不太厚,你还特别想回顾,又刚好买不起,抄书就是最朴素直接的选择。因此,大学期间,我也抄了不少计算机书。那本书似乎是个英国小姑娘写的,讲解了把一个块移到另一个位置应该遵循什么样的步骤,如何避免副作用。我照着画了不少图,记得当时想发明一套符号体系记录,似乎是失败了,也可能成功了,如果找到当时抄的书,估计现在连我也读不懂。

但是,从那以后很多年,五年以上十年以下吧,我一直就没有把魔方拿在手里过。我可以想像那东西什么样,商店里柜台也见到过。从同学的手里应该也借来摸过,不过不同于书,魔方不适合较长时间借来玩,那玩意会磨损的。我甚至可能问过营业员多少钱,印象里价格很打击人。

初中吧,我在二商店见到柜台里有个贼破的魔方。机会来了!我问多少钱,答那是不卖的。是因为太破了,还是那是个人的不是商店的,我不记得了。我再次死皮赖脸地求营业员阿姨,以贰圆钱买了下来。两员钱,大约相当于我一顿中午饭,合现在三十元左右?

但是,我却找不到我的手抄本了!读到这里,不知道你能否体会我当时那种欲哭无泪的感觉。我老觉得如果现在不做可能明天再也没有机会,甚至活着不活着都不知道,这种心理大概确实就是从那个时候开始形成的。

后来,我还见过很多别的像魔方一样的东西,不过一直没机会把魔方复原。我哥用铁丝做过两个九连环。他做东西非常精细,那铁环圆得简单可以用游标卡尺,魔得精光瓦亮的。我们练习了不短的时候。记得他和我左手和右手都可以拆装,十多分种吧。几年前见到老外问中国学生这玩意怎么玩,同学们研究了半天,我自豪地拿过来卡卡一顿操作,快得他们看不清手法。我还见过魔尺,由一块金字塔组成,能拧成球啊柱啊等各种形状。去北京培训的时候没事,跟韩老师买的。窝在空调屋里,我们一边看《武林外传》,一边探这个东西。那次买的,质量差得很,不小心就能拧断。几年以后,我又买过质量好的,不过,当初探索热情已缺,除了把说明书上所有的示例都拧出来显摆以外,用处不大了。还有魔盘,又见拼图,1到8个数字,放在3*3的空间里,利用那个空的位置把数字们排序。小学第一次见到,好像是我妈买的,当时没整明白。大学毕业以后手机里有一个,突然开了窍,找到一个普遍的解法,虽然麻烦,但是一定能整出来,最快似乎是9秒左右。然后兴趣了了。偶像YMH告诉我,说这算法还可以优化,有最优算法,可以用规划

(?),不过,我满足以整出来就行,更深入的还是留给牛人们吧。牛人们什么样呢,举个例子吧。偶像夫人曾经非常喜欢推箱子,有的关过不去就请教偶像。偶像不盛其烦,就写了个程序,自动求解的,列出步骤照着做就行了。

有魔柱,一个柱子上好几个环,环上有数字,数字可以跨过环,拧环、移动数字,利用空位达成某种排序--我从来没有成功过。

江山待有人才出,各领风骚数百年。二猫这一代就不同了。她很早就有个魔方,挺小的,边长两厘米左右。她一旦知道这玩意能拧,而且知道能拧成各面都相同的颜色,就要求我整一把。

我败了。这个我也不行啊。演示了把单独一个面拧成一个色儿。她说,那你再努力吧。有天趁她不在,我把魔方拆了,重新装成复原的样子,显摆了一顿。她一直问我怎么整的,我一直不说。不过,为避免留下撒谎的劣迹,最后,我还是招了。她说:你啥时候拧一个吧。

然后我就把这事给忘了,就像忘掉在小学同学家借了书抄一样。

有一天讨论的时候看桌上有个魔方,拧了两下,非常顺畅的手感。我感叹你们挺有钱呐。在我心里,魔方仍然是根本买不起的东西。郑同学说,十块钱。我心中窃喜,我也能买得起啊。然后感叹,没工夫学啊。我的心里仍然需要抄本书,记住那些避免副作用的步骤,把一个块移到另一处,这得多长时间啊。郑同学说,有个魔方小站,上面有视频教程,一个小时吧,就能学会。

我说:啊?

说实话,我根本没有相信。我问,你学会了没。郑同学说,不熟练。我说,那你拧一个。郑同学谦虚地说,我快忘光了,不过同时拿起了魔方开拧。

当时,我正准备去上课,还有一分钟吧。我看了两眼,说,我可不等了,得去上课了。郑同学说,等等,马上好。我说:我马上就上课了。

郑同学说:马、上、好。

大概就花了这么久,她就把魔方复原了。两分钟?

今天我终于找到时间把那教程看了。果然如郑同学所说,一个嘴挺大胡子拉碴的男生讲的。我看了不止一个小时,前后估计两三个小时,有的地方没看明白,有的地方精力不集中,没记住。倒回去重看来着。

半背着半照着做,反正,现在魔方复原了。中国的纪录是15秒,世界纪录是不到10秒,一般的正常人类,据说一两分钟。

有的同学可能会问,都已经有求解算法了,还有像星门一样的设备,把魔方装上去,卡卡卡卡,它就替你还原了。那么,非要手拧回去,意义何在?

大刘先生在小说《诗云》当中提到,机器人还是外星人的,最终理解了诗歌是不能用机械的方法生成的,它感受不到这种美。大刘先生此前写过一个诗歌机,似乎是用FOXBASE写的,或者BASIC,作品水平一般。此后数年,有学者用程序生成了宋词,水平已经可以糊弄文艺小青年,放琼瑶小说里说是主人公写的或者某代不知名作品,估计问题不大。那么,如果世易时移,机器终究能创造出真正的诗歌了,如何看待又一个领域人不如机器呢?

讨论过这样一个问题,电钢琴能不能替代声学钢琴?

很多人文学者这样回答:因为某某技术的限制,因为某某问题之太复杂 (以至于……),所以某某传统是不可替代的。

这是扯淡之论。你一个人文学者,怎么能有资格讨论技术是否有限制,你那么简单的头脑,哪知道别人可能轻易理解或者公式推导解决这一对你而言太复杂的问题。

你应该这么回答。即使机器能够替代人类,但是:1.这种创造的过程中的"美",只能由人,而不能由机器替代感受。这个道理好懂,《屋顶上的轻骑兵》或刘德华的《战神》,小青年受某高帅富委派送公主去哪哪,最后跟公主结婚生子的,还得是高帅富本人,不是作为工具的小青年。为什么观棋不语真君子,道理也在这里,你不能替我享受思考的乐趣。2.感受创造结果的美,需要理解这一创造过程,甚至亲自尝试一样。我可以拒绝尝试,找个工具来做,但是没有人可以替我选择放弃。

诗歌的创作,弹琴歌唱,下棋,爬山运动。除了自然力,没有人类可以禁止我们选择辛劳,如果我们乐在其中。即使受自然力所限,总有一天,我们的记忆会引领我们再回到从前,追求我们的理想。

你还记得最初的理想吗?

--------------------

博客会手工同步到以下地址:

[http://giftdotyoung.blogspot.com]

[http://blog.csdn.net/younggift]

表面的意思和真正的意思

表面的意思和真正的意思

抑郁得很,出来透口气。

这两天在douban上看贴子,一位女士回忆她小时候的好朋友。纯真的友谊,那个时代,可能还不叫闺蜜,发小这样的词,也可能还没有从北京

(?)走向全国 。该好朋友有一次忘了带书包,书本什么的就装在这位作者的书包里。从别的故事中也能看出来,两位真真是斤斤计较 (不含贬义)

的有脑袋瓜的小女孩,所以俩人走着走着就觉出来不对劲了,不公平,你背的时间比我短。不对,明明是你背的时间比我短。那是因为你的东西沉。那得比比才知道谁的东西沉。

两位就把书啊本啊笔啊,都拿出来,摊了一马路,比较谁的东西更沉。书是一样的,本是一样的,你的橡皮比我的大一块儿。最后,作者即将险胜,最后的最后,好朋友说,还是你东西沉啊,你比我多个书包!于是,作者输了。直到今年

(?),作者才想到,应该是她胜,因为事情的起因正是她朋友借用她的书包。

作者的回忆中,她们两个一直在持续这样的争吵。岁月变迁,才知道这样的争吵中,隐藏的不是矛盾,而恰恰是最真正的友谊。她们从来没有在争吵中把"你我"的区别计算进去。而后来的很多友谊,没有矛盾没有争吵,甚至持续几代人的友谊,都表现在共同的利益之下,或者说,共同的利益之下,谁知道那是友谊还是什么。

类似的,很多时候,温和恭谦不过是中国君子脸上的一层皮,其下是什么样的骨头肉,你哪里能知道。相比之下,横眉冷对的,虽然更直接,也更容易了解。

我和李记者到现在保持了十年的友谊,聚在一起的时候,主要以感叹人生、吹牛、欣赏各自拍的照片和经历为主。李记者和我都是做计算机项目的,但是计算机项目从来都不是谈话主题。有时我们也合作项目,与有的同学所想的不同,我们第一步不是先把项目做起来

(做大~~) ,然后再分蛋糕,而是先讨论如果有了蛋糕,如何分配。这也许是我们一直也没有做出来牛项目的原因,但是,我更注重的是,我们没有因为项目损害我们的感情。如果分配方案没有得到双方共识,我们大不了不做这个项目,但是如果项目做出来了,而我们对分配有异议,那就糟了。

小牛同学曾经评论过,你们咋这么没有人情味呢。我们只是用这样的方式保护我们的友情。

前几天回通化,于同学说吕同学在北京创业,几个好朋友很快就把公司整得有头有脸,挣了第一笔大钱,然后大家出现了分歧。有的人说,应该把钱再投入,有的人说,把我那份钱给我,我就想要小富即安。于同学认为,大家应该齐心合力……我的观点,别人的钱如果是别人的,别人就有权利决定怎么花。跟我们一毛钱的关系也没有。

如果你不尊重别人的选择,即使用强力

(或说服,或温情说服)达到了"你的"目的,你也失去了这个朋友。为什么一般地,大家在思想汇报的时候不说真话呢?因为组织会用你的话来评价你。当你说出口就被评价,你就只好闭嘴,或者说假话。如果你评论你的朋友的人生观价值观,你的朋友就不是你的朋友了。

Z同学曾经提到某同学打游戏 (还是打扑克?)的时候太

激歪了,整得跟真的似的。其实,这说明他还在你面前坦露真正的自我。一个男人,要么不喜欢这个游戏,要么,一定非常认真地从事它。如果输了他表现不在意,要么他不在意这个游戏,要么,他在刻意表现成熟。或者真正的成熟为大叔了,这点玩意都不在眼里了,只是在陪小孩玩而已。如果他把你当成小孩,一方面,呵护,一方面,他并不信任你,这两方面一定是统一地同时存在。

如果他真地注重你,也真地注重这个游戏,如果输了,他怎么会不痛哭流涕。

这就像有的同学,当他们申请国家创新实验或者学生科研立项的时候,一方声称我是真的喜欢科研和项目,另一方面却对哪个项目申请成功能得到多少利益那么清楚和津津乐道,对哪个项目需要什么技术却一头雾水并说这个是以后可以慢慢学到的。

这就像有的同学,一方面说爱你,一方面对你以后的义务规定详细可以写个手册。

真相掩盖在事实之下,需要用心去分析。有的人,跟你吵得面红耳赤,就差拳脚相加,却忘记书包是自己的,根本可以不借给你。有的人,明明说是全因为喜欢,却把精力投入到了利益的计算当中。到底是喜欢,还是喜欢因此得到的利益?

最近看爱情片,一个角色问,你喜欢我什么,另一个角色答,我就喜欢你某A特性。我心里替前一个角色问,那你以后又遇到了更A的人呢。

我回答过这样的问题,为什么做项目。我就喜欢做项目时创造出某种东西来的这种感觉,其他的,都是副产品。得到的利益、完成教学和科研任务、避免下岗,都是副产品。如果有一天,我在做项目时不能享受创造出某种东西的快乐,我就会放弃,我不会因为指导学生带来的快乐或者他们都有更好的前途了而留下来。

不按自己的意愿而从事的,那只是生存;告诉自己,别人的意愿就是自己的意愿,那是自我欺骗。所以,Z同学,如果有一个某同学打游戏或打扑克输了,和蔼地笑笑,他已经不可信任了。

编辑问过我,为什么写故事的时候只写计算机相关的。一方面,我只会这个,当时就是这样回答的。另一方面,能力所限,别的写不来。还有一个更重要的方面,如果你喜欢的就是这样的故事,为什么要写别的?如果你为了让更多的人看到你的故事,或者通俗而一般会否认的,为了出名,你为什么不什么流行就写什么呢。科幻以外,流行的东西多得是。

《知心爱人》的男歌手对问什么要创造这样一首深情的歌的回答,给我留下了深刻的负面印象。他说:当时估计市场会需要这样的夫妻档的歌。我对这段话给差评负分的原因,是因为令人真地感动的歌曲原来是设计来让我感动的,即我被设计了。

很多人,他们正是这样想的,只是没有傻到说出来。他们换了一个方式,比如163还是263,声称为了帮助你更容易输入以邮箱注册的账号,在你输入用户名的时候@后面自动补全域名,但是只补全他们自己的域名?人人网声称为了你的安全而索要手机号。从这一点诚实来看,google

reader稍好一些,他说,就是这个业务不挣钱。

即使2XXX年了,我们中国人似乎还不习惯直截了当地表达。我们更希望对方说,

"你是个好青年,只是……"。其实这有什么区别。而且,她都已经不允许你喜欢她了,你为什么还要在乎她的评价。

我小的时候看到的:每句话都有两层意思,它表面的意思,还有它真正的意思。本文开头的两个小女孩,她们的表现并非她们的本意,那是因为还不具备了解自己内心的能力;而另外的很多人,他们学会了并刻意掩盖本意。

--------------------

博客会手工同步到以下地址:

[http://giftdotyoung.blogspot.com]

[http://blog.csdn.net/younggift]

生活得有多么艰难

生活得有多么艰难

前两天回通化,见了初中刘同学和高中于同学,听他们讲了一些同学目前的状况。我妈还给我讲了一些亲戚的现状。总得来看,我的初中同学过得普遍比较惨淡,高中同学回到或留在通化的都是一方牛人,小康生活,离开通化的都老牛了。留在通化的,牛到我大致提提他们是干啥的,就非常容易人肉出来;在外的牛到,遍布世界各大城市和北大广。亲戚们的状态普遍不咋地,过得比较咋地的亲戚,早在我上小学以前就基本断联系了。

想同学们过得好的好坏的坏,从通化到长春以后,抑郁了几天。然后大学郭同学从四川来长,大家一聚再聚,他们喝酒我看着。大学同学普遍过得不错,像小建早在好几年前已经达到很多人心中的人生巅峰,不过,他本人的巅峰可能还远没有达到。当时学习最好的男生和女生两两结合,现在都过得非常不错。学习其次好的那些散在各研究所和高校,还有的在中学或者教育局成为骨干或领导了。当时的牛人还是牛人,当时像我这样排在最后的还是排在最后。

我突然就明白了思考了十来年的一个问题,为什么成年人要求孩子们好好学习,而自己成天就打麻将,甚至也不是为了应酬,就只是享受。因为在学业告一段落以后,社会阶级就定了型(至少大家这样以为),无论如何努力,再无希望。现在,甚至有不少人认为,一旦出生,社会阶级就已经定型了。这样的时代,以前也有过,倒是不稀奇,比如魏晋南北朝。不过,咱们还是别在这里讨论了,有些人甚至相信中国不存在阶级呢。说起来伤心。

今天下午跟李同学和小牛同学聊天。李同学特意穿了我们结题电化学工作站时的半袖,我们的左袖口上有个循环伏安的图,好像是铂电极扫描铁氰化钾的,我记得。但是当时我神情恍忽,竟然没有注意到李同学用心良苦,虽然我也恰巧穿了这件。不过后来晚上我和李同学在西兰花雕塑喷泉下面遇到了,合了影,算是补了遗憾。下午,我们谈到各种未来和计划。小牛同学说,有些人在很多年里逐渐就忘掉了自己的理想。一叹。

希望我们都能记得自己最初的理想。希望李同学也能够完美实施他的计划。

另一个体会。到长春,开网页,看看新闻和douban,觉得通化的现实与小资们的生活体系,是完全隔离的两个世界。先前在通化的时候,电视的新闻正重复着大约一周前网上的消息,我还以为自己穿越了呢。后来在长春的时候,看到douban上小资们依然故我,又继续推出各种新鲜消息,保持着对他们自己的情怀,也顺便对广大受苦受难的劳苦大众充满了同情的态度。这么伟大的同情,却在这么久的时间里没看到产生什么值得一提的效果,也是奇迹。

我又回到了小资们中间,喝咖啡写代码,提心吊胆怕下岗。生活真是艰难。

--------------------

博客会手工同步到以下地址:

[http://giftdotyoung.blogspot.com]

[http://blog.csdn.net/younggift]

与建一的讨论

建一:

>老师,我因为工作原因又出差来集中开发了…

你总是集中开发,可真得注意身体了。岁数一大,就不如年轻的时候扛造了。

你对于技术的思考和总结,已经越来越有高度,令我欣慰。有你这样的讨论,即
使我在小山村里也不孤独。

>简述的是在2006年到2013年我接触的web开发技术路线变化。

你提到的几种技术,我的体会是这样的:

1.J2EE SSH 与 orm/sessionbean 它们都不矛盾,算是不同的方面吧。它们不能
比较,互相作为补充吧。

2.在你所讨论的角度上,web service 与 SSH 一样,都是一种框架 (或架构) 手
段,它们在软件工程上的原则是相通的,比如倾向于你提到的封装、抽象、约
定,只不过是在这些方面的实现机制和强调的程度不同。就像XP和RUP其实并无本
质不同。

3.no sql 和 mongodb又是与orm/sessionbean类似的技术方向,数据留存。

我的感想:1.框架(和数据留存)都有不少技术,它们无所谓好坏,而是有各自不
同的优缺点 (包括学习曲线的陡峭程度、现有人员的技术程度也算特点,要作为
采用时的考量);工程师的责任,是针对具体项目,根据这些特点优缺点选择合适
合的技术。 2.如果不建立更全局和高度的观点来看待这些技术,是危险的。

4. 框架一直在试图解决一个问题,就是如何"约束"使用者的行为,而不是增加他
们的自由,以保证他们能够以更"正确"的行为使用框架所规范的底层机制,比如
语言。在一定程度上,框架的创造者们成功了。但是同时,使用框架真正的方
法,是理解和构造它们,而不是单纯被动地被约束。理解和构造框架,需要更深
层次的理论知识,更多地探索这些成型的框架的构造原则和动机。

5. nosql一类的数据留存技术,一直在试图解决两个问题。一是提高性能,降低
负载,采用的技术手段包括分布式 (集群、云,全算分布吧) ,二是与现有技术
的结合 (动机是方便程序员使用),比如与OO的结合,比如脱离sql。性能和负载
方面,似乎卓有成效,而与现有技术结合的方向,一部分技术似乎有这样的目
的,即能让傻瓜程序员 (我指的不是那种KISS的S,而是受到培训很少,不希望投
入时间和精力、智力)也编程序。后面这个目的,早在COBOL时代就已经有了,无
论他们取得了多少成果,我仍深感怀疑。我怀疑的原因是,创造性的工作是所有
智力活动之所以有价值的特性,而创造性工作需要严格精确地描述--没有适当的
工具和训练,我不相信正常人类可以使用正常人类语言精确描述任何意图。计算
机又不是神仙,焉能知道你想得是啥,甚至很多人自己都不明确自己想的是啥。
如果自己也不清楚,就变成了希望计算机代为决定,这涉及人是否要放弃自由意
志了。

> 曾经以为走在软件开发的路上,必须不断地在自己身上增加各种砝码,针对于具
> 体技术的砝码。然后你的重量就大了,力量就强了。结果一边走一边发现有些东
> 西慢慢变成负担,又开始甩脱直到轻松,留下的是对于负重的承受力和感知。"在
> 任何一组东西中,最重要的只占其中一小部分,约20%,其余80%的尽管是多数,
> 却是次要的。"

确实,增加的东西,一部分只是暂时的奇技淫巧、眩目的名词,短期可能效果不
错;应该减少的东西,也正是这些。应该留下来的,是基础理论。而所有的新知
识,都应该建立在自己的现有知识结构之上,是现有知识结构的一个演绎结果。

如果突然来了些新名词,却无法用我们现有的知识解释,要么,那就是我们要变
更知识结构了,要么就是这些新名词是骗人的。变更知识结构的,我遇到过的情
况是读《计算机程序的构造和解释》, (1) lamda运算与图灵机等价,所以,这
是一套不同的思考方法; (2)这很接近于Johan Linus以前对我说的,物理或电子
出身的人难以理解"模型",可能正是因为物理和电子工程师构造出的不是数据而
是物理模型,不是对问题的认识,然后建模,而是太早套用到了似乎唯一的既定
的解决方案上。这种什么跟什么是"同构"的,在《GEB》这本大书里有深刻讨论。
确认或猜想某个问题与某个模型同构,非常重要,因为我们可以选择一个更容易
解和对条件依赖更不那么苛刻的模型。

新名词骗人的,那就太多了,大多数新名词我都先归到这一类,如果不是一眼就
能看出来好的,等它著名了再说吧。

> 集大成的东西内部未必单一。平台级的产品,就应当能兼容并包多种形式、各尽
> 其能的模块或子系统,朴素的脚本是利器。这部分是联想到你设计的仪器软件平
> 台,以前没觉得是因为眼界小。

你这一段总结,让我想起了linux内核。这两天我配置linux内核,哗哗失败,一
次又一次。解决不了的困难,如同跟高手过招,屡屡被缠住,不要说攻击,连自
守都困难得很。不过,与高手同行,毕竟收获也很大--如果能幸存下来。linux内
核的结构,我看到的只是make的配置,正有点你说的这个意思。

我的另一个体会,针对你提到的"眼界"。这几天哪位同学来着,重提到一个问
题,研究了一六十三招以后,发现别人早就实现了。前几年Johan Lilius来长春
的时候,我请教他关于整个体系性能的问题,他给我篇论文,198X的。我看了以
后拍大腿,正是我想要的。另一个问题,我当时请教的,他从理认上否定了解决
的可能性。对198X年的论文,我当时提到,这多么令人沮丧,我们头疼很久的问
题,不仅有人解决了,而且解决了三十多年,而且,我们还不知道它已经解决了。
他说,你在博士阶段 (或者做科学研究) 所受到的训练,正是为了提高这种能力。

我们经常看到我们过去的不足,甚至憎恨过去的技术选择,那正是成长的结果。
当然同时,也说明我们那个时候多么幼稚。幼稚,我并不是指经验少,而是指理
论太差。我们一般所说的知识,要么来自基本理论的演绎,要么来自经验的归
纳,别无他途。也正因为别无他途,所以一切新名词都是唬人的。而靠从经验中
归纳,你得活多少年才能有结果啊。所以,基本理论的修养,和从基本理论中经
过漫长的过程推导出结论来的能力,都尤其重要。

本来这只是回复你一个人的邮件,写着写着,痛感我们为幼稚啊什么的所付出的
代价,想着很多别人也可能有同样的经历,或者会有同感。所以,我把回信发到
博客里了。

>以上。保重身体!

请在集中开发中保重,这样过不了多久,你身体就会不如我了。

重申,一切不利于人类繁衍的规章都是扯淡的。

请教:tiny210 linux,尝试s3c-udc与gadgetfs一起使用,失败

请教各位专家。
- 问题:tiny210 linux,尝试s3c-udc与gadgetfs一起使用,失败。
- 错误现象:
1.把usb.c(gadgetfs官方测试程序,我修改过)编译为可执行程序 usb。执行usb时,到向文
件描述符write后死机.
我对usb.c的修改,是为了使之识别 s3c-ucd。按s3c-hsudc.c注释,
   The S3C24XX USB 2.0 high-speed USB controller supports upto 9 endpoints.
   Each endpoint can be configured as either in or out endpoint. Endpoints
   can be configured for Bulk or Interrupt transfer mode.
我试着进行了几种配置,均导致死机。


2. 执行前usb运行前,执行了下述操作,控制台均无报错。
mkdir /dev/gadget
insmod gadgetfs.ko
mount -t gadgetfs none /dev/gadget
此时,
[root@FriendlyARM plg]# ls /dev/gadget
ls /dev/gadget
s3c-udc

3. dmesg的出错信息:
[  299.539226] gadgetfs: USB Gadget filesystem, version 24 Aug 2004
[  353.895836] s3c-udc: bind to driver nop --> error -120
其中第二行是mount操作后出现的。
我猜测,usb.c死机的原因在这里,即gadgetfs加载失败。
请教原因何在?

- 操作系统:
[root@FriendlyARM plg]# uname -a
uname -a
Linux FriendlyARM 3.0.8-FriendlyARM #9 PREEMPT Tue May 7 22:56:46 CST 2013 armv7l GNU/Linux

- 内核配置:
  │ │      --- USB Gadget Support                                                       │ │  
  │ │      [*]   Debugging messages (DEVELOPMENT)                                       │ │  
  │ │      [*]   Debugging information files (DEVELOPMENT)                              │ │  
  │ │      (500) Maximum VBUS Power usage (2-500 mA)                                    │ │  
  │ │            USB Peripheral Controller (S3C HS USB OTG Device)  --->                │ │  
  │ │            *** NOTE: S3C OTG device role enables the controller driver below ***  │ │  
  │ │      <*>   S3C high speed(2.0, dual-speed) USB OTG device (NEW)                   │ │  
  │ │              S3C OTGD transfer mode (enabled DMA MODE)  --->                      │ │  
  │ │      <M>   USB Gadget Drivers                                                     │ │  
  │ │      <M>     Gadget Zero (DEVELOPMENT)                                            │ │  
  │ │      < >     Audio Gadget (EXPERIMENTAL)                                          │ │  
  │ │      < >     Ethernet Gadget (with CDC Ethernet support)                          │ │  
  │ │      < >     Network Control Model (NCM) support                                  │ │  
  │ │      <M>     Gadget Filesystem (EXPERIMENTAL)                                     │ │  
  │ │      < >     Function Filesystem (EXPERIMENTAL)                                   │ │  
  │ │      < >     File-backed Storage Gadget                                           │ │  
  │ │      <M>     Mass Storage Gadget                                                  │ │  
  │ │      <M>     Serial Gadget (with CDC ACM and CDC OBEX support)                    │ │  
  │ │      < >     MIDI Gadget (EXPERIMENTAL)                                           │ │  
  │ │      < >     Printer Gadget                                                       │ │  
  │ │      < >     CDC Composite Device (Ethernet and ACM)                              │ │  
  │ │      < >     Nokia composite gadget                                               │ │  
  │ │      < >     Multifunction Composite Gadget (EXPERIMENTAL)                        │ │  
  │ │      < >     HID Gadget                                                           │ │  
  │ │      < >     EHCI Debug Device Gadget                                             │ │  
  │ │      < >     USB Webcam Gadget                                                    │ │ 

- 其他信息:
1. g_serial.ko与s3c-udc配合,可以与PC的HOST端通信;
我的理解,这表明 tiny210的ucd 确实是 s3c-udc.

2. gadgetfs.ko载入内核(with dummy_hcd + usb.c),dmesg无错误信息。
我的理解,这表明gadgetfs.ko与dummy_hcd可以配合工作。

# lsusb -v
lsusb -v

Bus 3 Device 7 ID 0525a4a4 Netchip Technology, Inc. Linux-USB user-mode bulk source/sink
Device Descriptor
   bLength                18
   bDescriptorType         1
   bcdUSB               2.00
   bDeviceClass          255 Vendor Specific Class
   bDeviceSubClass         0 
   bDeviceProtocol         0 
   bMaxPacketSize0        64
   idVendor           0x0525 Netchip Technology, Inc.
   idProduct          0xa4a4 Linux-USB user-mode bulk source/sink
   bcdDevice            1.00
   iManufacturer           1 Licensed to Code, LLC
   iProduct                2 My Source/Sink Product
   iSerial                 3 1.3
   bNumConfigurations      1
   Configuration Descriptor
     bLength                 9
     bDescriptorType         2
     wTotalLength           39
     bNumInterfaces          1
     bConfigurationValue     3
     iConfiguration          4 The Configuration
     bmAttributes         0xc0
       Self Powered
     MaxPower                2mA
     Interface Descriptor
       bLength                 9
       bDescriptorType         4
       bInterfaceNumber        0
       bAlternateSetting       0
       bNumEndpoints           3
       bInterfaceClass       255 Vendor Specific Class
       bInterfaceSubClass      0 
       bInterfaceProtocol      0 
       iInterface              5 Source/Sink
       Endpoint Descriptor
         bLength                 7
         bDescriptorType         5
         bEndpointAddress     0x87  EP 7 IN
         bmAttributes            2
           Transfer Type            Bulk
           Synch Type               None
           Usage Type               Data
         wMaxPacketSize     0x0200  1x 512 bytes
         bInterval               0
       Endpoint Descriptor
         bLength                 7
         bDescriptorType         5
         bEndpointAddress     0x03  EP 3 OUT
         bmAttributes            2
           Transfer Type            Bulk
           Synch Type               None
           Usage Type               Data
         wMaxPacketSize     0x0200  1x 512 bytes
         bInterval               1
       Endpoint Descriptor
         bLength                 7
         bDescriptorType         5
         bEndpointAddress     0x8b  EP 11 IN
         bmAttributes            3
           Transfer Type            Interrupt
           Synch Type               None
           Usage Type               Data
         wMaxPacketSize     0x0008  1x 8 bytes
         bInterval               6
Device Qualifier (for other device speed)
   bLength                10
   bDescriptorType         6
   bcdUSB               2.00
   bDeviceClass          255 Vendor Specific Class
   bDeviceSubClass         0 
   bDeviceProtocol         0 
   bMaxPacketSize0        64
   bNumConfigurations      1
Device Status     0x0000
   (Bus Powered)

Bus 3 Device 1 ID 1d6b0002 Linux Foundation 2.0 root hub
Device Descriptor
   bLength                18
   bDescriptorType         1
   bcdUSB               2.00
   bDeviceClass            9 Hub
   bDeviceSubClass         0 Unused
   bDeviceProtocol         1 Single TT
   bMaxPacketSize0        64
   idVendor           0x1d6b Linux Foundation
   idProduct          0x0002 2.0 root hub
   bcdDevice            3.00
   iManufacturer           3 Linux 3.0.8-FriendlyARM dummy_hcd
   iProduct                2 Dummy host controller
   iSerial                 1 dummy_hcd
   bNumConfigurations      1
   Configuration Descriptor
     bLength                 9
     bDescriptorType         2
     wTotalLength           25
     bNumInterfaces          1
     bConfigurationValue     1
     iConfiguration          0 
     bmAttributes         0xe0
       Self Powered
       Remote Wakeup
     MaxPower                0mA
     Interface Descriptor
       bLength                 9
       bDescriptorType         4
       bInterfaceNumber        0
       bAlternateSetting       0
       bNumEndpoints           1
       bInterfaceClass         9 Hub
       bInterfaceSubClass      0 Unused
       bInterfaceProtocol      0 Full speed (or root) hub
       iInterface              0 
       Endpoint Descriptor
         bLength                 7
         bDescriptorType         5
         bEndpointAddress     0x81  EP 1 IN
         bmAttributes            3
           Transfer Type            Interrupt
           Synch Type               None
           Usage Type               Data
         wMaxPacketSize     0x0004  1x 4 bytes
         bInterval              12
Hub Descriptor
   bLength               9
   bDescriptorType      41
   nNbrPorts             1
   wHubCharacteristic 0x0001
     Per-port power switching
     Ganged overcurrent protection
     TT think time 8 FS bits
   bPwrOn2PwrGood        0 * 2 milli seconds
   bHubContrCurrent      0 milli Ampere
   DeviceRemovable    0xff
   PortPwrCtrlMask    0xff
  Hub Port Status
    Port 1 0000.0503 highspeed power enable connect
Device Status     0x0003
   Self Powered
   Remote Wakeup Enabled

Bus 2 Device 1 ID 1d6b0001 Linux Foundation 1.1 root hub
Device Descriptor
   bLength                18
   bDescriptorType         1
   bcdUSB               1.10
   bDeviceClass            9 Hub
   bDeviceSubClass         0 Unused
   bDeviceProtocol         0 Full speed (or root) hub
   bMaxPacketSize0        64
   idVendor           0x1d6b Linux Foundation
   idProduct          0x0001 1.1 root hub
   bcdDevice            3.00
   iManufacturer           3 Linux 3.0.8-FriendlyARM ohci_hcd
   iProduct                2 EXYNOS OHCI Host Controller
   iSerial                 1 s5p-ohci
   bNumConfigurations      1
   Configuration Descriptor
     bLength                 9
     bDescriptorType         2
     wTotalLength           25
     bNumInterfaces          1
     bConfigurationValue     1
     iConfiguration          0 
     bmAttributes         0xe0
       Self Powered
       Remote Wakeup
     MaxPower                0mA
     Interface Descriptor
       bLength                 9
       bDescriptorType         4
       bInterfaceNumber        0
       bAlternateSetting       0
       bNumEndpoints           1
       bInterfaceClass         9 Hub
       bInterfaceSubClass      0 Unused
       bInterfaceProtocol      0 Full speed (or root) hub
       iInterface              0 
       Endpoint Descriptor
         bLength                 7
         bDescriptorType         5
         bEndpointAddress     0x81  EP 1 IN
         bmAttributes            3
           Transfer Type            Interrupt
           Synch Type               None
           Usage Type               Data
         wMaxPacketSize     0x0002  1x 2 bytes
         bInterval             255
Hub Descriptor
   bLength               9
   bDescriptorType      41
   nNbrPorts             1
   wHubCharacteristic 0x0002
     No power switching (usb 1.0)
     Ganged overcurrent protection
   bPwrOn2PwrGood        2 * 2 milli seconds
   bHubContrCurrent      0 milli Ampere
   DeviceRemovable    0x00
   PortPwrCtrlMask    0xff
  Hub Port Status
    Port 1 0000.0100 power
Device Status     0x0003
   Self Powered
   Remote Wakeup Enabled

Bus 1 Device 1 ID 1d6b0002 Linux Foundation 2.0 root hub
Device Descriptor
   bLength                18
   bDescriptorType         1
   bcdUSB               2.00
   bDeviceClass            9 Hub
   bDeviceSubClass         0 Unused
   bDeviceProtocol         0 Full speed (or root) hub
   bMaxPacketSize0        64
   idVendor           0x1d6b Linux Foundation
   idProduct          0x0002 2.0 root hub
   bcdDevice            3.00
   iManufacturer           3 Linux 3.0.8-FriendlyARM ehci_hcd
   iProduct                2 S5P EHCI Host Controller
   iSerial                 1 s5p-ehci
   bNumConfigurations      1
   Configuration Descriptor
     bLength                 9
     bDescriptorType         2
     wTotalLength           25
     bNumInterfaces          1
     bConfigurationValue     1
     iConfiguration          0 
     bmAttributes         0xe0
       Self Powered
       Remote Wakeup
     MaxPower                0mA
     Interface Descriptor
       bLength                 9
       bDescriptorType         4
       bInterfaceNumber        0
       bAlternateSetting       0
       bNumEndpoints           1
       bInterfaceClass         9 Hub
       bInterfaceSubClass      0 Unused
       bInterfaceProtocol      0 Full speed (or root) hub
       iInterface              0 
       Endpoint Descriptor
         bLength                 7
         bDescriptorType         5
         bEndpointAddress     0x81  EP 1 IN
         bmAttributes            3
           Transfer Type            Interrupt
           Synch Type               None
           Usage Type               Data
         wMaxPacketSize     0x0004  1x 4 bytes
         bInterval              12
Hub Descriptor
   bLength               9
   bDescriptorType      41
   nNbrPorts             1
   wHubCharacteristic 0x0009
     Per-port power switching
     Per-port overcurrent protection
   bPwrOn2PwrGood       10 * 2 milli seconds
   bHubContrCurrent      0 milli Ampere
   DeviceRemovable    0x00
   PortPwrCtrlMask    0xff
  Hub Port Status
    Port 1 0000.0100 power
Device Status     0x0003
   Self Powered
   Remote Wakeup Enabled
[root@FriendlyARM plg]# 

3. g_zero.ko载入内核,dmesg无错误信息,如下:
[  495.979552] zero gadget: adding config #3 'source/sink'/bf1fad28
[  495.979569] zero gadget: adding 'source/sink'/d9c30080 to config 'source/sink'/bf1fad28
[  495.979586] zero gadget: dual speed source/sink: IN/ep2-bulk, OUT/ep1-bulk
[  495.979596] zero gadget: cfg 3/bf1fad28 speeds: high full
[  495.979605] zero gadget:   interface 0 = source/sink/d9c30080
[  495.979615] zero gadget: adding config #2 'loopback'/bf1fada8
[  495.979625] zero gadget: adding 'loopback'/d9c30880 to config 'loopback'/bf1fada8
[  495.979637] zero gadget: dual speed loopback: IN/ep2-bulk, OUT/ep1-bulk
[  495.979646] zero gadget: cfg 2/bf1fada8 speeds: high full
[  495.979655] zero gadget:   interface 0 = loopback/d9c30880
[  495.979664] zero gadget: Gadget Zero, version: Cinco de Mayo 2008
[  495.979724] zero gadget: zero ready
[  495.998990] Registered gadget driver 'zero'
4. usb.c我修改的那一段,某个版本如下:

/* s3c-udc, high speed. by Young */

} else if 
                (stat (DEVNAME = "s3c-udc", &statb) == 0) {
HIGHSPEED = 1;
device_desc.bcdDevice = __constant_cpu_to_le16 (0x0100);
                fs_source_desc.bEndpointAddress
                    = hs_source_desc.bEndpointAddress
                    = USB_DIR_IN | 2;
EP_IN_NAME = "ep2-bulk";
                fs_sink_desc.bEndpointAddress
                    = hs_sink_desc.bEndpointAddress
                    =USB_DIR_OUT | 1;
EP_OUT_NAME = "ep1-bulk";


source_sink_intf.bNumEndpoints = 3;
                fs_status_desc.bEndpointAddress
                    = hs_status_desc.bEndpointAddress
                    = USB_DIR_IN | 3;
EP_STATUS_NAME = "ep3-int";
}

少年派 vs. 哈尔罗杰

少年派 vs. 哈尔罗杰
今天,看完了哈尔罗杰历险记,十四册。这是很多八零九零后小朋友小时候的读物,不少人盛赞过,陪伴过他们的童年。
哈尔和罗杰是两兄弟,大的十九岁,小的十三四岁。都身强力壮,在历险记里的主要职业是替他们的爸抓各种动物--活捉,然后卖给动物园。这些动物包括,虎、狮子、象、各种灵长类、爬行类、鲨鱼、鲸。凡是能想起来的凶猛的,全抓了。我一度非常奇怪,这些看哈尔罗杰长大的八零九零后们,怎么就会出了那么多环境保护的,比如不用方便筷子,不吃狗肉,不穿动物皮毛的,没有买卖就没有杀害的。看了大半历险记的时候,我开始逐渐明白了。
原因之一是,八零九零后们看哈尔罗杰的可能不算太多。
原因之二是,时代不同了。前两天我听高晓松的青春无悔,月亮,白衣飘飘的年代,什么的,听得我心旷神怡的。然后我就跑到DOUBAN上去搜,看看别人都啥看法。赫然看到一贴评论,原文忘记了,大体意思是 "那个直男横行的时代"。高的歌里也充满了各种文艺的意像,当然也噫噫呀呀了。不过,按二猫妈的说法,歌曲里主要是积极向上和励志的。白衣,充满了向往和留恋,月亮,大气滂薄,风雨欲来。这两首歌,据说都是纪念诗人海子的。诗人海子并非战士,所以他 (不知道为什么)自杀了。不过,那个年代的人选择的是决绝的抗争,死也好,怎么也好。现在的人们,不少会选择哭喊,没人听的话,就哭喊为什么没有人听。
哭喊这种事,少年派也干过。少年派,就是李安导演的那个印度少年。不管是老虎还是lie狗要咬他,还是天上下雨海里浪大,他都叫喊,为什么啊,为什么,或者在猩猩一巴掌把lie狗打趴下的时候大喊,好哎,加油啊。
我看片子的时候,一直在给他出主意,"应该往狗嘴里捅,别来回扫,那样没劲","傻啊,那是老虎,跳啊"。就跟少年派一直在跟上帝商量讨论一样,他也不理我。不过,我在这喊是秉承"大喊大叫是看电影的一部分"这样一个低俗原则,少年派一个劲地想跟上帝对话,是遵循哪条精神病法则呢?果然,上帝一次也没有理过他。大暴雨以后出了太阳,少年派顶礼膜拜那次,并非上帝答理他了,他自作多情而已。他应该学学中国古文,"天地不仁 以万物为刍狗"。
如果光看李安,会以为西方普遍是这种调调,打算靠臣服跟上帝结盟缔约的呢。看了哈尔罗杰以后,我们会了解到,李安只是西方一个流派而已。还存在像哈尔罗杰这样,活捉动物,打算开发亚马逊森林的人们。想想 lengends of the fall,就会知道,还有那种跟上帝绝不合解,最后上帝妥协,或者干脆战死的。此外,李安在西方人眼中,十有八九是个东方人。而此"东方",值得注意,在西方语境中,一般并不指中国及东亚,而是指印度,有时候还包括土耳基伊朗一带。特意提到这点,是希望小资们对西方人讨论李安时提到的"东方"二字不要太自恋,Raj说,这是一部分非常印度的片子。
每当我上面提到"李安"二字,总想说"安"。网上有故事说,说李安当年靠老婆为生,快放弃的时候,他老婆说"安,不要忘记你的理想。"我对他们夫妻俩的对话非常震惊。这段加了引话,在很多中语言里称为直接引语的话里,他老婆称他为"安"而不是"李安"。这是非常有毛病的称呼方法。欧美人才这样称呼别人的名字,不带姓吧,比如简,比如静云 (不是静香,静云全称柳生静云),比如安。中国人似乎只对名字三个字的,才能去掉名字称呼,比如贵福。
直接引语现在越来越多地被记者篡改其中的名词,民工大哥经常使用大学教授才知道的术语,没想到李安或者报道李安的家伙也这么不老实。这让我对他们及他们所报道的电影中引用的上帝说的话也产生了怀疑。上帝可能一声没吱,他们吱吱了半天。
哈尔罗杰在遭遇各种动物袭击时,都没有想到那是大自然或者动物们报复,在吃各种动物的肉时都没有过心存内疚。如果他们像少年派那么吱吱歪歪,估计死多少回了。少年派在海上漂流中的种种,让我想起另一个家伙,作为参照。有个叫 wild 的片子。那里面有个小子,想去阿拉斯加或者类似的地方,远离都市--是不是有小资的汗毛立起来了?他放弃学业攒了些钱买装备,然后去图书馆看了本书,自认为学会了腌肉,然后就去了荒野。爽了半个夏天以后,这家伙遇到个问题就是吃的不够了。好不容易打到一头牛,腌肉的时候因为动作不够快,苍蝇在上面产了卵,失败了,后来他就饿死了。
我看到腌肉的时候忍不住大喊,傻啊,不能把整头牛全腌了的话,腌一半也行啊,腌三五斤也行啊。看了书以后事先没有演练一下要花多少时间么,一头牛需要多少盐,算过没有,试过没有,有脑子没有。
这位兄弟一边赶苍蝇,一边哭 (我记得),一边跟上帝讨论命运为什么如何残忍(我记得)。
对少年派和上面这位兄弟,我想请他们对着哈尔罗杰照照镜子。想对他们说一句,你们对生活哪那么多态度,哪那么多感受哩?谁TM希望关心你们的感受啊。
前一阵子流行弃学辞职走遍哪哪的风,同学们纷纷打算见识一下真实的世界。一位青年旅舍的老板对此吐糟了一段。他说,不少小年轻的,胳膊腿都全乎的,对他说,老板,你看这是我打算走遍中国/世界的计划,已经走过哪哪和哪哪了。老板说,好。然后小年轻的说,住宿费能便宜点么。老板吐的就是这个槽,他说:你乐意走遍哪走遍哪,为什么我应该给你减住宿费呢,你的理想跟我有个P关系。你如果没钱,我可能给你提供打工的机会,挣了钱付住宿费。
直男时代以后,大家都比较乐意叫喊,期待这个世界 (除了他本人以外的其他部分)倾听和乐于倾听他的声音。这个世界如果很忙没工夫听的话,他们就希望上帝能够倾听一下。其实,上帝和这个世界一样都没空。换句话说,这个世界也有很多想发言的,你拿出一秒钟听一下了没?啥都没听,你就敢断言这个世界需要以你的方式拯救,你就去拦运狗的大货车,去当志愿者,去指责别人没有"爱心"啦。
罗素指责他那个时代的教育时提到,有些人认为教育应该有专门给贵族的,教育如何享受生活,另一些教育是专门给非贵族的,教育如何饲候贵族们。少年派与哈尔罗杰的分野,不在对生活有多小资上,而在于,有些人认为自己是不必创造价值,只要感受这个世界就可以了。他们应该去搬砖头扛麻袋,去和真正的自然和谐相处那么一段时间,然后再来讨论这个世界应该如何。
我想起了小资们怀念一个时代抨击另一个时代的一些文章,其中提到,那些了不起的知识分子以及他们的孩子被下放到农村,过的日子有多么惨淡,天理如何不公平。我每读到这些的时候就特别想问他们,那些出生在他们下凡的地方的农村孩子,天理有多么公平。如果说知识分子由于社会分工能够远离生产,那他们的孩子哪个细胞长得与众不同了?
小资们是不是真地信奉"人生而平等"?所以,每个人都应该像哈尔罗杰一样与自然斗争,争得人类包括其他人类生存的权利。所以,有时候我恶意地想,少年派们就应该扔到海里去,而且不必每次都那么幸运,还给他们机会YY与神相处过。
--------------------
博客会手工同步到以下地址:

为什么我们要学习基本理论

为什么我们要学习基本理论
想说这件事很久了,就是我们为什么学习基本理论。我的基本理论非常差劲,很多时候拖了后腿,这也是我对这一点感受很深的原因。
很多同学提到,计算机是个日新月异的学科,每年甚至每个月都在产生新的技术、新的名词。去年可能还很难解决的问题,今年就非常容易了。当年用记事本做个网页那个费劲,现在随便用dreamweaver之类的工具就能画一个来,成了最没技术含量的工作。同学们说,在这种情况下,为什么我们还要学习195X年发明的那些技术,甚至学习电子学这样194X年的技术。
1. 基础理论过时很慢
幸好,我没有听到有同学问,为什么我们还要学习3000年前的数学。一个学科赖以存在的基础,不像新科电视剧,它的出现和消失都是非常缓慢的。即使计算机这样的学科,那些影响到软件工程的理论,也大多在195X年就已经出现了。比如模块化、信息隐藏、编译原理、操作系统。更基本的算法,在电子计算机1946年以前早就出现了。比如世界上第一个计算机程序的作者生活于18XX年,是拜伦的女儿,就是那个诗人拜伦。有人可能会说,她怎么能为计算机这样不存在的东西写程序呢?她当然不是为"电子"计算机写程序,而是个数学家。这倒不是计算机科学为了显得自己有历史,而是她的工作确实是计算机的理论基础--而且对软件工程等有确实的影响。
为什么要学习基本理论,有很多理由。其中一个理由是前一段时间跟建一长聊之后想到的。建一要做一些不止是计算机的工程--事实上,这是一个普遍的现象,我们很少从事纯粹的计算机工作。他遇到的困难之一是,那个领域里充满了各种复杂的细节,其中很多是陌生的。我后来想到,这时基础理论在一定程度上能有帮助。一方面,很多工程类学科都依赖数学,这是共通的那一部分;另一方面,许多工程方法具有相似性,有时候,接近的学科,即使你没有接触,也能猜测到可能会有什么样的机制支持你。这两种情况下,更深刻地理解学科的基础就有意义了。
基础理论的学习,也能帮助学习"方法"。不少同学都提到,大学应该学习"方法",而不是"知识"。 (我略过了另一些观点,有人认为大学应该学习与人交往或者做人什么的。这种观点的价值观估且不讨论,我对它的困惑主要在于,还有一半没上大学的,他们就不需要与人交往或者做人了么?)而"方法"是很难传授的,只有在学习某个东西的过程中才能体悟。学习基础理论,动机之一就是通过它学习"方法"。
这些理论,以及学习这些理论过程中了解到的"方法",在学科的历史中长久地不过时。而你的一生,比学科要短很多,没有见到它们过时的可能。换句话说,那些十年以后就消失了的东西,并非基础理论。
2. 硬件进步的影响呢?
对基础理论的另一种质疑,由学科本身的成长导致。比如,莫尔法则指出,计算机硬件aoao地成长。所以,有人据此认为,程序的优化是没有必要的,又进一步推得,程序优化的技术是没有必要学习的。
我最近在精读CSAPP 就是这本[http://book.douban.com/subject/1896753/]。第四章读了两遍,还有很多没记住,正准备看第四章。这时看到网上有贴子提到,第四章的优化是毫无用处的。他的理由是,你优化了半年,程序效率可能才提高20%,而你这半年啥也不干,或者就只是玩,半年之后你的程序性能自然就达到指标了--因为硬件性能的提高。
这贴子听起来很有诱惑力。如果这个世界以这样的方式运作,那生活简单太美好了,美好到可能很多人都不想活了。你想,如果衣来伸手,饭来张口,啥也不用干,想要啥有啥,所有人都听你的...而根据康德的理论,人类之所以能感受到美,就是因为在过程中感受到自身的力量。
这贴子还有其他的问题,这种美好的生活是不会存在的。没有工作过,没有为别人创造过价值的人,可能难以理解这一点。你工作的意义不仅是实现某个效果(比如你那个程序,没有优化快20%的),而且在于在特定的时间完成这个工作。
我要对每一届进实验室做项目的研究生同学反复说,你的工作不仅是完全某个任务,而是必须在规定时间前完成。凡是在规定时间以后完成的,基本就没有意义了。这跟降落伞差不多,需要你的时候如果你不在,你就永远也不用在了。
为什么。
在万恶的旧社会,有一个时代,叫做486时代。那个时候的主流计算机型叫做486。那时候著名的奔腾还没有出生,像CS这样的游戏还没有它们能运行的硬件。那个时代看碟 (对,基本是碟,而不是AVI) 需要使用硬件解压卡。没有硬件的帮助,CPU的速度还不足以完成播放。那个时代著名的播放器叫做xing,能不用解压卡,但是它是英文的。后来。后来的事件太重要了,我另起一段。
后来,有一个重要的软件出现了,它不需要解压卡就能播放影碟,而且,它是中文的。它叫做金山影霸。是先前和后来著名的金山公司的重要产品。是的,后来有了586,有了奔腾,有了你现在用的这样的机器。这些机器的性能高到不仅不需要解压卡,连声卡和网卡的运算都免了,全在CPU里完成。但是,在金山影霸存在的那个时代,它们全、都、不、存、在。
这就是金山影霸存在的价值,也是你的工作的意义。我在课堂提到的一个比喻这样说,一个将军有多么牛,靠什么度量?如果敌人很牛,天气很差,我方装备非常缺乏,地理环境也不熟悉,而且身陷死地,自己的军队士气低落,全是老农军事素养低下。如果在这样的情况下,你带兵打了胜仗,你就是很牛的将军。如果反过来,敌人全很完蛋,天时地利都利于我方,你的士兵个个特种兵,你也打胜了。那打胜了有什么好说的,应该的啊。
你存在的意义就在于,你能够克服各种困难,完成人所不能。不仅做出来,而且在那个时候就要实现,它们都是你的工作的意义。如果要等半年硬件进步,你的老板为什么要付给你钱?
不仅硬件进步,厂商们,比如MS或GOOGLE还会封装底层的各种机制,让你调用它们的API。它们越封越多,越封越严。一方面,没有对底层的深刻理解,用它们的API做简单的程序非常容易,做难的程序比以前更难;另一方面,如果三两行就能写一个程序了,还是那个问题,你的老板为什么要付你钱。所以,你必须在它们还没封完以前把程序做出来。等它们封完了,你的工作就不值钱了。
3. 有人质疑,那他的聪明呢
这也是跟同学们讨论的一个话题。A同学如果学习了基础理论,才设计出某个程序,和另一种情况比,B同学完全没有学习基础理论,也设计出了某个程序,哪个更牛?
有些人认为,天赋异禀的B同学更牛,他更聪明,更有智慧,更富有创造力。你看,他没看理论,独立地就设计出了与某大公司相同的框架。
不过须知,做工程项目和科学研究,不是奥运会比赛,你聪明不聪明对公司和工资都没啥影响。你徒手或者用弓箭射杀鬼子也没有加分。完全自己设计,不遵循现成的基本理论,不参考 (或否定) 别人的设计,基本是小农经济时代的思维吧。证明你是本小镇最聪明的人又怎么样,你织的布就更好了,就比大机器生产的质量更高更便宜了么?
深入学习基础理论,能避免前人和别人早就做过的蠢事,也更容易重复牛人的成果。你没得到独创的机会,实在是得归疚于生得晚了,要创造也只能创造些别的了。无论你是否知道,是否把耳朵眼睛全睹起来,别人已经创造完了的,总归是创造完了。
有些人误认为古龙莫言之类的创造者,都全身心投入到女人和地方特色中去,两耳不闻窗外事。细读一下他们别的言论你就会知道,他们对于西方文学各种流派和文学基本理论的概念都熟悉得很呢。只是,写小说的时候,跟听故事的读者说不来这些东西就是了。你会跟你的客户说你很了解汇编语言么,有意义么。你应该展示汇编语言的威力。
4. 再说硬件
说到硬件,还有两点。一是,即使半年后硬件进步了,你的优化也还是有意义。如果你优化了20%,你仍然比同样的硬件下别人的东西快20%。就像在列车上奔跑,停步的那个人,还是会落后,不是落后于地面,而是落后于不停奔跑的那个。二是,算法的理论 (和实践) 告诉我们,算法与算法之间性能的差别,比硬件和硬件的性能差得如此之大,以致于一个差的算法,即使运行在银河机上,而好的算法运行在当年的日立小计算器甚至算盘上,好的算法仍然快得多。这个说起来话就长了。
又想起来前一段时间某段对话。某人说,这些东西的技术某公司都有前期研究,所以...言下之意这些工作是不是可以便宜一些。
不能。
有些工作就是体力活,就跟给你家刮大白似的。你会刮也白扯,我给你家装修的时候也不会便宜。不过,问题的另一方面是,如果你不会刮,或者我由于基础理论好,刮得格外好或者格外快,那铁定得加钱了。
5. 最后一段
关于基本理论,齐同学当年提到过一件事。他对考基本概念很反感。我对动手能力强的同学希望考理论的应用,而不考理论,非常理解。
那么为什么还要考察基本概念呢。尤其齐同学还提高,如果按自己的话答,老师就给扣分,老师就希望背下来。
事情是这样,按自己的话答,是不会扣分的。为什么齐同学有此误解呢?估计是他答的知识点不全。基本概念的考核在我做学生的时候,也非常头疼。现在想来,是我理解得不够深刻,所以答得不完整,以后应用的时候也受到负面影响。当然,我并不是说背也来就高超很多,大家都不咋地。
正确地做法是,深刻理解,理解到可以复述,就像背下来一样。你女朋友的电话号码记得那么清楚,为什么用来谋生 (也包括她的生?)的工具,怎么能随手就忘呢?
所以我等读完CSAPP,我还会再次重读第四章。直到能用手把图里的节点以及它们的连接画下来。那个时候,才是真正掌握的开始。
--------------------
博客会手工同步到以下地址:
----
杨贵福
东北师范大学 计算机科学与信息技术学院
--
Sincerely,
YANG Guifu
School of Computer Science and Information Technology
Northeast Normal University
Changchun, P.R.China

重剑无锋,大巧不工。

无不大工。