shukai0414 2008-4-15 11:29
linux kernel 编译新手指南
在正式介绍之前先作几点声明:
1)由于linux内核实在是太庞大了 涉及的内容包罗万象 我自己的水平也很有限 所以我不可能将内核配置的方方面面都写出来 本文中我只是将我认为最重要的一些部分作一个介绍 当然 仁者见仁 智者见智 也许我认为重要的其他人不觉得重要 反之亦然 所以欢迎大家对本文进行补充 也欢迎大家对错误之处进行指正
2)本文介绍的内核配置是针对i386体系结构 对其它体系结构不完全适用(当然大部分也适用)
3)本文在介绍内核配置的过程中假设你的linux是以桌面应用为主要目的 也就是说我对内核配置的推荐做法都是在保证系统吞吐量(throughput)的情况下尽最大可能性来提高系统的响应能力(responsiveness)
4)本文仅仅针对2.6.x内核 参考的内核是2.6.20
5)本文只介绍对内核的配置 并不会介绍如何从头到尾编译出一个内核 因此请对编译内核的步骤还不太清楚的弟兄们先参考一些相关的文章
6) 参考书籍《LINUX内核编程》
7)是否写名出处属于个人意愿 我也不想让别人一定要知道文章谁写的 重点的是文章对你是否有用
本文所指的内核配置其实最核心的东西就是一个文件 这个文件名为.config 位于内核源码的根目录下 这个文件在你刚刚将内核源码解压缩后并不存在 需要你进行过一次配置后才会产生出来 这个文件是一个文本文件 里面有许多行信息 这些信息决定了在你编译内核的时候要支持哪些特性以及哪些模块 下面举两个例子 比如在我的.config文件中有一行为:CONFIG_SMP=y 这就表示我编译的内核要支持对称多处理器(Symmetricmulti-processing) 这意味着在编译内核的c文件时会定义一个叫CONFIG_SMP的宏;另外还有一行:CONFIG_NTFS_FS=m 这一行表示编译内核的过程中要编译出一个支持NTFS文件系统的可加载内核模块(LKM loadable kernelmodule)
上面的例子中提到了可加载内核模块(LKM loadable kernel module)的概念 我在这里有必要对这个概念进行一些介绍 首先说linux是单内核(monolithic kernel)结构的 linux编译后可以视为一个大的程序 这个程序为所有的调用者提供服务(当然 内核中还有许多的内核线程在运转着) 那么凡是需要支持的功能(比如对某种硬件的支持)都应该编译进内核的镜像中去 但世界上有成千上万种硬件设备 如果把支持它们的程序都编译进内核镜像中去会导致内核过于庞大 而且这些设备并不是在每台机器上都有 实际上常用的也就那么几十种而已 把它们都编译进内核镜像也会造成大量的浪费 所以内核的开发者们设计出一种能够动态地增加内核功能的机制---可加载内核模块(LKM loadable kernelmodule 本文以后简称LKM) LKM可以在需要的时候动态地加载到内核中去 一旦加载上就成为了内核的一部分 从而扩展了原有内核的功能(读者可以用/sbin/lsmod来观看系统中有哪些LKM被加载了) 上面提到的CONFIG_NTFS_FS=m会使编译内核的工具将支持NTFS文件系统的程序编译为一个LKM 如果将这一句话改为CONFIG_NTFS_FS=y那么就会使得实现NTFS文件系统的程序被直接编译到内核的镜像中去
总体来讲 内核配置的过程就是编辑.config文件的过程 当然你可以用任何一个文本编辑器来手工编辑.config文件 不过如果真的决定这样做 我只能说愿佛祖保佑你 在.config文件中可以编辑的条目达数千之多 为了简化编辑过程 内核的开发者们开发出了一些工具专门用于编辑.config文件 这些工具都附带在内核的源码压缩包中 但是这些工具在第一次使用的时候要进行编译才能使用(因为linux内核源码包不能直接将binary的文件打进去 毕竟它要在各种硬件平台下使用) 因此使用这些工具之前 你的linux必须安装相应的开发环境 比如GTK或者QT的开发环境 关于如何安装这些环境许多文章都讲过 我就不赘述了 这几个工具都可以在内核源码的根目录下通过输入make xxx命令的方法来调用 下面分别介绍
1)menuconfig 调用命令:sudo make menuconfig 这是一个字符界面的配置工具 虽然是字符界面但也提供了简单的菜单界面 它的好处是可以在没有X Window的环境下对内核进行配置 该工具需要libncurses的开发环境
2)qconf 调用命令:sudo make xconfig 这是一个GUI的配置工具 基于QT 这个工具非常直观易用 大家一看就明白怎么用 要求具备QT的开发环境
3)gconf 调用命令:sudo make gconfig 与上面的相似 只不过基于GTK 所以要求GTK开发环境
这三个工具我推荐使用qconf 因为menuconfig不够直观 gconf我觉得有bug 而且在最新的2.6.20内核中的gconf我没能成功地使用起来 它总是会弹出一个空的窗体然后就没响应了 不知道是为什么
在使用上面提到的工具进行配置前你一定要准备一个.config文件的模板 因为.config文件中可以编辑的条目太多了 大部分都是与驱动程序相关的 如果你一项一项地进行配置需要花费大量的精力(坦白地讲 我也没有过这种经历 因为驱动程序太多了 我也不知道哪些有用哪些没用) 因此在配置之前 你应该找到一份模板 然后集中精力编辑一些比较重要的配置条目 linux的/boot目录下就有一些很好的模板 比如/boot/config-2.6.17-11-generic 你只要把这样的文件copy到你的内核源码根目录下并更名为.config即可 另外 注意在qconf中 大多数条目都可以有三种状态:打上对勾 打上圆点 无勾选 这三种状态分别对应.config文件中的=y =m =n 也即直接编译进内核镜像 编译为LKM 不定义宏或不编译
下面我就将我认为重要的配置条目逐一地向大家介绍(大部分都与桌面性能相关) 下面每个条目的名称以它在gconf菜单中的全路径表示
1)General setup-->Cpuset support:
该条目为y或者n 为y时定义CONFIG_CPUSETS宏 建议不勾选这项 因为这个特性是主要是用于NUMA架构和拥有大量逻辑CPU的SMP架构 开启这一特性会浪费一些内存 对一般人的桌面环境没有任何帮助
2)Processor type and features-->Symmetric multi-processing support:
该条目为y或者n 为y时定义CONFIG_SMP宏 勾选这一项使得内核支持对称多处理器 建议勾选 因为最新的CPU大多支持双核或者超线程 就算你现在是单CPU 难保你哪天升级:)
3)Processor type and features-->Processor family
这是一个单选条目 目的是为了指定CPU的具体型号以便进行优化 应该慎重选择 选错有可能造成内核无法正常工作 举个例子来说明这个选项的优化作用 比如你选中了Athlon/Duron/K7 那么内核在进行memcpy()的时候就会使用经过3DNow!指令集优化过的版本 下面我大致把市面上常见的CPU应该选哪项做一个粗糙地分类:
针对AMD的CPU:
a)Sempron(闪龙)/Duron(毒龙)/Athlon(速龙):选择Athlon/Duron/K7
b)Sempron64/Athlon64/Athlon64 X 2/Opteron(皓龙):选择Opteron/Athlon64/Hammer/K8
c)比上述CPU都古老的:选择K6/K6-II/K6-III (当然如果你的CPU是K5的就得选586/K5/5x86/6x86/6x86MX了 )
针对INTEL的CPU:
a)奔腾2:选择Pentium-II/Celeron(pre-Coppermine)
b)奔腾3:选择Pentium-III/Celeron(Coppermine)/Pentium-III Xeon
c)奔腾4/奔腾D/赛扬D:选择Pentium-4/Celeron(P4-based)/Pentium-4 M/older Xeon
d)酷睿2:选择Core 2/newer Xeon
注意:如果你的CPU是赛扬(赛扬D除外) 你必须先确认它到底是基于P2 P3还是P4的 一般来讲主频高于1G的是基于P4的 高于500M但小于1G的是基于P3的 其它的是基于P2的 另外 志强处理器你也要区分是基于P3 P4或者是Core 2
4)Processor type and features-->Generic x86 support
该条目为y或者n 为y时定义CONFIG_X86_GENERIC宏 目的是针对x86体系结构进行一般优化 比如 当CONFIG_X86_GENERIC宏定义的情况下(当然CONFIG_X86_TSC宏也要定义 这个取决于前面Processor family的选择 ) 内核中的get_cycles()函数会使用TSC(timestamp counter)获取cycles值 这个选项一定要勾选上
5)Processor type and features-->Maximum number of CPUs
这个条目是一个数字的宏(NR_CPUS 范围为2-255) 该数字决定内核最多支持的逻辑CPU数量 恰当地设定该数字可以使你的内核节省一些内存 这是因为内核中有许多数据结构是根据NR_CPUS的大小来固定分配空间的 即使你现有的逻辑CPU少于NR_CPUS 这些空间也会被分配出来从而造成浪费 如何确定你有多少个逻辑CPU呢?举例来说吧:比如你的系统是单CPU 但是支持超线程(Hyper-threading) 那么逻辑CPU数量为2;再比如说你的系统是双CPU 每个CPU又支持双核 那么逻辑CPU数量为4 一般来说 大家应该把这个数值设定为大于等于你系统的逻辑CPU数 考虑到大多数人应该还是使用单CPU系统 我推荐大家将这个值设定为4 因为目前个别INTEL的CPU同时支持双核与超线程 另外INTEL还推出了四核心的CPU AMD应该也会很快推出四核心CPU 所以将这个值设定为4是为了给不久的未来上个保险同时对于少于4个逻辑CPU的朋友又不会浪费你太多的内存
6)Processor type and features-->SMT (Hyperthreading) scheduler support
该条目为y或者n 为y时定义CONFIG_SCHED_SMT宏 定义它的目的是为了对支持超线程的CPU提供能好的调度功能 我举例说明一下:比如一个系统有两个CPU 每个CPU又支持超线程 那么系统中有四个逻辑CPU 我们将这个四个CPU记为C00 C01 C10 C11 其中C00与C01是一个物理CPU上的两个硬件线程 而C10与C11则是另一个物理CPU上的两个硬件线程 假设某一个时刻系统中有两个线程在执行 在没有定义CONFIG_SCHED_SMT宏的情况下内核很可能会将这两个线程分别调度到C00与C01上去 但这是不优化的 因为C00与C01是一个物理CPU上的两个硬件线程 它们共享了许多硬件资源 导致两个线程运行时并不能充分发挥这个系统的资源优势;而定义了CONFIG_SCHED_SMT宏的情况下 内核的调度器就会将这两个线程调度到位于不同物理CPU的逻辑CPU上 比如C00与C10上
乍一看似乎只要你的CPU支持超线程 那么你就应该勾选这一项 但是我认为并不一定这样 比如你的系统是单CPU并且支持超线程 那么这个时候CONFIG_SCHED_SMT宏对于提高调度效果并没有什么意义(当然前提是我对内核调度器的理解无误的话:)) 而且定义CONFIG_SCHED_SMT宏还会对调度增加额外的开销
我的建议是:在你的CPU支持超线程的前提下 只有当你的系统有多个CPU或者支持多核的时候才有必要勾选这一项
7)Processor type and features-->Multi-core scheduler support
该条目为y或者n 为y时定义CONFIG_SCHED_MC宏 它的作用很类似于前面提到的CONFIG_SCHED_SMT 只不过它针对多核(multi-core) 我的建议是只有你的系统拥有多个物理CPU时才有必要勾选 比如我家里的机器CPU为单AMD Athlon 64 X24200+ 虽然是双核 但只有一个物理CPU 我就没有必要定义这个宏
8)Processor type and features-->Preemption Model
这是一个单选条目 它是一条对桌面响应能力有很重要意义的选项 我强烈建议大家选择Preemptible Kernel(Low-Latency Desktop) 选中这项会定义CONFIG_PREEMPT宏 表示该内核将支持抢占式内核(Preemptible Kernel )特性 为了突出它的重要性 我下面通过一个例子简单介绍一下抢占式内核的概念:假设某系统中(假定只有一个逻辑CPU)有两个线程在运行 一个叫线程H 一个叫线程L 线程H的动态优先级要比线程L高 在某一时刻 线程H由于等待键盘响应进入了阻塞状态 这时内核将会调度线程L将其投入运行 而再假设在线程L运行的过程中由于某种原因进入了内核空间(这里主要指由于系统调用或者异常) 而恰巧在L进入了内核之后用户按下了键盘 键盘中断导致线程H从阻塞状态进入了就绪状态 那么按照正常的逻辑此时应该立刻将CPU交给线程H(因为线程H的动态优先级高) 从而让线程H立刻进行用户按键后的操作处理 这个时候 如果系统支持抢占式内核特性的话 那么linux确实会像刚才的逻辑那样做 但是如果不支持抢占式内核特性的话 那么线程H将无法立刻得到执行 它必须要等到线程L完成了在内核空间中的所有工作并返回用户空间的前一刻才能得到调度 这就会对线程H造成一个调度上的延迟 这种延迟最大可能达到几百毫秒之多 而几百毫秒的延时可能让人产生响应迟钝的感觉 因此对于以响应能力为重要指标的桌面系统来说 抢占式内核特性是很重要的(据我所知windows与mac osx的内核都属于抢占式内核) 因此极力建议大家选中这项
抢占式内核特性是从2.6.x内核开始有的 我从fedora core 2一直到fedora core 6以及linux6.10自己编译的内核都开启这个特性 从来没有遇到过任何稳定性方面的问题 所以请大家放心 另外 再多说一句 不要把抢占式内核与抢占式多任务(preemptive multitasking)混为一谈 linux从最开始就是支持抢占式多任务的
9)Processor type and features-->Preempt The Big Kernel Lock
该条目为y或者n 为y时定义CONFIG_PREEMPT_BKL宏 定义该宏是为了在某线程占有大内核锁(BigKernel Lock)的时候仍然可以被其它高优先级线程抢占调度 这个特性同样是为了提高桌面系统的响应能力 建议勾选
10)Processor type and features-->High Memory Support
这是一个单选条目 目的是用于配置linux内核对high memory的支持 这个条目解释起来比较麻烦 我就不细说了 我的建议是:如果你的物理内存小于等于896MB 并且在短期内没有升级内存的可能性的话 你就选择off;如果内存大于896MB或者说有可能升级到大于896MB内存的话 并且小于4GB 那么选择4GB;如果你的内存大于4GB的话 原则上你应该选择64GB 但是为了充分利用你的系统资源 这种情况我还是建议你安装x86_64版本的linux
11)Processor type and features-->Allocate 3rd-level pagetables from highmem
该条目为y或者n 为y时定义CONFIG_HIGHPTE宏 这个宏的功能解释起来也比较麻烦 我也就不细说了 但注意这个宏只有在前一条目选择了4GB或者64GB才有意义 我的建议是:如果你的物理内存数量超出896MB不是很多的时候就不要选中这项 比如说只有1GB内存的时候就我觉得就没有必要选;但如果超出很多就有必要选中 比如说2GB内存的时候
12)Processor type and features-->Timer frequency
这又是一个单选条目 选择完成后最终会定义一个叫HZ的宏 这是一个数字宏 目前在2.6.20内核中这个数字可以为100 250 300与1000四种 这个数字决定了每秒钟时钟中断发生的次数 每次时钟中断要处理许多事情 但就桌面性能来说 它的频率决定了内核定时器与用户空间定时器的精度 这个数字越大 定时器的精度就越高 而用于处理定时器中断所造成的开销也就越大 不过为了提高桌面系统的多媒体性能 我建议大家将这一条目选择为1000HZ 当然 如果你觉得自己的CPU性能不够高 也可以考虑选择HZ_250或者HZ_300(当然 性能够不够高没有一个绝对的准绳 我觉的凡是主频高于1G的CPU选则1000 HZ是毫无问题的 )
13) File systems-->Ext3 journalling file system support
该条目为y m或者是n 这个条目决定了内核对Ext3文件系统的支持 前面提到过y/m/n三者的含义 我的建议是:如果大家大量使用Ext3文件系统的话 那么选则y(也就是在qconf中打上对勾 即把Ext3的支持代码直接编译进内核镜像);否则的话 选则m(也就是在qconf中打上圆点 即把Ext3的支持代码编译成一个LKM)
那么为什么在大量使用Ext3的时候就选择y呢?这是因为LKM在需要的时候会被加载到内核空间的非线性映射区域 这块区域的页表是动态的 需要在不同的进程之间进行同步 而且一旦进程发生了切换之后 描述这一区域的页表项的缓存(TLB)将会被flush掉 从而导致进程切换后访问相同LKM的性能有所降低;而如果直接将代码编译进内核镜像的话 这些代码将会位于内核空间的线性映射区域 而这块区域的页表项是全局的 其缓存不会在进程切换后被flush掉 从而提高了性能
同理 如果你大量使用其它文件系统(比如Reiserfs)的话 你也可以将相应的条目选择为y
14)File systems-->DOS/FAT/NT Filesystems-->NTFS file system support
该条目为y m或者是n 这个条目与桌面性能倒是没有什么关系 只不过我估计大多数人都是linux/windows双系统 为了能够访问NTFS文件系统 记得要将这一项选择为m或者y 另外 值得一提的是:这个条目下面还有一个子条目NTFS file systemsupport 这个条目只能为y或者n 为y时定义NTFS_RW宏 定义该宏使得该模块支持对NTFS文件系统的写入操作 请注意 对于早期的2.6.x内核来说 这种写入操作是不安全的;而在2.6.20里面说现在写操作已经安全了 但是只能写已经存在了的文件 而且文件长度还不能改变 这样一来用处也不大了 所以我建议不要选中这个条目
15)Kernel hacking-->Kernel debugging-->Use 4Kb for kernel stacks instead of 8Kb
该条目为y或者n 为y时定义CONFIG_4KSTACKS宏 这个特性是将每个线程的核心堆栈从8Kb减少到4Kb 而发生外部中断时则给每个逻辑CPU准备一个IRQ stack以补偿核心堆栈减小带来的损失 这个特性的好处是在系统中有大量线程存在时降低了内存的使用量 另外更重要的是由于i386体系结构一个页面的大小就是4Kb 每次分配4Kb会减少内核中page allocator分配页面时造成的内存碎片效果;它的坏处是发生中断时会有切换堆栈的额外操作发生 我只建议内存比较少又需要同时运行大量线程的朋友开启这个选项
写到这里 我能想到的比较重要的条目也就都罗列出来了 我深深感到自己对linux内核的了解还远远不够 尤其是对于具体设备的配置方面我没能写出一个有用的建议 深感惭愧!另外 请注意 其实还有很多也必须要选择的条目我并没有罗列出来(比如说General setup-->Configure standard kernelfeatures (for small systems)-->Enable futex support) 但是这些条目或者与桌面性能关系不大 或者在前面提到的.config文件模板中几乎肯定已经选中了 所以我也就不提了
其实写本文的主要目的只是给新手一个参考。。。。
zhangqi0342 2008-4-21 12:13
很长的帖子!!!!!帮你顶!!!!