Linux内核修炼之道

978-7-115-22585-6
作者: 华清远见嵌入式培训中心 任桥伟
译者:
编辑: 黄焱

图书目录:

详情

本书以轻松的语言引领读者步入Linux内核开发的大门。 本书首先讲解Linux内核学习的方法,然后讲解Linux内核编译方法、如何阅读内核代码,然后讲解系统初始化、系统调用、中断处理、内核同步机制、时间管理、进程管理

图书摘要

第1章 初识Linux

我一直都认为自己是个很冷静、很理智的人,但是在过去的某年某月,我初识了Linux,并为之着迷,至今仍深陷其中,找不到出去的路。

如果你尚未与Linux亲密接触过,那么希望本书可以成为你初识Linux的见证。如果你已经是个Linux达人,那么就选个安静的早晨或下午,陪我一起缅怀下这过去的18年吧。

1.1 Linux史记

至此落笔之际,恰至Linux问世18周年,18年的成长,风雨颇多,感慨颇多,谨以这18年来的点滴之事为Linux的成人礼添彩。

1.1.1 Linux诞生记

1987年

MINIX诞生,而我也已端坐于学堂之中,隐去一身的稚气,能够摇头晃脑地吟诵几句诗词了。若真是冥冥中自有定数的话,或许这时就暗定了4年后Linux的诞生。

1991年

Linus Torvalds,一个芬兰的大学生,他不能按照意愿访问大学的UNIX服务器,由此感到很愤怒,于是开始为一个以后被称为“Linux”的内核而工作,并于这一年的10月5日发布了Linux 0.01。

1992年

4月,第一个Linux新闻组“comp.os.linux”建立。10月,第一个可以安装的Linux版本SLS发布。同年,我拿到了平生的第一个毕业证。

1993年

8月,第一本关于Linux的著作《Linux Installation and Getting Started Version 1》出版。而这一年,我最敬佩的语文老师患病去世了,从此,我知道了生活中不仅仅只有欢聚,还有伤别。

1994年

Linux 1.0发布,并采用GPL(GNU General Public License,通用公共许可证)协议。大家要求Linus Torvalds想一个吉祥物,Linus突然想到小时候去动物园被一只企鹅追着满地打滚,还被啄了一口!既然想不到其他的吉祥物了,干脆就以这只企鹅作为吉祥物了!

1.1.2 泰坦尼克的狂潮

1995年

4月,首届Linux博览会召开,一个以Linux为特征的商业展览博览会。几个月后,我迎来了第二个中学阶段。

1996年

Linux 2.0发布,它第一个支持了SMP(对称多处理器)架构。此时Linux的全球用户已经达到了350万左右。

1997年

首例Linux病毒“Bliss”被发现。电影《泰坦尼克号》所用的160台Alpha图形工作站中,有105台采用了Linux系统。

1998年

1月,第一份Linux新闻周刊出版,同时,NetScape宣布他们将在自由软件许可协议下发布浏览器的源代码,这为Linux和自由软件的发展提供了广阔空间。

2月,Eric Raymond和他的朋友门提出了“open source”的概念,申请了该商标特权并组建了opensource.org网站,从而开始推动Linux的商业化发展。

4月,Linux广泛被美国国家公共新闻广播报道,标志Linux在主流、非技术性的媒体界首次出现。

5月,Google搜索引擎开始流行,不仅仅是因为它是最好的搜索引擎,而且还因为它是基于Linux和具有Linux特色的搜索网页。

6月,“从来没有一个用户向我提起Linux,Linux就像众多的免费产品一样,虽然它是很小的,却得到了一群忠诚的拥护者。”比尔·盖茨在6月25日的《PC周刊》上说。

7月,KDE和GNOME的桌面之争在其拥护者之间愈演愈烈,Linus以实际行动中表明KDE非常好用,在这种情况下,KDE 1.0诞生了。Oracle、Informix、Sybase都宣布将积极支持Linux。Linux开始成为一个家喻户晓的词语。

9月,Dave Whitinge和Dwight Johnson创建了LinuxToday.com,该网站后来被Internet.com收购,不过它一直是访问量最高和最容易阅读的Linux入门网站。

12月,一篇来自IDC的报道说Linux的发行量在1998年增长了200%以上,它的市场占有率也增加了150%以上。Linux拥有17%的市场占有率,增长率超过了市场上其他任何一个系统。

同年,我迎来了人生中一个非常重要的时刻:我上大学了!

1.1.3 提前发生的革命

1999年

1月,“Linux 2.2已经发布,我终于可以松口气了”创造者Linus Torvalds说。

3月,首届LinuxWorld讨论会和博览会在加洲的圣何塞举行,这是Linux第一个大型商业化的贸易展示活动,它无疑向世界昭示了Linux的到来。

8月,SG宣布了与Red Hat的合作关系,并且开始大规模地为内核的发展做贡献。Red Hat进行了首次公开募股,股价马上涨到了50美元,在那个时候这个价很高。摩托罗拉公司与Lineo建立了合作关系,进入Linux领域并提供嵌入式系统产品、支持和培训服务。Sun宣布了在Sun公共源许可(Sun Community Source License)下发行StarOffice和开发一个网络版本的办公套件。

9月,Red Hat的股票达到了135美元,这个价格在那个时候是难以置信的高。

10月,Sun宣布它将在Sun 公共源许可下公布Solaris的源代码。

12月,VA Linux Systems的首次公开募股价格是30美元,这个价格很快上涨到了300美元,它在NASDAQ历史上创造了最高的首次公开募股价格。

这一年,网络进入了宿舍,QQ、mud等也进入了我们的生活。

2000年

1月,VA Linux Systems宣布创建我们非常熟悉的SourceForge,到2000年底,SourceForge已经接到了12 000多个项目,拥有92 000个注册的开发者。

2月,最近的IDC 报告显示Linux现在成为“服务器电脑上第二个最受欢迎的操作系统”,在1999年占了25%的服务器操作系统销售额,Windows NT为38%,占第一位,NetWare为19%,排名第三,IDC以前曾预测过Linux将在2002或2003年到达第2位,这场革命提前发生了。

3月,嵌入式Linux协会(Embedded Linux Consortium)成立。

8月,HP、Intel、IBM以及NEC宣布开放源代码发展实验室(OSDL,Open Source Development Lab)成立。

9月,Trolltech发布了GPL下的Qt库。

11月,IBM宣布将在2001年投资10亿美元在Linux领域。首部基于Linux的手机IMT-2000在韩国发布。

这一年的某一天,我和同学坐在学校四大发明广场上观看《同一首歌》演出,困意盎然,期间那个粗犷的歌星的一句话却惊醒了我:“希望你们交通大学为中国的交通事业做出更大的贡献”,大意如此,我顿时无语,他的语言竟然和他的外表一样粗犷。

这一年的暑假,我第一次来到江南,在西湖断桥对面的饭馆里,透过落地窗恰好看到湖里荷花的位置,要了一份西湖醋鱼和一瓶啤酒,坐到下午四点钟,然后顺着苏堤白堤静静地走下去,直到绕湖一周再次回到断桥,已是晚上八点,坐在湖边的长凳上,一夜无语。

1.1.4 和平、爱情和Linux

2001年

1月,期待已久的Linux 2.4发布。

3月,Linux 2.5内核高级会议在加州圣何塞举行,它或许是历史上Linux 内核hacker最完整的一次聚会。

4月,IBM在几个城市鼓吹“和平、爱情和Linux”(Peace, Love and Linux)时遇到了麻烦。

6月,SHARP宣布基于Lineo嵌入式系统的Linux PDA即将上市。

这一年底,找工作的季节,我深刻认识了IT泡沫和9.11,找所谓的好工作无门和出国无门,我无奈地选择考研。

2002年

Linus Torvalds将Linux 2.4交由巴西18岁的内核开发人员Marcelo Tosatti维护,自己则负责Linux 2.5的开发工作。

这一年,我从一个交大到了另一个交大,这个转变似乎很平淡,并不深刻。

1.1.5 Ubuntu 4.10

2003年

1月,NEC宣布将在其手机中使用Linux,代表着Linux成功进军手机领域。

6月,IDC分析师称,2003年Linux服务器在西欧的销售量将达到18.2万台,到2007年,销售量将增至这个数字的3倍,销售收入将翻一番,达到19亿美元。

8月,韩国国家航空公司和IBM联合发布声明,表示韩国航空公司将把该公司的核心业务移植到IBM的eServer服务器当中完成,其中操作系统则采用Linux。

9月,三星在推出了首款基于Linux系统平台的CDMA智能手机SCH-i519。

11月,Linux 2.6发布,它被认为是第一款真正意义上的企业级内核,这是Linux内核从2001年以来第一次重大改动。

这一年,我第一次在电视直播里看着自己喜欢的米兰夺得了冠军杯。

2004年

1月,X.Org基金会成立。

2月,Linux标准2.0出台,规范了所有能被称为Linux操作系统所应该有的特性。

5月,基于Linux的路由系统出现。

10月20日,Ubuntu 首个版本发布,今天Ubuntu已经是Linux桌面发行版的一个成功典范。

11月,Firefox 1.0发布,它成为大众关注的焦点,IE市场份额降低1%——这种事已经多年没有发生过了。Firefox已经成为微软IE的强有力的对手。

又到了找工作的季节,宣讲会、笔试、面试,我就要离开学校了吗?

2005年

10月,Firefox的下载量突破了1亿大关,这表明,只要产品好,开放源代码软件也能够获得普通用户的青睐。

11月,Sun开放了除Java之外的几乎所有软件,这使得它在一夜间成为了最大的开放源码软件厂商之一。

