HACK #1 如何获取Linux内核

本节介绍获取Linux内核源代码的各种方法。
“获取内核”这个说法看似简单,其实Linux内核有很多种衍生版本。要找出自己想要的源代码到底是哪一个,必须首先理解各种衍生版本的意义。
接下来将简单介绍Linux内核的开发模式,并分析各种衍生版本在其中所处的地位,然后介绍获取这些衍生版本的源代码的方法。
内核的种类
想要获取正确的Linux内核源代码,首先必须了解Linux内核的开发模式。
Linux内核是由多个开发者以分散型的模式进行开发的。这里出现的“分散型”,是指多个衍生源码树同时存在。下面将简单介绍一些具有代表性的源码树及其地位。
Linus树
最具有代表性的源码树,应属Linux内核的最初创始人——Linus Torvalds所管理的Linus树。新版本Linux内核的发布,就意味着Linus树的源代码被贴上了新发布版本的标签。到2011年为止,Linux内核的版本号一直是用2.6.x这样的三个数字来表示的注1。Linus树一直被认为是Linux内核源代码的“根源”,因此一旦其发布了新版本,其他的开发树就会将自己独特的开发成果移植到这个版本上,在此基础上再次进行开发。Linus树由于其“根源”的地位而称为主线(mainline)。
一旦发布新版本Linus树,就会立刻打开一个“合并窗口”(merge window),接受下一版本需要作出的改变。合并窗口将开启约两周时间。合并窗口关闭后,就会发布下一版本的候选版,即所谓的“rc内核”注2。从rc内核发布后到下一版本发布的期间为测试期,这一期间基本只接受关于bugfix的修改。rc版内核每隔约一周时间会依次推出rc1、rc2……当Linus判断其质量已经达到可以发布的水平时,就会作为新版本发布。按照最近的实际情况来看,基本上在rc6~rc9左右就会发布新版本,也就是说Linux内核每隔2~3个月就会发布新版本。新版本发布后,又会打开下一版本的合并窗口,然后对rc版进行测试。Linux内核就是按照这样的周期来开发的。
小贴士:Linus树的内核由于完全没有任何华而不实的东西,因此称为“香草”(vanilla)内核或“库存”(stock)内核。
linux-next树
这是一个为发布将来的版本而积累新代码并进行测试的源码树,主要由Stephen Rothwell等人进行管理和运营。原则上要添加新功能或者进行安装配置时,首先要在linux-next树中进行测试,在确认各自之间可以兼容之后再添加到Linus树内。
stable树
这是一个主要只针对过去发布的内核版本进行bug修改,使其更加稳定的树,由Greg Kroah-Hartman、Chris Wright进行维护管理。这个树的版本号是在Linus树的版本号后面加一位数字,以2.6.x.y这样的4个数字来表示。针对某个Linus树版本的稳定(stable)版维护一般持续6个月左右,但也有持续更久的。
开发树
Linux内核可以说是各种功能的集合体。例如内存管理、文件系统、网络、各种设备驱动程序、CPU架构固有部分等。这些功能部分称为“子系统”,各子系统分别在不同的源码树中进行开发。在开发、修改过程中也有一些不属于特定子系统的内容,这些内容首先会被发送到Andrew Morton管理的mm树(准确地说是mmotm:mm on the moment ,补丁包的缩写)。这样的源码树统称为“开发树”。
在各开发树中开发出的源代码在经过linux-next中的测试后再植入Linus树。
开发树的数量多如繁星。如果哪天你因为想要开发某个功能而在手边的源代码上进行了修改,这也可以说是一个“开发树”。
Linus树、开发树等作为所有树的根源,也称为“upstream”,即“上游”。但这是广义上的叫法,有时也仅指最上游的Linus树。

发布版内核
最后要介绍的是发布版内核(distribution kernel)。应该有很多人使用的都是作为Linux发布版的一部分发布的内核。这些来源于发布版的内核几乎都是在Linus树或stable树内核的基础上进行发布版特有的扩展和bug修改而得到的。像这样添加了发布版特有的修改,并作为发布版的一部分发布的内核,就称为“发布版内核”。
如何获取上游内核
在了解Linux内核的各种衍生版本后,我们首先尝试一下获取上游内核(upstream kernel)。Linus树、linux-next树,以及绝大部分的开发树都可以从http://www.kernel.org/获取(见图1-1)。
Linux内核的开发都是在最新版上游内核的基础上进行的。其中最重要的就是作为所有树的根源的Linus树。下面介绍获取Linus树的两种方法。

