前言:
学习Linux和嵌入式也有一段时间了。其中经历了很多,但也学到很多。这里做一些总结,算是一个系列吧。但又不知能写多少文章,也不知能写多久。我将它命名为“嵌入式Linux之行”。目前李迟所学有限,见识不可能高,但却是李迟的经验和对所学东西的总结(有来自网络上的,也有来自书本的)。鉴于实际情况(因为我不知以后还会不会写此类文章),我将目前的几篇文章定为这个系列的“前奏”。
所谓“工欲善其事,必先得其器”。文中错误之处,还请见谅,并提出,可以在文后评论,一家一起学习进步。本文是该系列中的首篇文章,主要关于我对我所学的一些总结以及个人的想法。
1、起因
我在大二的时候就决定学习嵌入式了,原因很简单,某次开什么会,我看见我的助班的简介,主攻方向便是嵌入式,那时,“嵌入式”便进了我脑海。虽然不知其为何物,但却让我好奇。于是就决定学习它了。——不要奇怪,大学低年级时,我什么都想学,网站、黑客什么的,我都看过相关的书。现在想来,我似乎只对嵌入式感兴趣了。但是,只是限于某一个方面,即嵌入式Linux。
那时便开始了我的计划,学习单片机,学习Linux,等等。学单片机的原因也简单,因为那时我不会写程序,恰好有同学找我学单片机,我就学了。学Linux,是由于看到我宿舍同学(即sky.ljp)的Magic Linux桌面很好,觉得很爽,就去学习了(我说了,我对很多事都好奇)。现在想来,Linux的桌面于我,已没有什么好与不好的了,只要是Linux,对我来说,都差不多。(又:后来他sky.ljp无意告诉我,是他的一位同学“勾引”他搞,而他又“勾引”我搞。)
但是,学习的过程却是很辛苦,首先,没有志同道合之人,遇到困难,没人帮你——因为没人搞这个;解决了困难,没人跟你分享——因为没人懂这个。可能是这个原因吧,造成我今日的性格。
至于后来慢慢熟悉敲命令、写代码,是经过训练的。我的专业英语,是看芯片手册、看协议练出来的;我懂用emacs,是练出来的。现在有人问我问题,我解决后,都不忘加一句:这是我练出来的(我为什么懂xxx?因为是我练出来的!)。我想,大多人经历过一番辛苦后,都会有这种想法吧。
2、论学
嵌入式的范围很广很广,我目前所学的只限于Linux这一方面,因为我不想放弃我积累的Linux知识和经验。而且,用了这么久的Linux,也看了很多相关新闻,开源项目,我渐渐懂了一些GNU、Linux的精神了。我也愿意为其贡献自己的一份力量,这并不是说我多伟大,多牛,我觉得,如果某些问题我解决过的,别人又碰到过的,我有义务去帮忙;我将我的经验、教训总结出来,等等,是我目前能做的,是出了一份力了(不知接触Linux久的人,会不会有这种想法)。我渐渐意识到,写程序、写文章,首先是对自己责任,其次才是对别人(或读者)负责。先不管他人的评论,首先要对得起自己:程序是给自己写的,文章是给自己写的。这一点,《疯狂的程序员》里有提到的,这本书对我的影响很大,它让我思想改变了很多。
虽然乐于助人常常给自己造成很多麻烦,但我觉得我还是要这样做。可惜,这样会给别人造成致命的一点,别人常常以为你什么都懂,连个简单问题都懒得百度,就直接问人,我很烦这类事情,我也觉得自己很冤,本来好好的,想帮助你,结果却害了你。——这个“帮助”,不是说什么事情都帮。唉。其中的矛盾,我也没法很好地解决。只好一遍又一遍地说要学会独立,学会培养自己学习的能力,我不知有几人能听得进去。(注意:这里所说的“简单问题”,是指那种自己应该能解决的问题,比如,程序运行或编译代码时,提示“No such file or directory”这类问题,特此说明)
学某些东西,如果时间长了,应该对它会有所了解,有所熟悉,比如使用Linux很久了,连自己进到哪个目录都不知道,那就让人不解了。我们应该在学习过程中总结一些技巧,学会一些技巧,学习是一个长期过程,比如我最近才知道Linux的一个技巧,比如你在一个很深的目录,不小心输入“cd”,回车,回到自己的家目录,这时就可以输入“cd -”,就能进到刚才那个目录了。我周边很多人,都习惯于考试前突击,把一个学期的知识用一两周时间学习,这样的结果除了得高分外,学到的东西,很快就忘了。我自认为我的操作系统、编译原理和组成原理很懂,相关的书也看了很多,比如,学操作系统时,我还自己看了保护模式的知识。结果呢?考试不高分,因为分心去看别的知识点,而不是考试知识点。这终于让我彻底意识到考试与学习之间的关系,这种意识在未来很长时间内是不会变的。但我不后悔这样做,因为学到的东西是自己的,高分是给用人单位和学校看的,——当然,评奖学金、评优秀时很有用。做“自己”和做“别人的自己”,两种生活方式,就看我们怎么去选择了。
3、Linux
Linux其实是一个很有趣的OS,不过,很多人使用别的系统多了,就觉得看不惯Linux。比如,一般可执行文件都是以exe结尾,可Linux中很多情况下都忽略扩展名,这让人想不明白,人家安装软件都是用鼠标直接点击“下一步”的,而Linux却是./configure,make,make install。
其实,我们需要辩证看待事情,Windows有它的好,Linux也有它的好,它们各自的理念都不一样,为何一定要比较出高低好坏呢?
下面说一下Linux的一些基本的常识。这里的理解全是个人的理解,如果有错误,希望能指正。
Linux下很多看似没意义的字符,其实是有含义的,虽然我有些理解不到位,但却能帮助记忆。比如GCC的一些编译选项,如I(大写的字母I),可以认为它是include的首字母,如Wall,它不是wall,而是Warn all,等等。只要有一定的专业英文,理解它们是不成问题了。
Linux下的共享库前缀为lib,后缀名为so,so估计是shared object的简称吧,命名也有规律,比如一个SDL的库,名称很可能就是libSDL.so,在使用该库时,可以写它的全名,因为前缀和后缀都固定了,单写其“真正”名称即可,可以这样使用-lSDL来引入该库。
库是Linux很重要的组成部分,有些库牵涉的程序、软件很多,有一次,我在LG电脑上删除qt3的库(因为我安装了qt4,不需要qt3了),但是重启后,却进入不了桌面,我估计是被删除的库为别的桌面软件所用,后来使用光盘重新安装后所有的qt3,这才解决问题。此后,我不敢随便删除什么库了。
4、 基本能力
学习的能力。这是一种基本的能力,因为是你自己学习,而不是他人学习,凡事都要经过自己的思考,别人的经验、别人的代码,别人的算法,只有经过自己的消化,才有成为自己的东西。
英文的能力。这不是说CET-4或CET-6这种英语,那也是给学校和用人单位看的。我们的英文是真正为我们所用的英文。这里的能力指:
1、能看得懂编译错误信息,系统提示信息;
2、到某个开源项目的官方网站上知道在哪里下载源代码,知道看它README文件或INSTALL文件,并根据其中的说明来安装软件。
3、一些计算机方面的词汇,比如不要把driver看成“司机”,不要将bus看成“公车”,更不能将“kernel”不要翻译成“核仁”,等等。
其实,英语不难,假如时时接触到,哪会有不熟悉之理?比如“ls”命令,一开始可能不知道为何“ls”就能查看目录和文件,但当知道“ls”是“list”后,就会明白了。所有这些,不是一日便能学会的,前文说了,学习是一个长期的过程,这个过程中的积累,可以是请教别人得到的,可以是看相关书籍得到的,可以是从网络上搜索得到的。
专业知识的能力,这个是没得说了,一些基本的专业知识的能力是最起码的。我很难想象一个计算机专业的学生不会安装Windows系统,一个自动化专业学习没焊过电路板——有例外者不在列于此。
5、细节决定成败
有时,一些细节会给我们解决问题路上造成很大麻烦,有过调试经历的人应该会明白,有时,一个小小的疏忽,花费很久时间,一夜,甚至几天。
我遇到过一种情况,有一同学将无极性电容焊错了,因为那个地方有两个电容,四个孔,距离又相近,结果将电容的脚焊错了,由于电容小,又藏在单片机底下,花了不少时日解决这个“小小”的问题。
上面的是做板过程出现的问题,其实,做板到写程序,到烧程序到板上,都要很小心,每一步不能出错,我很反对将这些分工,它们是一个整体,如果从画电路图到焊板,到写代码,都是一个人的话,解决问题可能会比较快速,因为是一个人在操作。但这样代价太大了,其实可以找一些比较默契的人来一起合作,组队,这不失为一种好方法。现在不是很流行团队精神吗?我觉得,如果是志同道合之士的话,配合起来会很默契(至少所需时间不会很长),而不用进行什么“素质拓展”活动了。(我跟LG和LS他们还算默契吧,大家都搞过单片机,都是一个专业的,能谈的话题也多)
在写代码过程中,细节同样很重要。
有一次,我的同学编译一个程序,编译信息很奇怪,后来才知道,原来是一个宏的名称跟某个函数的参数名称一样造成的。我自己没有遇到这种情况,因为我代码中的宏全部是大写的,这样应该不会造成名称冲突,因为一个函数的参数是大写的话,看上去不太好。这告诉我们,遵循某些既成的约定,能比较容易、方便找到问题所在并解决之。
一般来说,头文件中都会有“#ifndef _HELLO_H #define _HELLO_H”等防止头文件被多次包含的语句。但有一次,我遇到一种情况,即某个头文件的这些宏语句定义跟系统内的一个头文件所用的宏语句是一模一样的。这样编译就会出错了。——应该不一定就会出错,但我遇到的情况,的的确确就是因为这个原因造成的。
在我做毕业设计过程中,有一部分是网络发送模块,也遇到一个小小细节花费很长时间才解决得了。原来,我将某个变量的类型从int 改成unsigned int,这样,当这个变量减到小于0时,它就变成一个很大的数了,那么,它永远不会变成负数。我郁闷了几天,后来通过gdb调试,一次一次打印该变量经过观察才发现这个问题,从此,我对有符号与无符号都有阴影了。
一些细节,需要我们付出多大的代价?!
此外,对于学习的一些哲理,网上有很多人分享了自己的经验,这样都是很宝贵的。比如:
“如果你不能享受追求技术给人生带来的愉悦,就到此为止吧”。
——来自http://linux.chinaunix.net/bbs/viewthread.php?tid=1164376&extra=page%3D1
“看得越多,学得越深,越发觉自己无知”
——一个printf(“helloworldn”)很简单吧,但如果你使用strace追踪它的系统调用,深入了解的话,你会发现自己不知不觉掉入了万丈深渊,出不来了。但等你出来后,你又会发现自己的功力大大提升了。所谓“一桶水不响,半桶水响当当”是也。
“搞技术的人,应该耐得住寂寞,抵得住外界诱惑,坐得住冷板凳。”
“君子有所不为而后有所为。”
——在某一方面付出了时间精力,必然在另一方面失去很多东西,世上没有十全十美的事。不可能整个学期都在玩,却希望考试通过,甚至拿奖学金(不排除很聪明的人,但我肯定是做不到的)。
搞技术,这本来就是一条不归路。如果承受不了,那就到此为止吧!