12月,Red Hat公布了第三季度业报,销售收入增长了43.6%,利润增长了114%。

这一年夏天,遭遇了到目前为止最为严重的一次失窃,除了IQ卡,所有的卡都随着钱夹子消失了。

1.1.6 Richard Stallman的征婚启事

2006年

6月,自由软件之父Richard Stallman在自己的网站http://www.stallman.org上发布了一则“征婚启事”。

我,单身,无神论者,白人,52岁,据说比较聪明,对于政治、科学、音乐和舞蹈有着不同寻常的兴趣。

我想寻找这样一位女士:爱好广泛,对世界充满好奇心,能够清晰表达她的爱憎(我痛恨动脑筋猜测),乐于使男人着迷,渴望被温柔地爱,对于快乐、真理、美和正义的评价高于“成功”。这样的话,我们就能不断对另一方产生热烈而又美好的了解,当我们被生活中其他东西吸引的时候,彼此就能感到宽容的温暖。

我有一个22岁的孩子——自由软件运动,他占据了我大部分的生活,没有精力再抚养更多的孩子了,但是我仍然会投入地爱我的爱人。我有大量时间花在巡回演讲上,经常要去欧洲、亚洲和拉丁美洲。如果你有空在某些时间陪我一起旅行,那就最好了。

如果你有兴趣的话,请写信到rms@stallman.org,让我们看看会有什么结果。

7月,Ubuntu被授予PC World 2006 World Class Award,证明了Ubuntu成为2006年世界最好的100个产品之一。Ubuntu越来越显示出他的不凡实力,虽说他是免费的,但是后台却是商业公司Canonical,加上太空人老板的聪明才智,逐渐地开始商业合作,比如和Sun合作,对有需要的客户提供Linux支持服务。

8月,Linux业界另外一位狂人,Linuspire公司总裁Kevin Carmony宣布推出免费版本的Freespire 1.0,该版本中附带有二进制的商业硬件驱动程序,在Linux社区中引起轩然大波。27日,网站http://linux.inet.hr/poll_filesystem.html上推出“Your favorite file system?”(你最喜欢的文件系统?)投票活动。

9月16日是“国际软件自由日”。

10月,Oracle Unbreakable Linux发布,Oralce成为第一个推出自有Linux服务的非操作系统软件厂商。17日,FSG(自由标准组,一个非营利的致力于开发和促进自由开放软件标准的组织)宣布与O'Reilly Media合作,共同为Linux应用程序开发人员提供类似MSDN的服务,该服务将作为LSB (Linux Standard Base) Developer Network的一个组成部分。

11月,微软和Novell达成一揽子协议,号称要改善Linux和微软操作系统的兼容问题。如图1.1所示,看着昔日的对手用“+”连起来是否会觉得古怪?

这一年,三次去青岛,回来时遭遇三次严重的飞机晚点,让我疑惑这个世界怎么了?

1.1.7 一封公开信

2007年

1月,虚拟人生游戏(Second Life)客户端开源。两大Linux领导社团OSDL和Free Standard Group宣布合并为新的Linux Foundation(Linux基金会),此举将促进社区的资源整合,也使Linux在企业市场能够更加高效地参与竞争。

2月,Bill Xu发起了一个“致招商银行的公开信”的行动,希望用这种方式促使招商银行改变在公众服务中使用专属软件的做法,取消客户端上的ActiveX技术,而转用其他开放、不限制用户平台的技术。据说,浦发银行的网络银行能很好地支持Firefox。

3月,Novell推出模仿苹果的“Mac vs PC”广告,它在广告中插入了第三者Linux——一位迷人的年轻女子。Novell用此来宣传预装Novell Linux的PC,一共发布了3个视频,你可以在youtube上看到它们。15日,Novell公开表示,同意从总费用上说Linux比Windows要昂贵,这使它在开源社区的名誉进一步恶化。

4月,DELL推出预装Ubuntu操作系统笔记本。

5月,Firefox在Linux中显示的表单控件(特别是单选框)比较突出的问题被修正,如图1.2所示。

6月5日,微软和Linux发行商Xandros宣布,双方达成了一个技术和法律上的合作。Red Hat、Ubuntu与Mandriva拒绝与微软进行专利交易。28日,Google桌面搜索Linux版正式发布,截图如图1.3所示。29日,第三版GNU通用公共许可证GPLv3发布。

7月,Fcitx小企鹅输入法开源项目终止。Linux平台上最受欢迎的两大中文输入法之一——Fcitx小企鹅输入法,在其官方主页上宣布项目终止开发。声明中提到,有“编程高手”质疑其代码风格是项目终止的导火索。

8月,SCO在控告Linux侵犯专利权的官司中败诉,从而申请破产保护。SCO面市时以Linux销售商Caldera Systems的面目现身,然后从Santa Cruz Operation收购了UNIX业务,之后重名为SCO集团。然后他们放弃了Linux业务,并开始起诉IBM、Novell及其他公司。他们认为IBM破坏了他们签署的UNIX协议,将SCO特有的UNIX技术在开源的Linux社区发布出去。Jim Zemlin对此评论说:“如果它们把事业基础建立在协助Linux,而不是攻击Linux,那么它们大可享有像Red Hat这些公司一样的成功,而不是沦落到申请破产保护的下场。”

10月,Acacia Research通过其子公司IP Innovation向Red Hat和Novell提出控告,Red Hat Linux操作系统及Novell旗下的SUSE Linux Enterprise Desktop与SUSE Linux Enterprise Server侵犯了他所拥有的专利。随着围绕开源的纠纷不断,2007年对于律师来说注定是“丰收”的一年。

11月,Google推出基于Linux的开源移动平台Android。Phoronix网站发布了ATI显卡在Linux和Vista下的游戏性能对比测试,结果令人鼓舞,在Linux下的游戏性能首次超越了Windows!

这一年,我开始在blog.csdn.net/fudan_abc上写《Linux那些事儿》。

1.1.8 首款Android手机

2008年

1月,NOKIA宣布收购了著名开源跨平台开发工具Qt的开发商Trolltech。

2月,Google资助Linux版Photoshop的研究。

4月,Sun移除了Java最后的限制,将其彻底开源。

7月,腾讯公司在这个月的最后一天发布了QQ for Linux 1.0 Preview版,这是第一次官方的版本。

9月,Google联合T-Mobile、HTC,正式发布了首款Android平台的手机G1。Google 开源浏览器Chrome发布,发布仅仅几个小时,它的总体占有率就达到了2%。

10月,OpenOffice3.0发布,这对Linux的普及和实用化影响巨大。月底Ubuntu 8.10发布,Fedora 10发布。

12月,各类发行版的Linux操作系统占据了大约三成的上网本市场份额。

对于我来说,这一年的基调是出差,大半年之后回到上海,很多地方很多事情都变得陌生起来,才发觉忘却其实也是一件很容易的事情。

1.1.9 Linux信用卡

2009年

1月,Linux兼容内核正式使用项目UNIX名称Longene,中文别名“龙井”。兼容内核是一个自由、开源的操作系统项目,目的是要把Linux的内核扩充成一个既支持Linux应用、也支持Windows应用,既支持Linux设备驱动、也支持Windows设备驱动的兼容内核,使用户可以直接在Linux操作系统上高效运行Windows应用。

2月,微软起诉GPS设备制造商Tomtom侵犯其8项专利权,Tomtom的GPS设备采用的是Linux系统,尽管微软声称Linux侵犯其专利期已有多年,但该案被视为微软状告Linux侵权的第一案。

3月,Adobe Reader 9.1 for Linux发布。UltraEdit正被移植到Linux,名为UEX,意即UltraEdit for Linux。

4月,IDC最新发表的题为《Linux在新经济中的机会》的报告称,用户2009年的Linux开支预计将比2008年增长21%,超过整个软件市场的增长速度。整个软件市场2009年的增长率是2%。

5月,NOKIA宣布开放Qt源代码仓库,以便让社区的开发者能够进一步参与 Qt 的开发。

6月,法国的ENAC开发组为Linux内核开发了类似iPhone的Multi-touch(多点触摸)技术支持。

7月,Linux基金会与CardPartner和UMBrella银行共同推出了Visa白金信用卡,正面印有Linux吉祥物,如图1.4所示。每办理一张这样的信用卡就可以为Linux基金会带来50美元的赞助,使用该卡每消费一次Linux基金会就能从中获得1%的金额。

8月,微软在提交给美国证券交易委员会的年度文件中,将Ubuntu列入竞争对手。

9月,目前为止最新的内核版本2.6.31发布,Linux成为首个正式支持USB 3.0的操作系统。

10月,Ubuntu 9.10发布。

11月,Vim的作者Bram Moolenaar推出了新的编程语言Zimbu,一种不拐弯抹角直截了当的实验性编程语言。Moolenaar表示Zimbu集现有语言的优点于一身, 同时避开它们的不足。Zimbu代码清晰易读,使用范围广泛——既能写OS kernel,又能写脚本,还能写大的GUI程序,可以编译和运行在几乎所有系统上。

1.2 内核的版本

很多年来,Linux内核的版本都是以X.Y.Z这3个数字的形式设定的,偶数Y代表稳定版,奇数Y代表不稳定的开发版。所谓的稳定版本是指内核的特性已经固定,代码运行稳定可靠,不再增加新的特性,要改进也只是修改代码中的错误。而不稳定版本是指相对于上一个稳定版本增加了新的特性,还处于发展之中,代码运行不大可靠。

Z的递增表示个别的修正版发布。“稳定”的1.0.0内核在1994年3月发布,随后发布了“不稳定”的1.1.z分支,直到1995年3月发布了新的稳定版1.2.0。X数字从1跳跃到2是在1996年6月,正式推出稳定版2.0,之后又有不稳定版2.1 分支,然后是“稳定”的2.2、2.4和2.6。

