嵌入式Linux经验谈

本文作者:admin       点击: 2009-05-12 00:00
前言:
不设限的开放原始码

Linux的魅力真的无法挡。只要你有耐心学习它-其实应该说“它们”-其中的乐趣真的乐无穷啊!可惜,一般人习惯于微软窗口环境,于是促使微软推出WinCE Pro和Core版本想跟Linux社群一较高下。但微软至今还是不开放WinCE的原始码,软件工程师必须使用它的API来设计自己的程序,因此WinCE的“黑盒子”和“臭虫”永远都无法被我们立即解决掉。这种不痛快,真让人受不了。 

反观Linux,几乎可以百分之一百满足所有想窥探操作系统究竟在搞什么的人的欲望,只要他愿意花时间去读Linux程序代码和技术手册,研究它们的逻辑,并试着自己动手做。 

尼米兹航空母舰

美国尼米兹核子动力航空母舰(Nimitz Aircraft Carrier)是历史上最大的军舰,也是最昂贵的军舰,建造这样的巨无霸是为了要充分运用F-14雄猫式等90架高性能战斗机。或许微软帝国就像尼米兹航空母舰一样壮大,但微软的财大气粗似乎没有吓阻一大群Linux雄兵。讽刺的是,Linux社群的成长已经逐渐威胁到微软的市场地位。所以我们现在要问:到底谁才是软件业的尼米兹航空母舰?微软或Linux?

木匠精神的延伸 

虽然美国是软件的发祥地,可是Linux核心却是芬兰大学生Linus Torvalds在1991年发明的。好在Free Source Foundation(FSF)创办人和GCC发明人Richard Stallman早在1984年就提倡开放原始码的观念,算是挽回美国人的面子。只是Stallman那时还没开发或找到像Linux这样好用的操作系统核心。1980年代的头条新闻是:AT&T由于捍卫BSD UNIX版权和柏克莱大学大打官司。 

1970年代,UNIX在AT&T的贝尔实验室被美国科学家们发明出来以后,AT&T就像现在的微软一样想独占UNIX程序代码的版权。“一物克一物”是自然的法则,FSF就是这样诞生的。一直持续至今,Linux社群突破微软的威吓,已经缔造了许多不可能的任务了。现在连微软也不得不使用部份的GNU/Linux程序代码。回顾这段软件历史,真教人不可思议啊! 

Linux的精神很崇高,几乎等于美国的立国精神一样伟大。自由、平等、博爱就是Linux的精神。此外,在实作上,Linux几乎都是DIY的,使用者要自己建立开发环境和许许多多工具与链接库,没人能够代劳。这是承袭美国人的习惯,他们喜欢在家里设立workshop,自己当工匠设计家俱。Linux也是如此,敲敲打打统统自己来。这种类似美国西部拓荒的精神,正是高科技不断进步的原动力。 

内行人的必备工具 

为何Linux会流行呢?因为它的功能越来越稳定和可靠;因为Linux社群结合了全世界程序设计师的力量,使它的bug越来越少了-这实在可以比拟中国万里长城和埃及金字塔的伟大工程啊!现在连Mac X OS、VxWorks和数不清的软件都有用到Linux程序代码;而直接使用Linux核心的知名操作系统,譬如:RedHat/Fedora、Debian、SUSE、Ubuntu……等,都是Linux的一个桌上型发行版。此外,还有专供嵌入式系统使用的特制Linux、微型Linux……等,这些变种Linux大都是芯片设计公司直接将Linux核心移植到他们的芯片平台上,虽然它们无法像知名的桌上型Linux一样可以让用户不断复制和重新安装,可是它们小巧玲珑,普遍应用在手机、PDA、数字相机、嵌入式PC……等便携设备中。 

最近金融海啸来袭,企业纷纷缩衣节食,于是Linux的使用者又增加了。便宜是Linux的最大优势,但是便宜并没有侵蚀到Linux的强大功能。这真是匪夷所思,违反自然法则啊! 