下载tar文件
获取Linus树最简单的方法就是从kernel.org下载tar文件。2.6内核所有发布版本的tar文件都能够从http://www.kernel.org/pub/linux/kernel/v2.6/获取。
这里有很多种类的文件。例如,表1-1所示的是与2.6.38对应的文件,可以从中随意选择一个下载。无论下载的是哪个,解压缩后或打补丁后的tar文件都是一样的。
表1-1 Linux-2.6.38的各种源文件

rc版或者更新更为频繁的快照tar文件存放在子目录下。主要的子目录如表1-2所示。
表1-2 http://www.kernel.org/pub/linux/kernel/v2.6/的子目录

使用Git
Linus树和开发树通过修复各种补丁而不断更新。在最新的树中进行开发是最基本的原则,因此为了保持最新,必须每天多次下载tar文件修复补丁。这项工作是非常花费精力的,但是也不需要担心,因为可以用Git来解决。
Git是Linux内核所采用的SCM(Source Code Management system),具备分散开发所需的多个功能。Git命令更为详细的使用方法将在Hack #4中介绍,这里就先了解一下怎样使用Git命令来获取最新的Linus树。要在适当的目录下执行下列命令,但是在此之前必须注意的是,因为这条命令会将包括修改记录在内的所有仓库数据复制到本地磁盘中,所以必须要有1GB以上的磁盘容量。在操作时请注意磁盘和网络的容量。

$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6

命令执行完成后,应该就会生成一个标题为linux-2.6的目录。这就是包括修改记录在内的Linus树的最新、最完整的副本。
为了让手头的源码树时刻保持最新,需要在源码树的根目录(linux-2.6)下执行下列命令。

$ git pull

如果没有对手头的源码树代码作出任何修改,该命令会使得手头的源码树与Linus树的最新状态保持一致。当使用git clone进行复制时,git命令会记住复制源目录的URL,因此执行git pull时不需要指定URL。
使用git命令还可以获取除Linus树以外的开发树的最新版本。在http://git.kernel.org/上能看到放置在kernel.org下的其他开发树一览表。如果希望开发或者追踪各领域最新开发情况,也可以从这里找到开发树的URL。
如何获取发布版内核
在多数情况下,发布版内核的源代码都是按照各发布版所采用的方法进行打包的。因此要获取发布版内核的源代码,只需要下载源代码包,进行安装或解压缩就可以了。
下面选取具有代表性的发布版Fedora和Ubuntu为例,讲解如何获取这两种发布版内核源代码。这里选取的发布版的版本分别为Fedora 14和Ubuntu 10.10。
Fedora
在Fedora中,内核源码是作为源码RPM(SRPM)提供的。使用yum-units包里所带的yumdownloader下载SRPM。此后要使用的yum-builddep也是yum-units包中所带的,所以如果事先没有安装,首先请安装这个工具包。
可以执行下列命令来下载内核的SRPM。

$ yumdownloader --source kernel

在笔者的环境下,下载的是kernel-2.6.35.11-83.fc14.src.rpm。
如前文所述,发布版内核都带有自身特有的补丁。SRPM是将vanilla内核的源代码和补丁分开放置的,补丁在创建过程中被分配给vanilla内核的源代码。所以要获取发布版内核的源代码,就要完全执行RPM的创建过程,但并不完全执行。虽然每个SRPM在创建RPM时都需要用到不同的源码包,但只要执行下列命令,就能够安装创建Linux内核所需的所有源码包。这条命令请在root权限下执行。

# yum-builddep kernel-2.6.35.11-83.fc14.src.rpm

安装SRPM需要执行下列命令。安装SRPM,就是指将所包含的文件解压缩。SRPM包含的文件将解压缩到在主目录下生成的rpmbuild的几个子目录下。
小贴士:生成rpmbuild目录的位置,是通过%_topdir这个rpm的宏变量来设置的。在以前的发布版中是在/usr/src/redhat下的生成,近来的版本是在/usr/lib/rpm/macros下创建:

%_topdir          %{getenv:HOME}/rpmbuild

直接在用户目录下生成。

$ rpm 杋 kernel-2.6.35.11-83.fc14.src.rpm

RPM包的创建是通过rpmbuild命令进行的。本次操作的目的是获取内核的源代码,所以为了让命令结束前能给源代码修复补丁,应在rpmbuild命令中加上-bp选项。命令中的参数会赋予一个用来创建源码包的设置文件,即SPEC文件。

$ cd~/rpmbuild/SPEC
$ rpmbuild 朾p kernel.spec

这时就会生成一个标题为~/rpmbuild/BUILD/kernel-2.6.35.fc14/linux-2.6.35.x86_64的目录,在这个目录下会生成发布版内核的源代码。
使用源代码来创建内核二进制文件的方法,请参考Hack #2。
Ubuntu
在Ubuntu或基于Ubuntu的Debian下,内核源代码是作为deb包提供的。首先,与其他的源码包一样用apt-get来执行安装。标题为Linux-source的源码包就是最新的内核源码包的元包。

apt-get install linux-source

在笔者的环境下,到这一步就完成了linux-source-2.6.35的安装。
在安装内核源代码的deb包后,会在/usr/src下生成tar文件,只要将这个文件复制到适当的目录下并解压缩,就能够获取内核源代码。

$ cp /usr/src/linux-source-2.6.35.tar.bz2~
$ cd
$ tar xjf linux-source-2.6.35.tar.bz2