1.2.6.x内核

这些版本都是Linus发布的基础稳定版(Basic Stable),如果发现了冲突或严重的瑕疵,以基础稳定版为基础,新的稳定的修正版本2.6.x.y就会被发布出来。

2.2.6.x.y内核

这些版本也是稳定的,它们包含了对2.6.x内核的一些问题的修复。对于那些想要最近的稳定内核,且对于测试开发中的实验性版本没有兴趣的用户来说,可以使用这些版本。

3.-rc内核

这些是候选的发布内核,是当Linus认为目前的git(Linus为了帮助管理Linux内核而开发的一个开放源码的版本控制软件)内核树处于一个健全的稳定状态,足以用于测试的时候,而发布的内核。

这些内核是不稳定的,如果试着运行它们可能会不时出现问题,但是它们最终会变成下一个稳定的内核,因此,有更多的人来测试它就显得非常重要。

4.-git内核

这些内核是Linus的内核树快照(在一个git仓库中管理着,因此而得名)。-git内核通常每天都发布,且代表了Linus的内核树的当前状态。

5.-mm内核

这些内核是Andrew Morton发布的实验性版本,作为一个新特性和实验性补丁的试验场而存在,一旦一个补丁在-mm内核中经过一段时间被证明有价值,为了使其包含在主流内核中,Andrew就会把它推荐给Linus。

虽然鼓励通过-mm内核把补丁推荐给Linus,但有时子系统的维护者或者个人会直接把补丁推给Linus,尽管它们有些时候并没有在-mm中得到测试。通常情况下,你应该尽力使自己的补丁通过-mm内核中最大程度的测试后,再合并到主流内核中。

-mm内核是最具实验性的内核分支,在运行中要比其他任何分支都可能承担更大的风险,它的目的就是为了在新的改变被加到主流内核之前,消除各种bug。

6.未来的版本号

目前2.6内核的发布已经持续了很长时间,那么什么时候推出2.7呢?Linus的回答是,不会有2.7,他不会再遵循旧的模式,新的模式更好,不值得重复过去。他表示正在考虑新的编号方式,一种基于时间的版本号。比如用2008.7取代2.6.26,中间第二个数字代表年,2008年就是2.8,2009年的第一个版本就是2.9.1,之后2010年是3.0,等等。但他又表示“大而无意义的数字是令人不快的,26已经够大了”。

1.3 获取内核源码

内核源码可以通过HTTP和FTP两种方式从http://www.kernel.org获得。

2.6.x以及2.6.x.y位于http://www.kernel.org/pub/linux/kernel/v2.6。

● -rc内核位于http://www.kernel.org/pub/linux/kernel/v2.6/testing。

● -git补丁位于http://www.kernel.org/pub/linux/kernel/v2.6/snapshots。

● -mm内核位于http://www.kernel.org/pub/linux/kernel/people/akpm/patches/2.6。

● 在Linux系统中也可以直接使用wget工具下载,比如:

# wget ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.23.tar.bz2

1.4 Linux发行版

从严格意义上来说,Linux只是一个操作系统内核,然而,一个完整的操作系统不仅仅只是内核而已,它通常还包括了桌面环境、办公套件、媒体播放器、数据库等应用软件。

许多个人、组织和企业开发了基于Linux内核的Linux发行版。现在已经有超过600个Linux发行版,可以在http://en.wikipedia.org/wiki/List_of_Linux_distributions上看到它们的列表,其中,有多于300个正处于活跃的开发中,不断地改进。

学习内核最好的方法不是直接去分析它的源代码,而是首先去使用它,依照一个由上至下循序渐进的过程,在能够熟练地使用Linux操作系统之后再去研究内核中的实现。因此,了解并选择一个发行版进行安装使用便是一个不能回避的过程。

1.4.1 软件包管理器

Linux发行版通常被分割成一个个的软件包(package),每个软件包都包含了一个特定的软件或服务,比如一个处理PNG图像格式的库,或者一个Web浏览器。

软件包通常以已编译的机器码的形式提供,由软件包管理器(package management system)负责安装和卸载。每个软件包都包含有提供给包管理器的元数据(meta-information),比如包的描述、版本以及依赖。而包管理器能够利用这些信息实现搜索、自动更新到新版本、解决软件包之间的依赖关系。

虽然各个Linux发行版通常已经提供了很多的软件包,但是为了满足自己的特殊需求,用户经常会想要安装发行版中没有的软件,比如更新版本的软件,或者某些软件的替代品(比如用KDE替代GNOME)。如果软件包只提供源码,那么就需要在本地进行编译安装,此时该软件的状态就可能会与包管理器数据库中的不一致,这样的话,包管理器将不能对这个软件包进行自动更新等管理。

显然,安装、升级和卸载应用软件是影响用户对操作系统评价的决定性因素之一,因此对于各个Linux发行版来说,简洁强大的软件包管理机制是它们不可或缺的一部分。

目前,最为常见的软件包管理器是RPM(Red Hat Package Manager)和DPKG(Debian Package)。RPM最早由Red Hat公司制定实施,随后被Mandriva、SUSE等很多发行版采用。DPKG是为Debian专门开发的包管理工具,所有源自Debian的Linux发行版都使用DPKG,比如Ubuntu、Knoppix等。

1.4.2 流行的发行版

在众多的Linux发行版当中有许多杰出的作品,这里只简单介绍其中比较流行的几个。

1.Ubuntu

Ubuntu来自于祖鲁语和科萨语,被视为非洲人的传统理念,着眼于人们之间的忠诚和联系。Ubuntu精神的大意可以翻译为“天下共享的信念,连接起每个人”,Ubuntu Linux也将这个精神带到了软件世界。

Ubuntu基于Debian,它的出现改变了许多用户对Linux的看法,在此之前,很多人认为Linux难以安装、难以使用,但Ubuntu出现之后,这些都成为了历史。

Ubuntu官方主页为http://www.ubuntu.com。

2.Fedora

Fedora是一个由Red Hat赞助,由开源社区与Red Hat工程师合作开发的项目。Red Hat 是Linux用户最为熟悉的发行版,恐怕很多人使用Linux最初的岁月都是在Red Hat上度过的,但是自Red Hat 9.0之后,它便分为两个系列:由Red Hat公司提供收费技术支持和更新的RHEL(Red Hat Enterprise Linux),以及主要由社区开发的免费的Fedora Core。

Fedora官方主页为http://www.redhat.com。

3.openSUSE

SUSE是德国最著名的Linux发行版,在全世界范围内享有较高的声誉。SUSE自主开发的软件包管理系统YaST也大受好评。SUSE于2003年年末被Novell收购。

openSUSE项目是由Novell公司资助的全球性社区计划, 旨在推进Linux的广泛使用。这个计划提供免费的openSUSE操作系统。openSUSE是Novell公司发行的企业级Linux产品的系统基础。

openSUSE官方主页为http://www.suse.com/。

4.Debian

Debian最早由Ian Murdock于1993年创建,可以算是迄今为止最遵循GNU规范的Linux系统。Debian系统分为三个版本分支(branch):stable、testing和unstable。

Debian是我使用的第二个发行版(第一个自然是Red Hat),直至今日仍在使用。Debian能有众多的fans,它的包管理机制DPKG是原因之一,DPKG被誉为所有Linux软件包管理器中最为强大的,在Debian上安装、升级、卸载和管理软件变得非常容易,因此许多Debian用户都开玩笑说:Debian将他们养懒了。

Debian官方主页为http://www.debian.org/。

5.Slackware

Slackware由Patrick Volkerding创建于1992年,算起来应当是历史最悠久的Linux发行版。Slackware曾经非常流行,但是当Linux越来越普及,新手用户越来越多后,Slackware渐渐地被新来的人们所遗忘。在其他主流发行版强调易用性的时候,Slackware依然固执地追求最原始的效率,所有的配置均还是要通过配置文件来进行。

尽管如此,Slackware仍然深入人心(大部分都是比较有经验的Linux老手)。Slackware稳定、安全,所以仍然有大批的忠实用户。

Slackware官方主页为http://www.slackware.com/。

6.Gentoo

Gentoo最初由Daniel Robbins(前Stampede Linux和FreeBSD的开发者之一)创建。由于开发者对FreeBSD的熟识,所以Gentoo拥有媲美FreeBSD ports系统的软件包管理系统portage(使用Python编写而成)。Gentoo的首个稳定版本发布于2002年。

Gentoo的出名是因为其高度的自定制性:因为它是一个基于源代码的(source-based)发行版。尽管安装时可以选择预先编译好的软件包,但是大部分使用Gentoo的用户都选择自己手动编译。这也是为什么Gentoo适合有丰富的Linux使用经验的老手使用的原因。但是要注意的是,由于编译软件需要消耗大量的时间,所以如果你所有的软件都自己编译,并安装KDE桌面系统等比较大的软件包,可能需要几天时间才能编译完。

Gentoo的官方主页为http://www.gentoo.org/。

7.Mandriva

Mandriva原名Mandrake,最早由法国人Gaël Duval创建并在1998年7月发布最初的版本,其目标是使得新用户更容易使用Linux。Mandrake是世界上第一个为非技术类用户设计的易于使用、安装和管理的Linux发行版本。

Mandriva的官网主页为http://www.mandrivalinux.com/。

1.4.3 选择Linux发行版

在众多的发行版中选择是一件很让人头痛的事情,这里介绍几种挑选的方法以供参考。

1.参考发行版排行榜