如今,一旦软件工程师遇到任何程序问题,第一个想到的救兵,就是上网找Linux程序,或到Linux社群的Q&A网站、部落格查看信件找答案。Linux真是个宝藏,而且它是来者不拒,任何人都可以去挖宝。连IC设计工程师也可以找到他们所需要的Linux工具。不过,要看懂这些Linux程序、技术手册、信件,坦白说并非易事。一般人对Linux还很陌生,因为Linux是一大堆奇奇怪怪的命令、程序代码和术语堆砌而成的巨塔。只有Linux内行人看得懂它的门道,外行人只能跟着看热闹了。哈! 

专利战争 
在知识经济时代,打的是智慧战争,或专利战争。而专利构成的要件是:这个创意以前没有被任何人发表过。微软有许多独门的专利,其他公司或团体若抄袭或仿造微软的创意或专利,照理说,都会被微软告上法庭的。可是,Linux却像是打不死的“蟑螂”,永远存在。这是因为Linux有不怕被告的本钱:Linux的版本控管有记录可查,每一个版本都有log档案,记录了每一个设计概念和创意。 

此外,Linux社群都利用网络通信,共同讨论问题和交换意见,他们的新创意发想几乎都是公开的,而且是第一手的;即使某个模块或算法触犯到别人的专利权,Linux社群也可以藉由众人的力量及早发现、及早移除之,并设法设计出其它替代方案。相反的,一些Linux社群的网站还很欢迎任何人复制他们的创意哩!你说奇不奇怪啊! 

不过,“面包”也很重要。有些开放原始码社群四处寻找捐款,譬如:2000年时的OpenBSD,以及许许多多默默无名的Linux网站,类似现在的他们都很容易因为财务短缺而被迫关闭或被微软个个击破。FSF的GPL授权到GPLv4后也必须和商业妥协,当初Stallman在发表GPL时,就没说GNU是免费的,可是一般人都把GNU当成“免费啤酒”一样。 

2008年,我国电子厂在CeBit展和柏林CE展吃尽了苦头,都是因为厂商事先没有查清楚专利的来源。虽然GNU是软件授权,可是硬件和芯片其实也是用软件设计而成的,而那些软件很可能是使用GNU或其他授权,因此跟Linux软件一样,纵使硬件零组件是厂商自己采购的,可是芯片和电路图的使用仍需要专利所有者授权,因为Linux或其它开放原始码不是全部免费的。 

总之,Unix是Linux的祖先,也是其它操作系统的祖先-微软或许会否认,但这却是不容置疑的事实。如果没有Unix就不会有现在的PC和嵌入式装置。Unix诞生后,GNU也随之出现。连芯片和硬件都是软件设计的,因此软件才是智能的精髓。软件授权是无形的,而法律授权却是非常无情的。许多开放原始码一开始出现时,好像是免费的,可是等到有厂商拿去量产以后,他们就会来索取权利金,最明显的例子就是uC/OS-II。只重视硬件量产的我国厂商长期漠视软件的发展,以后恐怕会遇到更多的专利陷阱,这似乎是不可避免的。

Linux的时间和空间感觉

Linux是一种操作系统,“时间”在任何操作系统中占有很重要的地位,绝对主宰的地位,这就好像生物有“生命”能够活一样,倘若没有时间,Linux也不过是一大堆没生命的“文字游戏”而已,虽然它们仍然可以被储存于光盘或硬盘之中。然而,只有时间还不够,空间也很重要。因为对使用者而言,档案(file)和模块(module)可以说是Linux的基本构成单位,而它们很占空间,占据很多记忆空间,包括:SRAM、DRAM或DDR、光盘、硬盘、SD、MMC、CF……….等的容量空间。 

