Linux Kernel in a Nutshell 笔记(二)

3.Retrieving the Kernel Source
4.Configuring and Building

过去,kernel 被划分为两棵树,"development" 和 "stable" branch,前者的发行版号的第二位是奇数,而后者是偶数,2.5.25 就是 development 版本,2.4.25 则是稳定版本。但是自从 2.6 版本之后,内核开发不再区分这两种情况,而统一称为 "stable"。kernel team 发行版了 2.6.17 版本,接着开发人员继续开发新的功能,将其命名为 2.6.18-rc1,2.6.18-rs2 等,直到成熟了变为 2.6.18,而原来的 2.6.17 版本则由于各种 bug 的修复已经安全等升级变为 2.6.17.1,2.6.17.2 等版本。

下载源码文件:
$ wget -nd -r -b ftp://ftp.kernel.org/pub/linux/kernel/v2.6/longterm/v2.6.32/linux-2.6.32.28.tar.gz
$ mkdir ~/linux
$ mv linxu-2.6.32.28.tar.gz linux; cd linux
$ tar zxvf *tgz.gz

接下来需要生成内核配置文件 .config,在刚刚解压下来的 linux-2.6.32.28/ 目录下,并没有 .config 文件,因此需要我们创建。可以 "白手起家",根据默认配置创建,从当前运行的 kernel 创建或者从一个发行版本的 kernel 中获取,这里先涉及前两种方式。

从头还是创建:
[email protected]:~/linux$ pwd
/home/jaseywang/linux
[email protected]:~/linux$ ls
linux-2.6.32.28  linux-2.6.32.28.tar.gz
[email protected]:~/linux$ cd linux-2.6.32.28/
[email protected]:~/linux/linux-2.6.32.28$ make config
scripts/kconfig/conf arch/x86/Kconfig
#
# using defaults found in /boot/config-2.6.32.59+drm33.24
#
/boot/config-2.6.32.59+drm33.24:3314:warning: symbol value 'm' invalid for FB_VESA
*
* Linux Kernel Configuration
*
*
* General setup
*
Prompt for development and/or incomplete code/drivers (EXPERIMENTAL) [Y/n/?]

接下来你就需要回答将近 2000 项的 y/n/m,其中 y 代表将其嵌入到 kernel 中,n 代表不包含在 kernel 中,m 代表以模块的形式安装,? 表示 help。如果这样一条一条的选择下去,天都黑了,所有有底下这个方式,根据先前已经建立好的配置文件来进行。

每个内核文件都有一个默认的配置选项,该选项一般是内核维护者自己电脑的配置,比如对于 i368 的架构,该默认配置就是 linus 自己的开发机器的配置:
[email protected]:~/linux/linux-2.6.32.28$ make defconfig
*** Default configuration is based on 'x86_64_defconfig'
#
# configuration written to .config
#

最终会生成一个 .config 文件,但是最好根据自己的机器来进行适当的针对本级的修改。
[email protected]:~/linux/linux-2.6.32.28$ ll .config
-rw-r–r– 1 jaseywang jaseywang     67801 2012-04-30 23:14 .config

上面基本的配置文件已经产生了,接下来需要根据本机来进行定制了。有三种方式,terminal-based 的 menuconfig,GTK+ 的 gconfig,QT 的 xconfig。一般用的最多的就是第一个了。这需要下列包的支持:
$ sudo apt-get install  libncurses5 libncurses5-dev
$ make menuconfig

进去之后的东西就繁杂多了,在此不展开,所有的选项确认之后,两次 Esc 退出,保存 .config 文件。现在 linux-2.6.32.28/ 下的 .config 是最新的的文件,而原来的文件则变为 .config.old,比如我通过 menuconfig 增加了 oprofile 功能,diff 一下:
[email protected]:~/linux/linux-2.6.32.28$ diff .config .config.old
4c4
< # Tue May  1 00:11:00 2012

> # Mon Apr 30 23:14:09 2012
170,172c170
< CONFIG_OPROFILE=m
< # CONFIG_OPROFILE_IBS is not set
< # CONFIG_OPROFILE_EVENT_MULTIPLEX is not set

> # CONFIG_OPROFILE is not set
2428d2425
< CONFIG_RING_BUFFER_ALLOW_SWAP=y

现在就可以 build kernel 了:
$ make

技巧:

1.可以启用多线程的方式来编译,通过 -j 选项,一般 -j 后面接的数字是你 core 的两倍,看你目前机器的 processor:
$ cat /proc/cpuinfo  | grep processor | wc -l
16
按上面的公式,我 -j 后面的数值就应该是 32 了。
$ make  -j32

2.编译内核的一部分
如果只想编译内核的某一个单独的目录,可以像下面这样:
$ make drivers/usb/serial

如果想将模块编译到那个目录下,需要这样:
$ make M=drivers/usb/serial

3.输出不在当前目录
比如你当前的源码在 /mnt/cdrom/linux-2.6.32.28/ 下面,现在需要将其输出到 ~/linux/2.6.32.28/ 下:
$ make O=~/linux/2.6.32.38/

[email protected]:~/linux/linux-2.6.32.28$ make defconfig O=/tmp/linux
  HOSTCC  scripts/basic/fixdep
  HOSTCC  scripts/basic/docproc
  HOSTCC  scripts/basic/hash
  GEN     /tmp/linux/Makefile
  HOSTCC  scripts/kconfig/conf.o
/home/jaseywang/linux/linux-2.6.32.28/scripts/kconfig/conf.c: In function ‘conf_askvalue’:
/home/jaseywang/linux/linux-2.6.32.28/scripts/kconfig/conf.c:105: warning: ignoring return value of ‘fgets’, declared with attribute warn_unused_result
/home/jaseywang/linux/linux-2.6.32.28/scripts/kconfig/conf.c: In function ‘conf_choice’:
/home/jaseywang/linux/linux-2.6.32.28/scripts/kconfig/conf.c:307: warning: ignoring return value of ‘fgets’, declared with attribute warn_unused_result
  HOSTCC  scripts/kconfig/kxgettext.o
  HOSTCC  scripts/kconfig/zconf.tab.o
  HOSTLD  scripts/kconfig/conf
*** Default configuration is based on 'x86_64_defconfig'
#
# configuration written to .config
#

[email protected]:~/linux/linux-2.6.32.28$ ls -a /tmp/linux/
.  ..  .config  include  Makefile  scripts  source

[email protected]:~/linux/linux-2.6.32.28$ make -j32 O=/tmp/linux

  OBJCOPY arch/x86/boot/vmlinux.bin
  AS      arch/x86/boot/header.o
  LD      arch/x86/boot/setup.elf
  OBJCOPY arch/x86/boot/setup.bin
  BUILD   arch/x86/boot/bzImage
Root device is (8, 5)
Setup is 12028 bytes (padded to 12288 bytes).
System is 3997 kB
CRC f505cbee
Kernel: arch/x86/boot/bzImage is ready  (#1)

[email protected]:~/linux/linux-2.6.32.28$ ls /tmp/linux/
arch   crypto   firmware  include   init  kernel  Makefile  modules.order   net      security  source      usr      vmlinux.o
block  drivers  fs        include2  ipc   lib     mm        Module.symvers  scripts  sound     System.map  vmlinux

4.Different Arch
可以在当前系统上指定编译不同架构平台的 kernel,即交叉编译:
$ make ARCH=arm CROSS_COMPILE=/usr/local/bin/arm-linux-