查看完整版本: linux kernel 编译新手指南

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

很长的帖子!!!!!帮你顶!!!!
页: [1]
查看完整版本: linux kernel 编译新手指南