Linux迷宫 
嵌入式Linux系统的开发者更需要有灵敏的时空感觉,才不至于迷失在Linux迷宫中。一旦进入Linux国度,只能遵守它的“法律”前进,才不会寸步难行、瞬间“挥发消失”。Linux开发者所做的事情有点像复制“人”或“机器人”,因为Linux开发者也是在赋予物质“灵魂”或“生命”,都将时间和空间元素发挥到极致。 
Linux的“根文件系统(root filesystem)”就是此迷宫的地理位置。根据Linux的官方规则,必须依照“文件系统层次架构标准(FHS)”来建立文件系统。FHS规定的根文件系统的最上层目录名称和内容,

Daemon 
Daemon就是Linux迷宫里的守护神(guardian spirit),这个字出自希腊神话故事。不过,在希腊神话中,daemon是会诱惑、折磨、绑架人类的,是十足可怕的魔鬼(demon)。Daemon和demon发音一样,语源也相同,但它没有demon可怕啦!除非你不了解它、没搞懂它,才会被它“咬”。呵!呵! 
其它操作系统,如微软的Winodws以“服务(service)”或“系统代理者(system agent)”称呼它。它在用户接口背后运行,在特定时间或对特殊事件做出反应。典型的daemon包括:系统注册表管理(syslogd)、打印机同步管理、e-mail管理、网络协议管理…………等。启动daemon是使用shell script,这些script大都存放在/etc/rc.d/init.d/或/etc/init.d/里面。 

通常,Linux同时要执行很多个daemon才能满足复杂的应用程序之要求,这完全依赖CPU的分时多任务的功能,其实,这种分时多任务就是在模仿人类的行为能力。在20世纪文学的现代主义中,也出现相类似的观念和尝试,例如:James Joyce的名著就是描写主人翁在一天之内,所有的思想和言行,文学上称之为“意识流”技巧,将杂七杂八互不相关的事物、想法、情绪、文字……等放在一起,其中还穿插许多双关语、变形字(也许应该算是错字)、自创的组合字,Joyce想让不同读者有各自不同的解读,同样文字但具有多层意义,读起来有点像文言文,但比文言文还要艰涩难懂。 

将时间压缩、将所有事件同时并存、一字多意,这就是“意识流”小说的特色。不过,这种自然主义(或超写实主义)小说通常是很冗长的,因为作者想要成全时间,就得牺牲空间,人物虽然不多,可是两个人的对话内容可能会占据三、四章的篇幅,读起来很吃力(因此单凭这一点,“意识流”技巧就输给计算机了)。况且引经据典,读来着实费力又费神,不是普罗大众能够接受的,倒像是饱读诗书的机器人在讲话,令人不知所云哩!科技的进步会影响到文学和艺术的发展,在这里再次得到验证。 

嵌入式Linux的硬件中断处理 

操作系统最重要的任务就是要能和各种硬件周边沟通和通讯,而硬件周边往往就是国内业者的主要产品,因此编写程序来驱动和读写这些硬件周边,就成了Linux工程师的主要工作了。 

开机程序

不管是哪一种操作系统(O.S.)-UNIX、Windows、RTOS、Linux……等,都是从开机(boot)程序开始的,而大多数的开机程序是可以和操作系统本身分离的。所谓“分离(separate)”是指开机程序不需要操作系统核心(kernel)就可以单独存在和被人开发出来。以个人计算机(PC)的操作系统为例:BIOS就是PC的开机程序,它可以和Windows、MacOS、UNIX、Linux衔接,将O.S.加载内存,最后呼叫O.S.的主进入程序(main entry program),并将CPU控制权交给O.S.。O.S.起来以后,照理说,开机程序便功成身退了,但它却没有闲着,仍然存在于内存中,要负责“接住”“软重置(soft reset/warm reset)”。软重置就是指系统不关机但重新启动的意思。而“接住”软重置,就是指当重新启动时,开机程序必须接住“重置异常(reset exception)”讯号。顺利接住之后,开机程序会重头再被执行一次,直到O.S.再次起来。 