关于创建内核二进制码的方法,同样请参考Hack #2。
小结
本节介绍了在上游内核与发布版内核这两种情形下获取内核源代码的方法。首先要获取源代码,然后才能够读取源代码、修改bug以及开发新功能。Linux内核中有很多信息是必须读取源代码后才能理解的。通过读取源代码,能够从真正意义上理解一直以来“以为理解”的内容。因此一定要努力学习源代码。
参考文献
内核文档 Documentation/development-process/*
Linux内核版本3.0
2011年5月,Linus Torvalds宣布,Linux内核版本由2.6升级到3.0。据Linus Torvalds称,2.6系列由于经过39次发布后,更新号(第三个数字)过大,因此本次版本升级最大的目的就是进行一次改头换面。由2.6.39到3.0的版本升级与2.6系列内的版本升级并没有什么不同,也是由2.6系列延续下来的。目前预计在版本3系列中,将第二个数字作为Linus树的更新号,第三个数字作为stable树的更新号使用。也就是说,Linus树3.0的下一个发布版本将是3.1,基于版本3.0的stable树内核将是3.0.1、3.0.2。Linus树内核的tar文件在版本3系列中放在以下位置:
http://www.kernel.org/pub/linux/kernel/v3.0/
Git仓库也同样可以通过前面提到的URL(git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6)来获取。
—Munehiro IKEDA

《Linux内核精髓:精通Linux内核必会的75个绝技》一HACK #1 如何获取Linux内核的更多相关文章

  1. 《Linux内核精髓:精通Linux内核必会的75个绝技》目录

    1章 内核入门HACK #1 如何获取Linux内核HACK #2 如何编译Linux内核HACK #3 如何编写内核模块HACK #4 如何使用GitHACK #5 使用checkpatch.pl检 ...

  2. 《Linux内核精髓:精通Linux内核必会的75个绝技》一HACK #16 OOM Killer的运行与结构

    HACK #16 OOM Killer的运行与结构(1) 本节介绍OOM Killer的运行与结构. Linux中的Out Of Memory(OOM) Killer功能作为确保内存的最终手段,可以在 ...

  3. 《Linux内核精髓:精通Linux内核必会的75个绝技》一HACK #15 ramzswap

    HACK #15 ramzswap 本节介绍将一部分内存作为交换设备使用的ramzswap.ramzswap是将一部分内存空间作为交换设备使用的基于RAM的块设备.对要换出(swapout)的页面进行 ...

  4. 《Linux内核精髓:精通Linux内核必会的75个绝技》一HACK #11cpuset

    HACK #11cpuset 本节介绍控制物理CPU分配的cpuset.cpuset是Linux控制组(Cgroup)之一,其功能是指定特定进程或线程所使用的CPU组.另外,除CPU以外,同样还能指定 ...

  5. 《Linux内核精髓:精通Linux内核必会的75个绝技》一HACK #3 如何编写内核模块

    HACK #3 如何编写内核模块 本节将介绍向Linux内核中动态添加功能的结构—内核模块的编写方法.内核模块Linux内核是单内核(monolithic kernel),也就是所有的内核功能都集成在 ...

  6. 《Linux内核精髓:精通Linux内核必会的75个绝技》一HACK #2 如何编译Linux内核

    HACK #2 如何编译Linux内核 本节介绍编译Linux内核的方法.当发现bug而修改源代码或者添加新功能时,就需要对内核进行重新编译,生成二进制映像文件.另外,如果想要使用发布版内核中无效的功 ...

  7. 《Linux内核精髓:精通Linux内核必会的75个绝技》一HACK #21FUSE

    HACK #21FUSE 本节将介绍使用用户进程的文件系统框架—FUSE.FUSE概要FUSE(Filesystem in Userspace,用户空间文件系统),是用来生成用户空间的一般进程的框架. ...

  8. 《Linux内核精髓:精通Linux内核必会的75个绝技》一HACK #20 使用fio进行I/O的基准测试

    HACK #20 使用fio进行I/O的基准测试 本节介绍使用fio进行模拟各种情况的I/O基准测试的操作方法.I/O的基准测试中有无数需要考虑的因素.是I/O依次访问还是随机访问?是通过read/w ...

  9. 《Linux内核精髓:精通Linux内核必会的75个绝技》一HACK #17 如何使用ext4

    HACK #17 如何使用ext4 本节介绍ext4的编写和挂载方法.开发版ext4的使用方法.ext4是ext3的后续文件系统,从Linux 2.6.19开始使用.现在主要的发布版中多数都是采用ex ...

随机推荐

  1. C++总结:C++中的const和constexpr

    C++中的const可用于修饰变量.函数,且在不同的地方有着不同的含义,现总结如下. const的语义 C++中的const的目的是通过编译器来保证对象的常量性,强制编译器将所有可能违背const对象 ...

  2. 这是一份很详细的 Retrofit 2.0 使用教程(含实例讲解)

    前言 在Andrroid开发中,网络请求十分常用 而在Android网络请求库中,Retrofit是当下最热的一个网络请求库 今天,我将献上一份非常详细Retrofit v2.0的使用教程,希望你们会 ...

  3. Linux 常用环境搭建

    已有环境 python 2.6.6 jdk 1.7 —tomcat— —jenkins— —jq— —Python 2.7— —pip— —PIL— —Android SDK— —yum or apt ...

  4. Mysql中FIND_IN_SET和REPLACE函数简介

    一  FIND_IN_SET() SELECT * from u_user where FIND_IN_SET('32',tags) 上面的sql是精确查找,查找表中tags中含有32的记录(注意这里 ...

  5. python实现本地批量ping多个IP

    本文主要利用python的相关模块进行批量ping ,测试IP连通性. 下面看具体代码(python3): #!/usr/bin/env python#-*-coding:utf-8-*- impor ...

  6. Tornado源码分析 --- Etag实现

    Etag(URL的Entity Tag): 对于具体Etag是什么,请求流程,实现原理,这里不进行介绍,可以参考下面链接: http://www.oschina.net/question/234345 ...

  7. windows下的IO模型之事件选择(WSAEventSelect)模型

    异步选择模型类似的是,它也允许应用程序在一个或多个套接字上,接收以事件为基础的网络事件通知.对于异步选择模型采用的网络事件来说,它们均可原封不动地移植到事件选择模型.事件选择模型和异步选择模型最主要的 ...

  8. 向多页TABLE中插入数据时,新增行总是在当前页的最后一行

    CODE IN CO OATableBean table = (OATableBean)webBean.findChildRecursive("LineTable"); int n ...

  9. mac 终端 使用ftp命令

    Mac下使用命令行登陆ftp 最近使用forklift下载服务器pureftp上的东西,总是断断续续的,经常下载到99%然后显示下载失败,非常不舒服!原以为是forklift的问题,换了transmi ...

  10. IOS NSCharacterSet 去除NSString中的空格

    去除 username中的空格,table newline,nextline 代码如下: NSCharacterSet *whitespace = [NSCharacterSet  whitespac ...