今天是第一次开始写技术博客, a dear dairy moment. 首先感谢这个论坛上那些已经进入计算机软件开发*王国的前辈高手们,正是他们在网络上不求回报地留下一篇篇精辟文章,如一盏盏指路明灯,真正为后来者照亮前进的方向;同时也想鼓励那些仍然身处迷雾苦苦挣扎的摸索者,只要坚定信心不动摇,终有一天能够登堂入室,苦尽甘来,从此终身享受嵌入式软件开发这个超级好玩的游戏。不必担心,不要沮丧,虽然编程被某些人拔高得跟相对论一样,其实只是一门技术或者手艺而已。“(技者),无它,但手熟耳”,加油!
It will be my pleasure if I can help.
为什么要学嵌入式
初次接触计算机与软件编程的人都憧憬那种“艺高人胆大,潇洒走天下”的境界,然而由于方法不当或目标不明确,很多人热情不能持久,碰壁若干次后就中途放弃,空留遗憾和感慨:"软件编程太难!" 或许电影中的天才黑客表现得很轻松,但实际他们只会敲空格和回车。世上本没有什么事可以一蹴而就。毕竟总体说码农还是高技术活,而嵌入式比一般软件更难,它牵涉到软件语言、硬件电路、操作系统、通讯协议等多方面,对知识面和实践经验都有要求。
有人说哪里需要学那么多, 只要会用IDE工具就行了。的确,windows上各种集成开发工具层出不穷,这些傻瓜式工具屏蔽了大量底层概念,表面上降低了“程序员”门槛,但同时导致越来越多的从业者基础不牢,处于空中楼阁状态,只能充当软件开发流水线中一个机械的装配工。傻瓜式工具整体固然有助于提高开发效率,减少重复劳动,但如果个人想为今后的提高开辟更广阔的空间,就必须打破这个牢笼,对整个系统底层原理做深入挖掘,否则只能永远跟在不断变化的工具和接口后面亦步亦趋,直到退休还是一个“只会调用API的程序员”,悲哀!
同样是编程,位于不同层次,价值也大不相同。古代刀枪耍得好的是大侠,火器时代枪法准的可以纵横天下,而现在能够研发和操纵导弹原子弹才是国宝。任何一种技能的价值都依赖于时代背景,随着社会发展而兴衰起伏,我们应该选择可见时间段内有生命力的技术,或者说要审时度势地在技术潮流的不断变化中找准有利位置。目前的软件行业,桌面和嵌入式系统开发者之间,对于基本原理的理解以及技巧方面的差距越来越大,很多人经过短期培训就可以在PC上用工具熟练地堆砌软件,但由于上手快,难度低,这类程序员势必逐渐平庸大众化,价值也会随之降低。物以稀为贵,只有门槛更高的嵌入式开发才是面向未来的选择,具有更长远的价值。
目前的嵌入式热潮为那些半路出家的程序员提供了难得的加固基础,回炉改造的转化捷径。嵌入式开发常把人逼到一种境地:原来可以回避,工具自动完成的过程如果不能手动完成,工作就没法继续。其实这是难得的突破机会,当碰到无法回避的问题时,离跨越它也就为时不远。将来嵌入式软件也会变得越来越复杂,逐步接近桌面系统,那时切入的机会就越来越少了,现在学习嵌入式正是好时机。
怎样学习
1. 理论结合实践
人们常说,读万卷书,行万里路。于是我们每个人的成长基本都是先读万卷书,再行万里路。传统教育被认为只需要纯粹读万卷书,行万里路是毕业后的事。然而几千年前子曾曰:学而“时”习之,不亦乐乎。学与习从来都不能分割,否则只会事倍功半。缺少实践的教育使很多学生嘴高手低,企业面试时听到最多的话或许就是“这个听说过,那个也知道,只是没实际做过”,这就是有学无习的教育方式导致的必然结果,教学远离实践原因很多,比如:
a)教育者自身知识多来自书本,没有实际工作经验,缺乏对外交流的能力和信心,而教学*也没有这种要求,照本宣科自然就成为常态。学校所学与社会所需严重脱节,使教和学很大程度上成了老师和学生的自娱自乐。
b)重视各种基金背景的纵向课题,轻视面向企业实际问题的横向课题。纵向课题容易发论文,评职称,而横向课题没有唬人的标题和元素,总结不出“理论成果”。基金课题只要提个想法,发几篇论文很容易交差,而与企业合作拿钱就要担责,压力大,风险高。换言之,“科学允许失败”,企业投了钱却不允许失败。最终名目繁多的基金变相发了补贴,大量资金投入带来了高产量的垃圾论文和所谓科研成果(永远不可能转化成生产力)。而听话的好学生们在参与这种空对空课题后得到了什么?大概只有捏造数据和拼凑论文的技巧吧。至于那些得自书本而缺乏实践淬火的知识,其价值基本为零。毕业时,毫无技能地被抛向社会,表面“一肚子墨水”实际两手空空,战战兢兢,还要由企业承担再教育的成本。
个人不能改变制度,但却可以审时度势修正自己。目前社会越来越看重人的技能而不是纸面知识,只有学以致用,才能赢在进入社会的起跑线上。我的一位“另类”导师曾说:大学里每门都考高分的学生既愚蠢又可怜,他们还把大学当高中读。分数保证毕业就足够,为多余分数付出时间和精力,不如参与实践、锤炼技能来得实惠。买个开发板,移植一些开源程序;做做专业相关的兼职;选择一些有企业应用背景的课题。只有这样“学&习”结合,知识与经验才能同步积累。当今时代,知识逐渐为大众所共享,经验才真正属于个人。
工作后相反,很多人沉浸在琐碎的工作细节中,满足于经验带来的成就感和职位稳定的安全感,每天努力工作,自豪于可以在公司占据稳定位置养家糊口。然而一段时间后,不少整天埋头苦干的人却逐渐被边缘化,为什么?
现代企业分工越来越细,如果安心做流水线上的装配工,一旦技术更新换代,就会立刻落伍,所以这种表面的勤奋工作其实是不思进取,不爱学习的懒惰表现,背后隐藏着危机。所谓能低头做事还要会抬头看路,只有跳出对狭隘经验的满足,不断跟踪新技术,补充新知识,提升自身层次,才能始终站立在潮头。换句话说,如果大家都有应付眼前工作的能力和经验,那么眼界开阔,掌握更多新知识又重新显得分外重要。
总之,任何阶段都要均衡安排学习与实践。两者的关系就象吃饭和消化,人必须通过实践消化已有知识,才能腾出空间,不可能把所有的饭一次吃完;反之没有外部营养的摄取,靠消化老本维持不了多久。学习实践不均衡,就象一条腿走路,再怎么努力,也走不远。
2.读好书
写本好书,传道他人,原本是一件很神圣的事情,可惜现在已经逐渐变味。很多人写书(姑且称之为写吧)主要为了炫耀自己,捞取或名或利的各种资本,而不是真心帮助他人。看看下面某教材的截取(做反面典型,不给出处了,不会被告侵权吧,很多书上都这样写,抄来抄去实际上也找不到源头)
1)定义:以应用为中心,以计算机技术为基础,软硬件可裁剪,适应应用系统对功能、可靠性、成本、体积、功耗严格要求的专用计算机系统。
2)嵌入式系统发展的4个阶段:无操作系统阶段、简单操作系统阶段、实时操作系统阶段、面向Internet阶段。
3)知识产权核(IP核):具有知识产权的、功能具体、接口规范、可在多个集成电路设计中重复使用的功能模块,是实现系统芯片(SOC)的基本构件。
4)IP核模块有行为、结构和物理3级不同程度的设计,对应描述功能行为的不同可以分为三类:软核、固核、硬核。
点评:动机决定行为方式,编教科书的人只求用词语法显得专业,读者是否能懂就不是他们关心的了,反正他们是皇帝的女儿不愁嫁。而且教辅书多数还需要和各种形式的考试相互依存,狼狈获利,于是这种固化、僵化,方便考试出题的表达方式就成了各种教育出版社图书的专用语法。可想而知,那些虔诚的求学者,看了这正统的滴水不漏的却如同天书般的描述是否能有所收获?或许他们会觉得自己太笨,没有学习计算机的天分吧。可怜以前我很长时间也这么认为。
前新东方的王强一次演讲中提到了汉语和英语体现的文化差异:中国人(汉语)解释一个概念,习惯把一堆形容词放在前面,直到这堆臭裹脚布拆完,最后概念的核心才千呼万唤始出来。这个习惯本质就是摆架子弄玄虚,很多写书的人乐此不疲:多堆砌难懂的学术名词可以体现专业性;形容词多了滴水不漏;生造出一堆概念,说不定碰上哪个流行,自己就成了鼻祖。只是结果却害惨了广大读者,想学点东西要拿出十倍的耐心。真正想学习知识的人还要披沙拣金,排除这一类以正统教材自居的教科书的影响,真是绝大的讽刺。反过来看看英文定义:
An embedded system is aspecial-purpose computer system designed to perform one or a few dedicated functions, often with real-time computing constraints.It is usuallyembedded as part of a complete device including hardware and mechanical parts. In contrast, a general-purpose computer, such as a personal computer, can do many different tasks depending on programming. Embedded systems control many of the common devices in use today
Since the embedded system is dedicated to specific tasks, design engineers can optimize it, reducing the size and cost of the product, or increasing the reliability and performance.
读完心情舒畅!embeded system中心是“一种特殊的计算机系统”。本人给个“下里巴人”版:“嵌入式系统就是嵌入到各种电子设备中特殊专用的计算机系统。比如日常用的空调,洗衣机,电视等家用电器,以及MP3,MP4等消费电子产品,它们内部都有一个或多个CPU芯片,运行专用软件完成某种特定功能,这些就属于嵌入式系统。与此对应的是通用计算机系统,比如个人的PC机”
这种表述不“学术”,也不够严谨,却更清楚易懂。可人们害怕降低身份,不愿脱去学术这层高贵的画皮。表达最学术最完善的未必最好,传道首要应通俗易懂,而不是追求面面俱到。任何论述都有例外,不必去钻牛角尖。世上本没有绝对真理,要抬杠总能找到反例。如果总捎带着那些百分之几的例外,叙述起来包袱实在太重,酸腐的正反面辩证法方式也实在太无趣。先掌握主要,才有可能理解次要,否则就是一团糨糊。把所有情况一一说明,反而容易让人学得累或看不懂,再严谨也等于什么都没说。(sorry,借宝地发通牢骚)。教与学就象发射台与收音机,初学者频段很小,超出这个频段,再大的功率也不能接收。
适合初学的书大概有三类:
a)高手针对某专题的浅显阐述,要自己上网搜集整理,书店找不到,比如CSDN的博客:)。真正高手在民间而不是官方演讲台。
b)IT公司内部培训资料,公司培训目的是为让入职菜鸟尽快干活,不是为出书赚钱,所以不会花心思拔高和注水。而且只有每天带着生存压力拼搏在一线多年的人,才能做出精炼而实用的总结。
c)英文经典,不得不承认,英文词语歧义较少,在科学表达方面有一定优势,很多概念似乎只能意会不好言传,换用英文就变得简明准确;而且相比起来,老外在技术上也更纯粹和虔诚。
d)优秀源代码的解析。这种书纯粹围绕代码解析,废话少,实践性强。
3. 掌握关键技术和节点,以点带面
社会快速发展,知识大爆炸时代已来临,“长期进化使人类发展到今天这个高度,但每个人在出生的那一刹那,实际上与其他动物站在几乎同样的起点”(李笑来《把时间当做朋友》),人的生命有限,知识扩展的脚步却从未停止。面对高垒的书籍和海量信息,活到老学到老是每个人必须的选择,即便如此,人力有时穷,必须有重点和取舍。人们对未知事物有本能地探究欲望,从小又被念叨“书到用时方恨少”,于是很多人抱着“不管有用没用,多看点书总不会错”的想法东看西瞧。但别忘了学习某种程度也是投资,需要投入时间和兴趣,如果每样都尝试以免“用时恨少”,只会无头苍蝇一样在犹豫观望和浅尝辄止中浪费时间,最终走马观花一无所获。然后只能厚着脸皮拼凑简历:“熟悉”C,“学过”JAVA,“看过”linux,“用过”VC/VB。看上去一大堆,可没底气写“精通”,能蒙谁呢。
乱花渐欲迷人眼,只有摆脱各种花哨名词和工具的诱惑,选择和掌握关键核心技术,才能以从容的心态稳坐钓鱼台,俯视其他衍生技术。最优搜索中,离目标越近,搜索效率就越高,学习也一样。对于技术细节,用到再学也不晚。那嵌入式的关键和核心是什么呢?最基础的C语言/操作系统!并非说C一定优于其他语言,但从学习角度只有C才能从下到上串联和诠释计算机体系结构、软硬件、数据结构和算法等。掌握C,进可攻退可守。“说穿了,用Java来取代传统程序入门课程中使用的语言,比如C或C++等──无异让整体教学水准后退了一大步。许多大学转向Java的理由只是因为学生毕业后好找工作,但讽刺的是,这些学校培养出了仅具备肤浅技能的程序设计人才,他们正失去与具备深度知识的人才竞争的能力。”(《不懂C语言?你该感到危机》),这种说法或许会引发一定争议,但我认为反映了很大一部分现实。
此外要特别关注不同技术模块的连接点,软件发展过程中一个突出特点是不断分化与融合,或者说不断增加的层次。一个著名的玩笑“所有软件问题都可以通过增加一个中间层来解决”,事实也基本如此。新旧技术或层次之间需要转换接口以相互配合,而这类转换节点中往往就包含着双方的一部分技术精华,很大程度影响程序员对系统的整体理解。比如:C和C++的连接需要掌握extern C以及背后的C/C++部分编译连接原理;C和汇编的连接需要掌握函数参数压栈出栈以及寄存器占用等体系结构相关调用规范;C和JAVA需要掌握JNI的原理;C和操作系统则需要了解任务控制块所包含的操作系统核心数据结构;C和硬件驱动则需要知道标准库的作用以及内部实现概况。而这些关键点能够描绘一张软件系统的整体框图,使程序员跳出具体技术的羁绊,具有整体视野。
4.掌握思想方法,应对潮流变迁
横向选择关键技术,那纵向呢?IT业日新月异,任何具体技术都有时效性,前几年流行一时的symbian现已随着NOKIA的没落而销声匿迹,广大symbian开发者正经历转形的阵痛。但谁又能肯定这种痛苦不会落到目前风光的android开发者头上?怎样更好的适应潮流变迁,或者说哪些是变化中不变的因素呢?
软件领域,不同系统/语言和工具间表面上千差万别,但它们的很多核心思想是一脉相承的。到一定火候之后,所提炼和掌握的思想方法不会随工具和语言的变化而改变。比如某人通过C学会了哈希表,只要他真正掌握这一思想的本质,知道它适用于哪些场合,解决哪些问题,即使转用JAVA或其他工具,也不会丢失用哈希表解决问题的能力。这种不依赖于具体语言和工具的思想方法才是计算机软件真正的精华。
但是不要奢望看几篇文章就能真正掌握这些思想,只有在大量编程实践中获取足够的正反面经验,才能把前人理论融会贯通,升华成自己的思想。有了这些,即便将来老眼昏花,也比那些只能依附于某样特定工具的程序员层次来得高。
5.从历史发展了解技术的演化脉络。
软件发展到今天,不是靠某位天才拍脑袋想出来,而是在需求带动发展,发展产生新需求的过程中不断循环前进。也就是说,对于眼前各种复杂技术,可以回头看看它们的出现是为了解决什么问题,利用了怎样的思路,经历了怎样从原始粗糙到精细专业的发展过程。幼年时期没有包装过的技术方案往往能更清楚的展示其本质思想。了解演化过程,掌握前因后果会大大加深对某项技术的理解,提升眼界和高度,况且历史故事一般比单纯的理论更有趣味。
6.利用网络。
网络已逐渐成为最好的终身免费的课外老师,它正在并且会彻底改变现在的教育和学习方式。以前读书时,有问题只能问老师,老师却不是万能的。现在网络上有无数万能的名师,比如google,baidu,wiki,以及论坛中无数的高手,你的困惑往往很多人都经历过,只要一句话就能使你茅塞顿开。要学会善用网络自己查找问题答案,特别要关注高手的博客和读书笔记。意识到这种趋势并擅加利用,会使你的成长学习快人一步
7.研究开源代码
世上有这样一群人,他们开发各种优秀软件,然后无私共享不求回报。有些开源代码汇集了众多高手的智慧,隐含无数巧妙,且经历千锤百炼后,成为不朽的经典。比如操作系统领域的linux,编译器的gcc,图象识别与处理的opencv,视频编解码的xvid/ffmpeg,加解密的openssl等,都是相关领域的圣经。
代码对照理论,理解起来容易很多。多阅读一些的优秀开源软件,熟悉掌握常用技巧,逐渐就能胸中有丘壑。读书破万卷,下笔如有神嘛!So, read the fucking source code!
8.总结与积累
读书由薄到厚,然后由厚到薄,学习就是不断发现积累问题,同时解决消化问题的动态过程。总结与积累是前提,不注意积累,经验转眼就被遗忘,象黑瞎子掰玉米,掰一个丢一个。好记性不如烂笔头,一个好的习惯是写工作日记或博客,记录每天的收获。每次当我回头从笔记中看到自己在一点一滴不断进步,那种快乐和满足能激励和鼓舞我在技术上不断追求,活到老学到老。而且记录也是总结整理和感悟的过程,往往可以从中获得一些深层次的体悟和提高。
9.其他,如
与同一爱好的朋友交流,从别人身上发现自己的盲区,使知识体系更全面;多阅读英文资料与书籍,译著一般只适合作为参考,要尽早习惯看英文手册。另外有钱去上个培训班比一个人苦学要快,不过培训机构良莠不齐,要找到适合自己当前水平的正规机构。
最后送大家四个字“学,习,思,悟”