依照CPU、硬件周边和O.S.的不同,开机程序也各有不同,所以,全球会有许多家不同的BIOS公司存在。传统的BIOS(如今看来,可以算是古董了)是将硬件周边一并初始化,所以开机时间很慢。桌上型Linux的开机程序也是如此,例如:当Red Hat不正常关机,于重开机时,可以看到一大串蓝底白字的GRUB(GRand Unified Bootloader)开机讯息。为何要这样做?为何会这么慢?无非是因为CPU、BIOS、PC制造公司不愿意改变。不过,就技术面而言,这是可以改善的,但在传统的PC-BIOS产业里,这种改革的脚步最近才刚开始而已。 

嵌入式Linux的开机程序却技术领先很多。打从一开始,嵌入式Linux的启动加载程序(bootloader)就不像它的“祖先”(例如:GRUB)那样“笨重”。U-Boot和RedBoot是目前最常用的嵌入式bootloader,还有很多公司自行开发自己的bootloader。现在有许多PC-BIOS公司也仿效嵌入式Linux的bootloader,将BIOS简化,除了必要的硬件(譬如:SDRAM内存)以外,其余硬件周边的初始化都交给O.S.或Linux核心来做。因为Linux核心允许硬件驱动程序和通讯协议堆栈(protocol stack)以动态模块的方式,于Linux起来以后,让用户以insmod命令将这些模块一一挂入Linux系统里。因此,可以大幅缩减开机所需的时间。PC-BIOS公司肯这么做,当然是经过WinTel集团同意和鼓励的,因为在双核心(dual cores)/多核心CPU的时代,谁还有能力去编写和维护数以万行的汇编语言BIOS程序呢?为了顺应这个趋势,Windows操作系统的架构想必早就做好修改了。 

中断服务程序 

有了Linux核心,要设计一个硬件中断服务程序(ISR),变的很容易。因为底层的异常或中断处理全部交由Linux负责,软件工程师只要利用request_irq将ISR和IRQ号码链接在一起就可以了。当然这是很简化的讲法,要设计一个功能正常的GPIO中断处理程序,还需要将此GPIO装置和它的驱动程序向Linux核心注册才行。 

对Linux而言,一个上层ISR可以简单地被视为一个“应用程序”,虽然这种程序仍然存在于Linux核心内。那底层的异常或中断是如何处理的呢?说来话长,但关键在于:traps.c和与traps相关的一个汇编语言档案-若CPU是ARM,此档案是entry-armv.S;若用MIPS,则此档案是genex.S。“硬件异常(hardware exception)”通常称作trap,它不同于软件中断,它是真正由硬件产生的中断。举MIPS为例,traps.c内的trap_init负责将最底层的except_vec3_generic复制到“异常来源区”-位于SDRAM或ROM内,except_vec3_generic是硬件的异常处理程序(exception handler),它和其它异常处理程序全部存在于entry-armv.S或genex.S内。

except_vec3_generic内有exception_handlers,它是用来储存每一个硬件中断的lower-ISR,trap_init负责将所有的lower-ISR填入exception_handlers中。所有的lower-ISR都是存在于entry-armv.S或genex.S内。硬件的lower-ISR称作handle_int,说来奇怪,所有硬件都使用这唯一的lower-ISR,这是因为CPU分配给硬件的中断源只有一个,不管是MIPS或ARM或PPC都是这样的。一有硬件异常或中断发生时,程序计数器(porgam counter;PC)会跳到“异常来源区”,执行except_vec3_generic,再跳到handle_int,最后跳到plat_irq_dispatch-这就是high-ISR。 

每一种CPU都有它们各自的plat_irq_dispatch,这是由软件工程师按照CPU缓存器和硬件线路的不同自行设计的,MIPS、ARM或PPC的plat_irq_dispatch都会不一样。纵使SoC的CPU核心都是ARM,但因为SoC是不同牌子的,它们的plat_irq_dispatch也会不一样。这就是为何在Linux的术语里,会有CPU和Machine两种称呼,前者易懂,后者简言之,就是指特定的板子。