在网站http://distrowatch.com/主页的右侧,依据页面点击次数给出了排名前100的Linux发行版,如图1.5所示,默认是最近6个月的点击次数,你可以选择数据统计的时间范围。这虽然不够科学,但也足够说明问题。

2.Linux发行版比较服务

http://polishlinux.org/choose/comparison/上提供的这个服务可以让你指定两个发行版,然后进行直观的比较,比较的项目非常细致,如图1.6所示为选择Ubuntu和Mandriva时的部分显示结果。

3.Linux Distribution Chooser

http://www.zegeniestudios.net/ldc/index.php?firsttime=true上提供了“Linux Distribution Chooser”服务通过问卷的形式帮助你挑选合适的Linux发行版。如图1.7所示,你只需要回答一些简单的问题,系统会给出几个符合你要求的发行版,最后还会给出一些不完全符合但也值得考虑的发行版。

4.听听别人的意见

通过上面的挑选,如果你已经决定了最终使用的那个发行版,那么恭喜你,你可以去下载或者购买该发行版的安装盘安装体验了。如果仍然在几个发行版之间徘徊,那么就要问问别人的意见,或者到网上查找一下相关的资料,到社区看看别人的评价。如果还是决定不了,那还是试用一下吧。

第2章 配置与编译内核

如果你对Linux的兴趣仅是止于上上网、听听歌、看看碟,那么这里的内容或许并不适合你。如果你稍微有那么一点点的好奇心,希望能够体验一下新的特性、新的内核版本,懂得如何配置与编译内核都是必须的。

2.1 配置内核

编译内核的第一步就是配置内核,这是增加或减少对一些内核特性的支持的必要步骤,比如,可以为内核添加对IPv6的支持。

2.1.1 几种配置方式

为了完成内核的配置,必须切换到root用户,然后转入内核源码目录,比如:

# cd /usr/src/linux

然后执行下面的命令之一:

# make config
# make oldconfig
# make menuconfig
# make xconfig
# make gconfig
# make defconfig
# make allyesconfig
# make allmodconfig

这些命令都可以用来配置内核,它们的配置方式各不相同,不过我们比较常用的还是“make oldconfig”和“make menuconfig”。

1.make config

基于文本的最为传统的也是最为枯燥的一种配置方式,但是它可以适应任何情况。这种方式会为每一个内核支持的特性向用户提问。如果用户回答“y”,则把该特性编译进内核;回答“m”,则该特性作为模块进行编译;回答“n”,则表示不对该特性提供支持。

回答每一个问题之前,用户都需要考虑清楚,如果在配置过程中犯了错误给了错误的答案,就只能按“Ctrl+C”强行退出了。采用该方式时的配置界面如图2.1所示。

2.make oldconfig

make oldconfig与make config类似,但是它的作用是在现有内核设置文件基础上建立一个新的设置文件,只会向用户提问有关新内核特性的问题。

在内核升级的过程中,make oldconfig非常有用。用户可以将现有内核的设置文件.config复制到新内核的源码目录中,执行make oldconfig,此时,用户只需要回答那些针对新增特性的问题。

3.make menuconfig

基于终端的一种配置方式,提供了文本模式的图形用户界面,用户可以通过移动光标来浏览内核所支持的各种特性。使用这种配置方式时,系统中必须已经安装有ncurses库,否则会显示“Unable to find the Ncurses libraries.”的错误提示。make menuconfig运行时的界面如图2.2所示。

4.make xconfig

基于X Windows的一种配置方式,提供了漂亮的配置窗口,不过只有能够在X Server上使用root用户运行X应用程序时,才可以使用。它依赖于QT,如果系统中没有安装QT库,则会出“Unable to find the QT installation.”的错误提示。图2.3所示为make xconfig运行时的配置界面。

5.make gconfig

与make xconfig类似,不同的是make gconfig依赖于GTK库。图2.4所示为make gconfig运行时的配置界面。

6.make defconfig

按照默认的配置文件arch/i386/defconfig对内核进行配置,生成的.config可以用作初始配置,然后再使用make menuconfig进行定制化配置。

7.make allyesconfig

尽可能多地使用“y”设置内核选项值,生成的配置中包括了全部的内核特性。

8.make allmodconfig

尽可能多地使用“m”设置内核选项值来生成配置文件。

2.1.2 .config文件

不论采用哪种方式配置内核,最终的目的都是为了生成.config文件,.config文件位于内核源码树的顶层目录,内容形式如下:

#
# SCSI device support
#
# CONFIG_RAID_ATTRS is not set
CONFIG_SCSI=y
CONFIG_SCSI_DMA=y
# CONFIG_SCSI_TGT is not set
CONFIG_SCSI_NETLINK=y
# CONFIG_SCSI_PROC_FS is not set
#
# SCSI support type (disk, tape, CD-ROM)
#
CONFIG_BLK_DEV_SD=y
# CONFIG_CHR_DEV_ST is not set
# CONFIG_CHR_DEV_OSST is not set
CONFIG_BLK_DEV_SR=y
# CONFIG_BLK_DEV_SR_VENDOR is not set
CONFIG_CHR_DEV_SG=y
# CONFIG_CHR_DEV_SCH is not set

1.找一个旧的.config文件作参考

内核配置选项众多,即使使用漂亮的窗口界面去配置,也是相当的麻烦,所以我们最好找一个旧的.config文件作为参考,在这个.config文件的基础上执行make menuconfig等配置命令进行调整,生成新的.config文件。

当然,寻找这个作为参考的.config文件时是需要有的放矢的,一般来说,可以有如下几种途径。

● 使用make defconfig得到参考.config文件,它其实利用了arch/i386/defconfig文件。

● 利用系统中/lib/modules/<kernel-version>/build目录下的.config文件,比如:

# cd usr/src/linux-2.6.24
# cp /lib/modules/2.6.23/build/.config .

● 使用当前系统的配置文件,一般位于/boot目录中。

● 到网上搜索下载别人配置好的.config文件。

● 使用某个发行版提供的.config文件,比如slackware的.config。

2.直接修改.config文件

如果只是对内核所支持的特性进行微调,则可以直接修改现有的.config文件而不需使用前面所述的配置方式。.config文件中每个配置选项的值只能取“y”和“m”两者之一,如果这个特性不再支持,将其对应的选项注释掉即可。

3.备份、重用.config文件

通常我们需要将生成的.config文件备份,以备后用。比如当前内核版本为2.6.23,将它的.config文件备份为config-2.6.23。

# cd usr/src/linux-2.6.23
# cp .config /root/config-2.6.23

如果打算将内核升级到2.6.24,则可以重用备份的.config文件,因为这两个内核之间的区别很小。

# cd usr/src/linux-2.6.24
# cp /root/config-2.6.23 .config

不过,仅仅复制了该文件并不意味着马上就可以编译了。在编译前,我们还必须首先执行make oldconfig,在执行过程中,如果新内核选项没有出现在复制的.config文件中,它会停下来等候选择。

2.1.3 配置选项详解

内核的配置选项有很多,通常情况下大部分选项都可以使用默认值,因此并不需要了解它们代表的具体意义。但是某些应用需要将内核裁剪得足够小,这就需要我们知道各个选项所代表的特性,通过去掉不需要的特性,以及将部分特性编译为可加载的模块来减小内核的长度。

另外,即使不考虑内核裁剪的因素,当我们打算深入研究某一个子系统时,也需要首先从该子系统所涵盖的配置选项入手(可以从该子系统代码目录下的各个Kconfig文件入手),掌握它的各部分实现代码之间的分布关系,避重就轻地进行代码的分析。

下面的内容仅是对部分比较常用的配置选项进行简单介绍,读者可以参考内核针对各个选项提供的帮助。

1.General setup(常规设置)

● Local version - append to kernel release:在内核版本后面加上自定义的版本字符串(小于64字符),可以使用“uname –a”命令看到。

● Automatically append version information to the version string:自动在版本字符串后面添加版本信息,编译时需要有perl以及git仓库支持。

● Support for paging of anonymous memory (swap):允许使用交换分区(swap devices)或者交换文件(swap files)来作为虚拟内存。

● System V IPC:System V进程间通信(IPC)支持,许多程序需要这个功能,通常必选。

● POSIX Message Queues:POSIX消息队列,IPC的一部分。

● Export task/process statistics through netlink:通过netlink接口向用户空间导出进程的统计信息。netlink是一种在内核与用户应用之间进行双向数据传输的非常好的方式,用户应用使用标准的socket API就可以使用netlink提供的强大功能。

● Auditing support:审计支持,某些内核模块(例如SELinux,Security-Enhanced Linux)需要它。

● Kernel->user space relay support (formerly relayfs):在某些文件系统上(比如debugfs)提供从内核空间向用户空间传递大量数据的接口。

● Optimize for size (Look out for broken compilers!):编译时优化内核尺寸(使用“-Os”而不是“-O2”作为gcc参数进行编译)。

2.Loadable module support(可加载模块支持)

● Enable loadable module support:打开可加载模块支持,需要执行make modules_install将内核模块安装在/lib/modules/<kernel-version>目录下面。

● Module unloading:允许卸载已经加载的模块。

● Forced module unloading:允许强制卸载正在使用中的模块。

● Module versioning support:允许使用其他内核版本的模块。

● Automatic kernel module loading:允许内核通过运行modprobe自动加载所需的模块。

3.Block layer(块设备层)

● Support for Large Block Devices:支持大于2TB的块设备。

● Support for Large Single Files:支持大于2TB的文件。

● IO Schedulers:I/O调度器选项。

