本节书摘来自异步社区《Linux内核修炼之道》一书中的第2章,第2.1节,作者:华清远见嵌入式培训中心 任桥伟著,更多章节内容可以访问云栖社区“异步社区”公众号查看
第2章 配置与编译内核
如果你对Linux的兴趣仅是止于上上网、听听歌、看看碟,那么这里的内容或许并不适合你。如果你稍微有那么一点点的好奇心,希望能够体验一下新的特性、新的内核版本,懂得如何配置与编译内核都是必须的。
2.1 配置内核
Linux内核修炼之道
编译内核的第一步就是配置内核,这是增加或减少对一些内核特性的支持的必要步骤,比如,可以为内核添加对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支持。