● Anticipatory I/O scheduler:简称as调度器,anticipatory的中文含义“预料的,预想的”揭示了这个算法的特点,简单地说,在一个个I/O发生的时候,如果又有进程请求I/O操作,则将产生一个猜测时间,猜测这个I/O请求是要干什么的。这会造成比较大的延时,对数据库应用很糟糕,而对于Web Server等则会表现的不错。这个算法也可以简单理解为面向低速磁盘的,因为那个“猜测”实际上的目的是为了减少磁头移动时间。

● Deadline I/O scheduler:提供了最小的延迟时间和尚佳的吞吐量,特别适合于读取较多的环境(比如数据库)。

● CFQ I/O scheduler:为系统内的所有任务分配相同的带宽,提供一个公平的工作环境,它比较适合桌面环境。

● No-op:是一个简化的调度程序,它只作最基本的合并与排序。与桌面系统的关系不是很大,主要用在一些特殊的软件与硬件环境下,这些软件与硬件一般都拥有自己的调度机制,对内核支持的要求很小,很适合一些嵌入式系统环境。

4.Processor type and features(CPU类型及特性)

● Symmetric multi-processing support:对称多处理器支持,如果系统中有多个CPU或者使用的是多核CPU就选上。

● Subarchitecture Type:处理器的子架构,如果使用PC的话应当选“PC-compatible”。

● Processor family:处理器系列,按照实际使用的CPU选择。

● Generic x86 support:通用x86支持。

● HPET Timer Support:HPET是替代8254芯片的新一代定时器。

● Maximum number of CPUs:支持的最大CPU数,每增加一个内核映像(image文件)将增加大约8KB。

● SMT (Hyperthreading) scheduler support:支持Intel的超线程(HT)技术。

● Multi-core scheduler support:针对多核CPU进行调度策略优化。

● Preemption Model:内核抢占模式,有3种模式可供选择。“No Forced Preemption (Server)”为适合服务器环境的禁止内核抢占模式;“Voluntary Kernel Preemption (Desktop)”模式支持自愿抢占,但此时内核仍然是不可抢占的,它仅仅是通过增加抢占点缩减了抢占延迟,适用于一些需要较好响应性的环境,如桌面环境;“Preemptible Kernel (Low-Latency Desktop)”模式既包含了自愿抢占,又使内核具有可抢占性,因此具有很好的响应延迟,主要适用于桌面和一些嵌入式系统。

● Preempt The Big Kernel Lock:支持抢占大内核锁,适用于桌面环境。

● Machine Check Exception:让CPU检测到系统故障时通知内核,以便内核采取相应的措施。

● check for P4 thermal throttling interrupt:当P4的CPU过热时显示一条警告消息。

● High Memory Support:支持的最大内存,总内存小于等于1GB的选“off”,大于4GB的选“64G”。

● 64 bit Memory and IO resources:适用64位的内核和I/O资源。

● Allocate 3rd-level pagetables from highmem:在内存很大的系统上将用户空间的页表放到高端内存区,以节约低端内存。

● MTRR (Memory Type Range Register) support:MTRR规定了读写某段物理内存的策略,用于优化CPU数据传送性能。例如,可将MTTR设为在显存的地址范围上使用“write-combining”策略,CPU能够在PCI/AGP总线上,将许多次少量的数据写入集合成一次大的数据写入,这样能获得 2.5倍以上图像传送速度的提升。详细说明可参看内核文档Documentation/mtrr.txt。

● Boot from EFI support:EFI用于替代传统的BIOS计数。

● Enable kernel irq balancing:打开中断负载均衡。

● Timer frequency:内核时钟频率,桌面环境推荐使用1000 Hz,服务器环境推荐使用100 Hz或250 Hz。

● kexec system call:提供kexec系统调用,可以不必重启系统而切换到另一个内核。

5.Power management options(电源管理选项)

● Power Management support:电源管理有APM和ACPI两种标准且不能同时使用。即使关闭该选项,X86上运行的Linux也会在空闲时发出HLT指令将CPU进入睡眠状态。

● Suspend to RAM and standby:支持待机状态,系统将目前的运行状态等数据存放在内存,关闭硬盘、外设等设备,进入等待状态。此时内存仍然需要电力维持其数据,但整机耗电很少。恢复时计算机从内存读出数据,回到挂起前的状态,恢复速度较快。

● Hibernation(aka ‘suspend to disk’):支持休眠状态,将目前的运行状态等数据存放在硬盘上某个文件或者某个特定的区域,关闭硬盘、外设等设备,进入关机状态。此时计算机完全关闭,不耗电。恢复时计算机从休眠文件/分区中读出数据,回到休眠前的状态,恢复速度较慢。

● ACPI (Advanced Configuration and Power Interface) Support:必须运行acpid守护程序ACPI才能起作用。ACPI是为了取代APM而设计的,因此应该尽量使用ACPI而不是APM。

● APM (Advanced Power Management) BIOS Support:APM支持。

● CPU Frequency scaling:允许动态改变CPU主频,达到省电和降温的目的。

6.Bus options (PCI, PCMCIA, EISA, MCA, ISA)

● PCI support:PCI支持,如果使用了PCI或PCI Express设备就必选。

● PCI access mode:PCI访问模式,即访问PCI的方式,可以有4个选择,BIOS、 MMConfig、Direct、Any。前三个选择分别表示通过BIOS去访问、抛开BIOS直接(Direct)去访问、通过MMConfig去访问。最后一个选择“Any”表示如果拿不准的话可以让内核去选择一种访问方式,当然,内核会按照一定的优先级,首先尝试MMConfig,然后是Direct,如果这两种方式都不起效,最后再使用BIOS。

基于PCI总线的特殊地位,BIOS中专门提供了针对PCI总线的操作,这些操作里就包括了总线枚举的整个过程。在系统加电以后自检时,就会完成对PCI总线的枚举,之后对PCI设备的访问就都是通过BIOS调用的形式进行,提供有这些功能和服务的BIOS就称之为PCI BIOS。这也是PCI访问模式中的BIOS模式所表达的意思。

但是,一些旧的主板上,BIOS并不支持这么做,还有一些嵌入式系统里甚至于根本就没有BIOS的存在,为了适应各种需要,Linux就自己实现了包括总线枚举在内的一整套PCI总线操作,而不再去依赖BIOS,这就是Direct访问模式的由来。当然在64位的平台上,是没有什么PCI BIOS的,采用的总是Direct方式,使用make menuconfig配置内核的时候也就根本看不到PCI access mode这一项。

至于MMConfig模式,是PCI Express才用得上的。

● Message Signaled Interrupts (MSI and MSI-X):MSI是PCI Spec v2.2中提出一种全新的中断方式。MSI通过向一个预定义的内存地址写入一个已经预定义好的Message来提出中断请求,这个Message到达PCI主桥(host bridge)时,主桥会将它转换为具体的中断,发送到处理器。对PCI设备来说,这就消除了对中断引脚电路的需要,但是PCI Spec里还是要求支持MSI的设备最好同时也要具有中断引脚。MSI-X则是MSI的增强。

● Interrupts on hypertransport devices:hypertransport是AMD在1999年提出的一种总线技术。

● ISA support:ISA设备支持。

● MCA support:旧的IBM的台式机和笔记本上可能会有这种总线。

● PCCARD (PCMCIA/CardBus) support:PCMCIA卡(主要用于笔记本)支持。

● PCI Hotplug Support:PCI热插拔支持。

7.Executable file formats(可执行文件格式)

● Kernel support for ELF binaries:ELF是Linux下最常用的二进制文件格式,必选。

● Kernel support for a.out and ECOFF binaries:早期UNIX系统的可执行文件格式,目前已经被ELF格式取代。

● Kernel support for MISC binaries:Linux是第一个在内核级提供内建Java解释器的支持,从而执行Java代码的操作系统之一。这在2.2内核里已经实现了。2.4内核又做了改进,将这种支持的方法改为对“Misc”二进制类型的支持。通过使用这种类型的二进制代码类型,用户甚至可以利用DOSEMU(MS DOS模拟器)或者WINE (MS Windows模拟器)来运行在DOS/Windows下的.exe或.com的程序。

8.Networking

● Networking options:网络选项。

● Packet socket:Packet Socket可以让应用程序(比如tcpdump、iptables等)直接与网络设备通信,而不需通过内核中的中间网络协议(intermediate networking protocol)。

● TCP/IP networking:TCP/IP协议支持。

● The IPv6 protocol:IPv6支持。

● Network packet filtering (replaces ipchains):Netfilter可以对数据包进行过滤和修改,可以作为防火墙、网关、代理或网桥使用。

● DCCP Configuration:数据报拥塞控制协议(Datagram Congestion Control Protocol)在UDP的基础上增加了流控和拥塞控制机制,适用于流媒体业务的传输。

● SCTP Configuration:流控制传输协议(Stream Control Transmission Protocol)是一种新兴的传输层协议。TCP协议一次只能连接一个IP地址,而SCTP协议一次可以连接多个IP地址,且可以自动平衡网络负载,一旦某一个IP地址失效会自动将网络负载转移到其他IP地址上。

● TIPC Configuration:透明内部进程间通信协议(The Transparent Inter Process Communication Protocol)专门用于内部集群通信(intra cluster communication)。

● Asynchronous Transfer Mode (ATM):异步传输模式(ATM)支持。

● Appletalk protocol support:与MAC机器通信的协议。

● Amateur Radio support:业余无线电支持。

● IrDA (infrared) subsystem support:红外线支持,比如无线鼠标。

● Bluetooth subsystem support:蓝牙支持。

9.Device Drivers(设备驱动)

● Memory Technology Devices (MTD):MTD(Memory Technology Device)设备支持,比如常用于数码相机或嵌入式系统的闪存卡。

● Plug and Play support:即插即用支持。

● Block devices:块设备支持。

● ATA/ATAPI/MFM/RLL support:通常是指IDE硬盘和ATAPI光驱。

● SCSI device support:SCSI设备支持。

● Serial ATA and Parallel ATA drivers:SATA和PATA设备支持。

● Multi-device support (RAID and LVM):RAID和LVM支持。

● Network device support:网络设备支持。

● Input device support:输入设备支持。

● Character devices:字符设备支持。

● I2C support:I2C支持。

● SPI support:SPI(Serial Peripheral interface)支持。

● Multimedia devices:音视频多媒体设备支持。

● Graphics support:图形设备以及显卡支持。

● Sound:声卡支持(ALSA和OSS)。

● USB support:USB支持。

● MMC/SD Card support:MMC/SD卡支持。

● Real Time Clock:RTC支持,RTC通常与CMOS集成在一起,因此BIOS可以从中读取当前时间。

● DMA Engine support:DMA将某些传输数据的操作从CPU转移到专用硬件,从而可以进行异步传输并减轻CPU负载。

10.File systems(文件系统)

● Second extended fs support:Ext2文件系统支持。

● Ext3 journalling file system support:Ext3日志文件系统支持。

● Ext4dev/ext4 extended fs support:最新的Ext4文件系统支持。

● Inotify file change notification support:文件系统事件通知机制Inotify支持,用于替代老的dnotify机制。

● Inotify support for userspace:用户空间Inotify支持。

● Quota support:磁盘限额支持,限制某个用户或者某组用户的磁盘占用空间。

● Filesystem in Userspace support:FUSE允许在用户空间实现一个文件系统,如果你打算开发一个自己的文件系统或者使用一个基于FUSE的文件系统就选吧。

● Pseudo filesystems:/proc等伪文件系统支持。

● Native Language Support:本地语言支持,使用FAT/NTFS分区时需要选上。

11.Instrumentation Support(工具支持)

● Profiling support:打开Profiling支持,用于对内核的性能进行分析。

● OProfile system profiling:OProfile是Linux的若干种性能分析工具中的一种,能够帮助用户识别诸如循环的展开、高速缓存的使用率过低、低效的类型转换和冗余操作等问题。

● Kprobes:使用printk收集内核的调试信息是一个众所周知的方法,而使用了Kprobes,不需要经常重新引导和重新编译内核就可以完成这一任务。

12.Kernel hacking(内核hack选项)

● Show timing information on printks:在printk的输出中包含时间信息,可以用来分析内核启动过程各步骤所用时间。

● Magic SysRq key:Magic SysRq键是一种组合键,在系统无法响应时,可以进行一些基本的维护任务。

● Enable unused/obsolete exported symbols:导出无用和废弃的符号,这将使内核不必要地增大。

● Run 'make headers_check' when building vmlinux:在编译内核时运行“make headers_check”命令检查内核头文件,当你修改了与用户空间相关的内核头文件后建议启用该选项。

● Use 4Kb for kernel stacks instead of 8Kb:如果配置该选项,则内核为进程提供的内核栈缩小为4KB,为此,每个CPU提供了一个4KB大小的中断栈专供中断服务程序使用。小的内核栈可以缓解系统的内存压力。

13.Security options(安全选项)

● Enable different security models:允许内核选择不同的安全模型,如果未选中则内核将使用默认的安全模型。

● Socket and Networking Security Hooks:允许安全模型通过Security Hook对Socket 与Networking进行访问控制。

● Root Plug Support:一个简单的Linux安全模块,在指定的USB设备不存在时,它简单地禁止所有egid为0的进程运行。

14.Cryptographic API(加密API)

提供核心的加密API支持。

2.2 编译内核

2.2.1 准备工作

虽然与配置内核相比,编译内核所做的工作要少得多,但是在正式编译之前,我们仍需要做一些必要的准备。

1.需要了解的基础知识

首先我们需要了解系统中与编译过程有关的目录及文件。

● /boot/vmlinuz-<version>:用于启动的压缩内核镜像。

● /boot/system.map-<version>:存储内核符号表。

● /boot/initrd.img-<version>:一个镜像文件,类似ramdisk(initrd的全称就是initial ramdisk),它将一些驱动程序和命令工具打包到img里,比如sisc_mod、ext3、sd_mod等模块和insmod、nash等命令,然后在开机的时候在内存里开辟一段区域,释放到那里运行。

它的作用是,在没有mount根分区(/)以前,系统要执行一些操作,比如挂载scsi驱动,此时就把initrd释放到内存里,作一个虚拟的/,然后执行其根目录下的脚本,运行insmod等命令加载模块。

● /boot/grub/menu.lst:GRUB的配置文件(不同的发行版中它可能位于不同位置)。

● /lib/modules/:该目录包含了内核模块(包括系统自带的和自己编译的)及其他文件,不同的子目录由内核版本号来区分。

● /lib/modules/<kernel-version>/build/:存放编译新模块所需的文件,包括了Makefile、.config、module.symVers(模块符号信息)以及内核头文件等。

● /lib/modules/<kernel-version>/kernel/:存放模块的ko文件。

● /lib/modules/<kernel-version>/modules.alias:模块别名定义,模块加载工具使用它来加载相应的模块。

● /lib/modules/<kernel-version>/modules.dep:定义了模块间的依赖关系。

● /lib/modules/<kernel-version>/modules.symbols:标识符号属于哪个模块。

2.下载内核源码压缩包

需要注意下载bz2格式的压缩包时,需要安装bzip2工具进行解压。

3.获取相关补丁

如果需要的某些特性并没有被现有内核支持,则需要去获取相关的补丁。比如,为了使内核支持图形化的启动界面,我们可能要用到bootsplash工具。bootsplash项目的网站http://www.bootsplash.org/上提供了针对很多内核版本的补丁供下载。

4.构建编译环境

编译内核需要用到一系列的工具,在编译之前,我们需要确保它们已经被安装。下面是一些Debian和Ubuntu发行版上用到的工具包。

● modutils:模块工具。

● kernel-package:包括了make-kpkg等工具。

● patch:如果不需要为内核打补丁,可以不安装patch工具包。

● build-essential:提供了C/C++的编译环境,包括了gcc、make等工具。

5.备份

当修改内核时,我们必须准备一个能够启动的备用内核。实现该目的的一种方式是通过配置Linux引导程序(LILO或GRUB)以允许用户选择启动的内核映象,其中之一是从未修改过的内核的备份。

2.2.2 如何为内核打补丁

通过打补丁的方法升级内核版本,可以不用下载整个源代码。针对每个内核版本的补丁文件可以在ftp.kernel.org上面获得,我们的问题是应该选择哪个补丁文件,一个补丁又到底应该打在哪个版本的内核上。

下面的内容简单介绍了如何应用与卸载补丁,详细的内容也可以查看内核文档Document/applying-patchs。

1.什么是补丁

一个补丁就是一个文本文档,由diff工具创建,它存放了两个不同版本的源代码之间的差异。为了正确地应用一个补丁,我们需要知道这个补丁文件是以哪个版本为基础产生出来的,以及它将把目前的源代码变化到什么新的版本,简单地说,就是需要清楚产生这个补丁文件的两个源码版本的情况。

2.如何打补丁和卸载补丁

patch工具可以用于打补丁和卸载补丁。内核的补丁是相对于保存内核源码的父目录而生成的,这就意味着,补丁文件中的文件路径包含了内核源码存放目录的名字(比如linux-2.6.23/,或者像是“a/”和“b/”之类的其他名字)。但是很可能我们本地系统上的内核源码存放目录和补丁中不匹配,为了解决这个问题,我们需要切换到自己的源码目录,并且在执行patch命令的时候加上“-p1”参数,这样就会去掉补丁文件中路径的第一个分量。比如:

# cd /usr/src/linux
# patch –p1 < ../patch-x.y.z

为了卸载一个以前打上的补丁,需要使用“-R”参数。

# patch –R –p1 < ../patch-x.y.z

3.如何利用补丁升级内核版本

考虑这样的几个场景:将内核从2.6.23升级到2.6.24;将内核从2.6.23.8升级到2.6.24.6;将内核从2.6.23.6升级到2.6.23.8。不管处于哪种场景,打补丁时要谨记的一点是:内核的补丁文件都是以2.6.x(基础稳定版basic stable,2.6.x.y是稳定版stable)为基础发布的。下面对这3种场景的打补丁过程分别进行介绍。

(1)将内核从2.6.23升级到2.6.24。这种情况,可直接使用补丁文件patch-2.6.24。

# patch –p1 < ../patch-2.6.24

因为下载得到的补丁文件通常是使用gzip或bzip2压缩的格式,所以使用前还要将其解压生成patch-x.y.z文件。不过,我们也可以不用解压,使用下面的命令形式:

# bzcat ../patch-2.6.24.bz2 | patch -p1 //bz2格式
# zcat ../patch-2.6.24.gz | patch -p1 //gz格式

(2)将内核从2.6.23.8升级到2.6.24.6。这种情况下,我们需要将升级的过程分解为几个步骤,首先将2.6.23.8退回到2.6.23,然后再升级到2.6.24,最后升级到2.6.24.6。

# bzcat ../patch-2.6.23.8.bz2 | patch -p1 –R
# bzcat ../patch-2.6.24.bz2 | patch -p1
# bzcat ../patch-2.6.24.6.bz2 | patch -p1

(3)将内核从2.6.23.6升级到2.6.23.8。这种情况下,我们同样需要将升级过程分解,首先将2.6.23.6退回到2.6.23,然后再升级到2.6.23.8。

# bzcat ../patch-2.6.23.6.bz2 | patch -p1 –R
# bzcat ../patch-2.6.23.8.bz2 | patch -p1

4.patch的替代工具

除了patch之外,也有其他的用来打补丁的工具,比如interdiff、ketchup等。

2.2.3 编译步骤

下面是针对2.6内核的通用的编译步骤。

(1)下载源码并解压。

虽然我们可以将内核源码存放在任何自己找得到的地方,但通常还是会将内核源码下载到/usr/src目录并解压(Linus本人说不要解压到这个目录)。

# cd /usr/src
# wget ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.23.tar.bz2
# tar jxvf linux-2.6.23.tar.bz2

(2)如果需要的话,下载补丁。

(3)进入刚刚解压的内核源码目录。

# cd /usr/src/linux-2.6.23

(4)如果需要的话,为内核打补丁。

(5)配置内核。

# make menuconfig

(6)编译内核。

# make

(7)安装内核模块。将所有编译得到的内核模块复制到/lib/modules/<kernel-version>/目录下面。

# make modules_install

(8)安装内核。

# make install

make install主要完成了3个工作。

● 复制生成的内核映像到/boot目录。在内核编译完成后,源码树目录arch/i386/boot/中会生成一个bzImage文件,该文件被复制到/boot目录并重命名为vmlinuz-2.6.23。

● 生成initrd-<kernel-version>.img文件。

● 配置引导程序(GRUB或LILO)。

(9)重启进入新内核。

2.2.4 文档的编译

内核源码树的Documentation/目录下面有大量的文档,它们是内核最好的参考资料,对于我们学习内核有着重要的意义。我们可以使用下面的一些命令生成指定格式的文档。

# make htmldocs //生成HTML文件
# make pdfdocs //生成PDF文件
# make psdocs //生成Postscript文件
# make mandocs //为Kernel API生成man手册
# make installmandocs //将Kernel API手册页安装到man程序能够找到的目录中

执行make htmldocs/pdfdocs/psdocs之后,在Documentation/DocBook/目录下,会生成一些很重要的文档:

● kernel-api:内核开发的API手册。

● kernel-locking:内核加锁的HOWTO文档。

● kernel-hacking:内核开发的一些注意事项。

● usb:USB Host端的API手册。

● gadget:Usb Device端的API手册。

2.2.5 编译小技巧

下面是一些内核编译过程中可以使用的小技巧。

(1)屏蔽编译信息。

# make > /dev/null

(2)加速编译过程。

可以使用“-j<n>”参数,其中n = 2 * CPU的个数,对于一般的单CPU系统,通常用是使用“-j2”参数,为编译过程分配两个任务,这样在进行磁盘I/O操作时候,CPU就不会空闲了。

# make –j2 > /dev/null

(3)使用verbose模式,将每一步执行的命令都打印出来,并重定向到一个文件中去,这样以后可以方便地查找模块之间的依赖关系。

# make V=1 > ~/bak.txt

(4)使用ccache提高编译速度。ccache主页为http://ccache.samba.org/。使用ccache时,需要更改源码树根目录下面的Makefile文件,在CC和HOSTCC变量的定义前添加ccache。

CC = ccache $(CROSS_COMPILE)gcc
HOSTCC = ccache gcc

2.3 自由软件的编译与安装

在我们使用Linux的过程中,经常会遇到需要自己编译软件的情况,可以说自由软件的百家争鸣本身就是Linux世界不可分割的一部分。因此,本节简单介绍下自由软件的编译与安装过程。

自由软件和私有软件的区别在于它们对源代码的访问不同。自由软件以源代码文件压缩包的形式发布,用户必须自己编译源代码才能使用。

对于大部分的自由软件,存在已编译版本,用户可以只安装这些预编译的二进制代码。而某些自由软件并不以这种形式发布,或者其早期版本不以二进制代码形式发布,而且,如果你使用的是特殊的操作系统或者特殊的硬件架构,许多软件并没有为此提供编译好的版本。更重要的是,亲自编译软件可以让你只启用自己感兴趣的选项,或者通过对该软件源码的修正以便它能够确实满足自己的需求。

2.3.1 发布时的组织结构

通常,自由软件发布时都具有相同的组织结构。

● INSTALL文件:描述安装步骤。

● README文件:包含有关该软件的一般信息(简短描述、作者、项目URL、相关文档、有用的链接等)。如果不存在INSTALL文件,通常在README文件中会包含安装步骤简介。

● COPYING文件:包含许可证或是发布该软件的情形。有时候该文件叫LICENSE。

● CONTRIB或是CREDITS文件:包含该软件相关人员的列表(活动的参与者、相关评论、第三方软件等)。

● CHANGES文件:包含最近改进以及故障修正,有时为较少见的NEWS文件。

● Makefile文件:控制该软件的编译(对make该文件是必需的)。如果该文件一开始不存在,那么它将由预编译配置过程生成。

● 经常也有configure或Imakefile文件以便用户针对特殊系统自定义生成新的Makefile文件。

● 保存源文件以及在编译结束后保存二进制文件的目录,通常为src。

● 保存与该软件相关的文档(通常是man形式)的目录,通常为doc。

● 有时也有保存该软件特定数据(一般是配置文件、数据示例文件或资源文件)的目录。

2.3.2 配置

仅从技术兴趣上看,自由软件作者提供源代码的目的在于使该软件可移植,使其能够在现存的类UNIX系统上几乎不加修改地使用,而这需要在编译这些软件之前对其进行配置。

有几种不同的配置方式,但我们需要选择作者指定的那个。

● 如果在该软件的发布目录中存在一个名为configure的文件,则可以使用AutoConf进行配置。

● 如果在该软件的发布目录中存在一个名为Imakefile的文件,则可以使用imake进行配置。

● 根据INSTALL文件(或README文件)的内容提示运行一个shell脚本(比如install.sh)。

1.AutoConf

AutoConf用于正确配置软件,它创建编译需要的文件(比如Makefile),且有时会直接对源代码进行修改(比如使用config.h.in文件)。AutoConf的规则十分简单。

● 该软件的作者了解配置他的软件需要进行哪些测试(比如:“你使用哪一版本的库文件?”),他使用一种精确的语法将这些测试编写进configure.in文件。

● 并且,他通过运行AutoConf从configure.in文件生成configure自动配置脚本,该脚本将在配置软件的时候运行所需的测试。

● 最终用户执行该脚本,这样AutoConf就会为编译进行配置。

下面是一个AutoConf的使用示例:

# ./configure
loading cache ./config.cache
checking for gcc... gcc
checking whether the C compiler (gcc ) works... yes
checking whether the C compiler (gcc ) is a cross-compiler... no
checking whether we are using GNU C... yes
checking whether gcc accepts -g... yes
checking for main in -lX11... yes
checking for main in -lXpm... yes
checking for main in -lguile... yes
checking for main in -lm... yes
checking for main in -lncurses... yes
checking how to run the C preprocessor... gcc -E
checking for X... libraries /usr/X11R6/lib, headers /usr/X11R6/include
checking for ANSI C header files... yes
checking for unistd.h... yes
checking for working const... yes
updating cache ./config.cache
creating ./config.status
creating lib/Makefile
creating src/Makefile
creating Makefile

为了更好地控制configure,可以通过命令行或环境变量为其添加选项。比如:

# ./configure --with-gcc --prefix=/opt/GNU

或者(在bash中):

# export CC=`which gcc`
# export CFLAGS=-O2
# ./configure --with-gcc

或者:

# CC=gcc CFLAGS=-O2 ./configure

一般而言,大部分configure脚本执行失败时的出错信息都类似于“configure: error: Cannot find library guile”,这表示configure脚本找不到某个库文件。configure脚本在测试时会使用该库文件编译一个小测试程序,如果它不能成功编译该程序,就说明它不能够编译该软件,所以会给出该出错信息。出现该错误后,我们可以采取下面的措施。

● 可以在config.log文件中找到配置过程所执行的每一步骤,从中发现产生这一错误的原因。

● 检查提示的库文件是否已正确安装。如果没有,在安装之后再运行configure。检查它是否已安装的有效方式是查找包含提示字符串的库文件,一般是lib<名称>.so。比如:

# find / -name 'libguile*'

● 检查编译器是否能够访问该库文件,它是否在/usr/lib、/lib、/usr/X11R6/lib (或是在由环境变量LD_LIBRARY_PATH指出的)目录中。

● 检查该库文件相应的头文件是否已安装于正确地方(通常是/usr/include或/usr/local/include或/usr/X11R6/include)。

● 检查是否拥有足够的磁盘空间(configure脚本需要一些空间来保存中间文件)。可以通过“dh”命令查看系统中各分区的使用情况。

● 检查是否某些环境变量设置错了,比如LD_LIBRARY_PATH。

2.imake

imake让你能够使用简单的规则生成Makefile文件以配置自由软件,这些规则指定需要编译那些文件才能生成所需的二进制文件,而imake生成相应的Makefile。可在Imakefile文件中指定这些规则。

使用imake最为简单的方法是进入解压后的代码目录,然后运行xmkmf脚本,而它又会调用imake程序。

3.各种shell脚本

阅读INSTALL或README文件了解进一步信息。通常,需要执行install.sh或configure.sh文件。该安装脚本或是非交互的(它自己决定需要什么),或者会向询问有关系统的信息(比如是路径)。

另外,某些自由软件在其初期开发阶段,有时会要求用户手动更改某些配置文件。通常,这些文件是Makefile文件和config.h文件。

2.3.3 编译

既然该软件已正确配置,所剩的就是编译了。这个阶段通常比较简单,并且不会出现什么严重的问题。

编译源代码的各个步骤常存储于Makefile或GNUMakefile文件中。当执行make时,它会从当前目录读取该文件(如果该文件存在的话)。如果它不存在,可以通过make的-f选项指定其他文件。

通常,使用make需要遵循如下一些约定。

● 不加参数执行make表示仅编译程序,而不安装。

● make install编译程序(不是一定的),并随后将文件安装到系统的正确位置。某些文件常常无法正确安装(比如man、info),可能会需要用户自己手动复制。有时候,需要在子目录中再次执行make install,通常这是由于包含了第三方开发的模块。

● make clean清除编译产生的所有临时文件,大多数情况下还会删除可执行文件。编译时最为常见的错误有:

(1)main.c:16: decl.h: No such file or directory

编译器不能找到对应的头文件。不过,在软件配置阶段就可能已经发现该错误了。解决方法如下。

● 检查该头文件确实已经存在于以下某个目录中:/usr/include、/usr/local/include、/usr/X11R6/include或它们的某个子目录。如果没有,请在整个磁盘上查找它(可以使用find或locate命令)。如果还是没有,请检查是否已经安装了该头文件所对应的库。

● 检查该头文件确实可以读取(可以使用less命令来测试)。

● 如果它确实在/usr/local/include或/usr/X11R6/include目录中,你可能需要为自己的编译器添加额外的参数,打开编译出错的那个目录中的那个Makefile文件,找到出错的那一行,并在调用编译器(gcc,有时是$(CC))的地方添加字符串-I<路径>,其中<路径>是包含该头文件的路径。如果不清楚要把该选项加到哪里,就把它添加到文件开始处CFLAGS或CC变量定义后面。

● 再次运行make,如果它还是不起作用,请检查前面的那个选项是否被添加于编译过程中出错的地方。

● 如果还是不起作用,只有向周围的高手或开发社区求助了。

(2)'struct foo' undeclared (first use this function)

结构几乎是所有软件都会使用的一种数据类型,系统在头文件中可能会定义许多。这个错误提示表示该问题可能是由于找不到头文件,或误用头文件所造成。解决该问题的正确步骤如下。

● 试着检查一下出问题的结构是否已由程序或系统定义,比如用grep命令查看该结构是否已经在某个头文件中定义了。比如,进入该软件源代码的根目录中执行:

# find . -name '*.h'| xargs grep 'struct foo' | less

在屏幕上可能会出现许多行,找到头文件中grep指出的那一行,检查它是否就是你所需要的。如果是,则说明该头文件未包含于出错的.c文件中。有两个解决方法:在出错的.c文件开始处添加#include "<文件名>.h";或者将该结构的定义复制到该文件的开始处。

● 如果没有找到,在系统头文件(通常位于/usr/include、/usr/X11R6/include或/usr/local/include)中再次查找。不过这一次如果找到的话,就需要在.c文件中添加#include <<文件名>.h>的语句。

● 如果该结构还是不存在,请试着找找它是否是在哪个库中定义(请查看INSTALL 或README文件以确定该软件使用了哪些库以及它们的版本)。如果该软件需要的版本不是系统上安装的那一个,就需要更新该库了。

● 如果依然不起作用,就要检查该程序是否真能在你的架构上运行了(某些程序还没有移植到Linux系统上),并检查你是否已经为自己的架构正确配置了该程序(比如在执行configure的时候)。

(3)parse error

这个问题解决起来较为复杂,因为编译器常会在真正出错的地方之后报错。有时候,它仅仅是由于某个数据类型未定义。如果碰上如下的错误信息:

main.c:1: parse error before `foo_t
main.c:1: warning: data definition has no type or storage class

那么很可能是foo_t类型未曾定义,解决方式同前一个问题类似。

(4)no space left on device

这个问题解决起来较为简单:磁盘上已经没有足够的空间从源文件生成二进制文件了。你可以通过释放安装目录所在分区的一些空间来解决(删除临时文件或源文件,卸载某些已经不用的程序)。

(5)/usr/bin/ld: cannot open -lglloq: No such file or directory

这表示ld程序无法找到某个库。为了包含某个库,ld将会搜索由-l<库>选项指定的库文件,相应文件为lib<库>.so。如果ld找不到,它将给出一条错误信息。要解决该问题,可以如下操作。

● 用locate命令检查该文件是否在硬盘上。通常,图形库在/usr/X11R6/lib目录中。比如:

# locate libglloq

如果上述查找没有结果,就使用find命令再次查找(比如find /usr -name "libglloq.so*")。如果还是找不到,就需要安装它了。

● 一旦找到了该库,请检查它是否能被ld访问。/etc/ld.so.conf文件指定了寻找这些库文件的目录,把该库的路径添加到该文件末尾(可能需要重启系统以使改动起作用)。也可以把该目录添加到环境变量LD_LIBRARY_PATH中。

● 如果还是不行,请用file命令检查该库文件是否为一个可执行文件。如果它是一个符号链接,请检查该链接完好且没有指向不存在的文件(可用nm libglloq.so检查)。而且,该库文件的权限可能是错误的(比如,如果不是root用户且该库文件不允许读)。

(6)glloq.c(.text+0x34): undefined reference to `glloq_init'

该问题是由于在编译的最后阶段某个符号找不到。通常,这是因为某个库出问题了。可能的问题如下。

● 首先,请查找该符号是否应该在某个库文件中。比如,如果该符号以gtk开头,它就应该属于gtk库。如果这个库能够很容易地找到,你可以用nm命令列出该库中的符号。比如:

# nm libglloq.so
0000000000109df0 d glloq_message_func
000000000010a984 b glloq_msg
0000000000008a58 t glloq_nearest_pow
0000000000109dd8 d glloq_free_list
0000000000109cf8 d glloq_mem_chunk

使用nm时添加-o选项可以分别在不同行中显示库中的名称,从而使搜索变得更为简单。假定我们要搜索符号bulgroz_max,可以:

# nm /usr/lib/lib*.so | grep bulgroz_max
# nm /usr/X11R6/lib/lib*.so | grep bulgroz_max
# nm /usr/local/lib/lib*.so | grep bulgroz_max
/usr/local/lib/libfrobnicate.so:000000000004d848 T bulgroz_max

可以看到该符号bulgroz_max定义于frobnicate库中(其名称前有一个大写字符T)。然后,你只需要编辑Makefile文件以在编译命令行中添加字符串-lfrobnicate(将其添加于定义LDFLAGS或LFGLAGS的那一行的末尾,或是在创建相应二进制文件的那一行处)。

● 编译中使用的库文件不是该软件需要的。请阅读该发布版的README或INSTALL文件,以查看需要哪个版本。

● 该发布版的目标文件没有全部正确链接,缺少了定义该函数的文件。请键入nm -o *.o以查看应该是哪个文件,然后将相应的.o文件添加到对应的编译命令行上。

● 出错的函数或变量可能并不存在,可以尝试删除它:编辑出问题的源文件(它的名字会出现于出错信息的开始处)。这可能会导致程序执行混乱,以及在启动时出现segfault(段错误)等错误。

(7)Segmentation fault (core dumped)

有时候,编译器立即挂起,并产生该错误信息。除了建议安装一个更新版本的编译器,没有更好的办法了。

(8)no space on /tmp

在不同的阶段,编译器需要临时工作空间,如果它不能申请到这些空间的话,它将出错。因此,你需要清理分区,不过请尽量小心,因为删除某些文件会导致某些正在执行的程序(X服务器、管道等)挂起。你必需能够清楚知道自己在做什么!如果/tmp所在的分区并不仅仅包含该目录(比如根目录),请搜索并删除core文件。

(9)make/configure 死循环

在你的系统上,这常常只是一个时间上的问题。make确实需要了解计算机时间和它检查的文件的时间。它比较这两个时间,并根据结果确定某个目标是否已过时。

某些日期问题可能导致make不停地编译(或不停地递归编译某个子目录)。在这种情况下,touch(其作用是将有问题的文件的时间设定为当前时间)通常会解决该问题。比如:

# touch *

或者:

# find . | xargs touch

2.3.4 安装

既然编译已经完成,接下来就需要将编译后的文件复制到一个合适的位置(通常是在/usr/local的某个子目录中)。执行make install将完成该任务,安装所有需要的文件。

通常,在INSTALL或README文件中将描述该过程。不过有时候,开发人员会忘了提供这一信息。那时,我们就必须亲自安装所有东西了。

● 复制可执行文件(程序)到/usr/local/bin目录。

● 复制库文件(lib*.so文件)到/usr/local/lib目录。

● 复制头文件(*.h文件)到/usr/local/include目录。

● 复制数据文件通常到/usr/local/share。如果你不知道安装的过程,可以先试着不复制数据文件运行程序,然后就可以按照程序的提示将他们复制到正确的位置了(比如根据某个出错信息:Cannot open /usr/local/share/glloq/data.db)。

● 文档的安装有一点不同:man文件通常会被复制到某个/usr/local/man的子目录中,通常这些文件的格式为troff(或groff),且它们的扩展名是某个数字,它们的文件名是某个命令的名称(比如 echo.1),根据其扩展名 n将其复制到/usr/local/man/man<n>目录;info文件复制到/usr/info或/usr/local/info目录。

相关图书

Linux常用命令自学手册
Linux常用命令自学手册
庖丁解牛Linux操作系统分析
庖丁解牛Linux操作系统分析
Linux后端开发工程实践
Linux后端开发工程实践
轻松学Linux:从Manjaro到Arch Linux
轻松学Linux:从Manjaro到Arch Linux
Linux高性能网络详解:从DPDK、RDMA到XDP
Linux高性能网络详解:从DPDK、RDMA到XDP
跟老韩学Linux架构(基础篇)
跟老韩学Linux架构(基础篇)

相关文章

相关课程