《如何安装Linux内核源代码.docx》由会员分享,可在线阅读,更多相关《如何安装Linux内核源代码.docx(17页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、如何安装Linux内核源代码怎样获取Linux内核源代码下载Linux内核当然要去官方网站了,网站提供了两种文件下载,一种是完好的Linux内核,另一种是内核增量补丁,它们都是tar归档压缩包。除非你有十分的原因需要使用旧版本的Linux内核,否则你应该总是升级到最新版本。使用Git由Linus领头的内核开发队伍从几年前就开场使用Git版本控制系统管理Linux内核了参考阅读:什么是Git?,而Git项目本身也是由Linus创立的,它和传统的CVS不一样,Git是分布式的,因而它的用法和工作流程很多开发人员可能会感到很陌生,但我强烈建议使用Git下载和管理Linux内核源代码。你能够使用下面的
2、Git命令获取Linus内核代码树的最新“推送版本:$gitclonegithttpdocsj/doc/1405527f27284b73f242502b./pub/scm/linux/kernel/git/torvalds/linux-2.6.git然后使用下面的命令将你的代码树与Linus的代码树最新状态同步:$gitpull安装内核源代码内核包有GNUzipgzip和bzip2格式。Bzip2是默认和首选格式,由于它的压缩比通常比gzip更好,bzip2格式的Linux内核包一般采用linux-x.y.z.tar.bz2形式的文件名,这里的x.y.z是内核源代码的详细版本号,下载到源代码包
3、后,解压和抽取就很简单了,假如你下载的是bzip2包,运行:$tarxvjflinux-x.y.z.tar.bz2假如你下载的是gzip包,则运行:$tarxvzflinux-x.y.z.tar.gz无论执行上面哪一个命令,最后都会将源代码解压和抽取到linux-x.y.z目录下,假如你使用Git下载和管理内核源代码,你不需要下载tar包,只需要运行gitclone命令,它就会自动下载和解压。内核源代码通常都会安装到/usr/src/linux下,但在开发的时候最好不要使用这个源代码树,由于针对你的C库编译的内核版本通常也链接到这里的。应用补丁在源代码树的根目录下还有很多文件需要讲明,COPY
4、ING是内核许可描绘文件即GNUGPLv2,CREDITS是介入Linux内核的开发人员名单,MAINTAINERS列出了维护各个子系统和驱动的个人,Makefile是内核Makefile的基础。生成内核生成内核其实很简单,甚至比编译和安装其它系统级组件,如glibc还要简单,从2.6版本开场,Linux内核引入了一个新的配置和生成系统,它使生产内核的操作变得愈加简单了。配置内核既然已经拿到内核源代码,那我们在开场编译前就能够根据需要自行配置和定制,能够编译你指定的功能和想要的驱动,配置内核是生成内核必须的一步,由于内核提供了大量的功能,支持各种不同的硬件,有很多都需要配置,内核配置是由配置选
5、项控制的,配置选项都有CONFIG前缀,例如,对称多处理SMP是由CONFIG_SMP配置选项配置的,假如设置了这个选项,SMP就被启用了,反之则被禁用,配置选项能够确定会生成哪个文件,可以以通过预处理指令操控代码。配置选项能够控制生成经过要么是布尔型,要么是三态型,布尔型就是“是或“否,大部分内核配置选项都属于布尔型,如CONFIG_PREEMPT,而三态型则在“是和“否的基础上,又增加一个“模块选项,模块选项表示配置选项被设置了,但最后会编译成模块,而不是直接编译进内核,模块能够理解为可独立动态载入的对象,一般来讲,驱动配置通常都是三态型。配置选项可以以是字符串或整数,这样的选项不会控制生
6、成经过,指定的值由内核源代码访问预处理宏时使用,例如,能够为某个配置选项指定静态分配数组的大小。Linux厂商也会随发行版提供预编译的内核,如Canonical为Ubuntu,或RedHat为Fedora提供的内核,这样的内核通常只启用了需要的内核功能,几乎所有驱动都被编译成模块了,这样的内核提供了一个良好的基础内核和广泛的硬件模块支持,无论怎样,想要成为内核高手,你应该编译本人的内核。值得庆幸的是,内核提供了很多工具简化配置,最简单的工具是基于文本命令行的实用程序,如:$makeconfig这个工具会一个选项一个选项地配置,但用户需要介入,如指定“是y,“否m还是“模块m,整个配置经过需要很
7、长的时间,因而,除非是有人按小时计费请你升级内核,实在找不出别的理由用这种最原始的方法配置内核了,相反,有现成的基于ncurses的图形化工具能够代替。$makemenuconfig或是基于gtk+的图形化工具$makegconfig上述三个工具都将配置选项分成多个类别,如“处理器类型和特征,你能够在这些类别上来回移动,查看内核选项,当然可以以修改它们的设置了。下面这个命令会根据你的架构创立一个默认的配置基础。$makedefconfig固然默认配置有些武断在i386上,默认配置是由Linus配置的,但假如你从未配置过内核,它提供了一个良好的开端。配置选项存储在源代码树根目录下一个名叫.con
8、fig的文件中,你能够打开这个文件手工编辑其中的配置选项,修改后或要在新的内核源代码树上应用现有配置文件,你能够使用下面的命令验证和更新配置:$makeoldconfig在生成内核之前必须运行这个命令。配置选项CONFIG_IKCONFIG_PROC指定了完好的内核配置文件压缩包位置,默认是/proc/config.gz,这样在生成新内核时要克隆现有的配置就变得非常简单了。假如你当前的内核开启了这个选项,你能够从/proc拷贝该配置文件,然后在此基础上生成新的内核:$zcat/proc/config.gz.config$makeoldconfig内核配置好后,使用下面的命令进行生成:$make
9、和2.6以前的内核不一样,在生成内核前不再需要执行makedep命令了,依靠树会自动维护,也不需要再指定特定的生成类型,如bzImage,或独立生成模块,默认Makefile规则会自动处理好一切。将干扰信息最小化在生成经过中会遭到警告和错误的干扰。最小化干扰信息的一个窍门是重定向make的输出,但仍然会看到一些警告和错误:$make./detritus假如你想查看生成输出,你能够事后阅读这个文件,假如你完全不想看到任何输出,那么就重定向到/dev/null:$make/dev/null同时执行多个生成作业Make命令提供了一个功能能够将生成经过拆分成多个平行的作业,这些作业能够独立运行,可以以
10、并行运行,在多处理器系统上能够极大地提高生成速度,也提高了处理器利用率,由于生成大型源代码树会出现大量的I/O等待时间。默认情况下,make只能拆分成一个作业,由于Makefiles经常会包含不正确的依靠信息,假如真是这样,多个并行执行的作业将会引起混乱,最终会导致生成经过失败,假如Makefiles中的依靠信息无误,那么完全能够拆分成多个作业执行,如:$makejn这里的n表示拆分的作业数量,通常按每个处理器拆分成1-2个作业,例如,在一个16核心的机器上,你能够运行:$make-j32/dev/null使用distcc或ccache等优秀的工具可以以大大提高生成速度。安装新内核内核生成好之
11、后,你需要安装它,怎样安装于系统架构和引导加载程序有关,我们以x86架构,grub引导加载程序为例进行讲明。首先将arch/i386/boot/bzImage拷贝到/boot,重命名为vmlinuz-version,这里的version也是版本号,然后编辑/boot/grub/grub.conf,为新内核添加相应的项目,假如是使用LILO引导装载程序,则修改/etc/lilo.conf文件,然后运行lilo。模块的安装与系统架构无关,都是自动完成的,以root用户运行:%makemodules_install这个命令会将所有编译好的模块安装到/lib/modules下对应的子目录中。生成经过会
12、在源代码树根目录下创立一个System.map文件,它包含一个符号查找表,映射内核符号到它们的起始地址,在调试期间能够用它将内存地址转换成函数和变量名。可能会碰到的问题与普通用户空间的应用程序相比,Linux内核有多个特殊的属性,下面是我以为最重要的一些不同:内核既不访问C库也不访问标准C头;内核是用GNUC编码的;内核缺少用户空间提供的内存保护;内核不能容易地执行浮点运算;内核有一个小型的固定大小的进程堆栈;由于内核支持异步中断和SMP,因而同步和并发是内核主要担忧的问题;可移植性也很重要。下面我们就逐个来了解一下这些问题,所有内核开发人员都必须记住它们。无libc或标准头和用户空间应用程序
13、不一样,内核并没有链接到标准的C库,也没有链接到任何其它的库,这样设计的原因有很多,包括如先有鸡还是先有蛋的问题,但主要原因还是速度和内核大小,不要讲完好的C库,就是它的一个子集也够大,内核太大只会导致效率低下。不要担忧,很多常用的libc函数都在内核中实现了,例如,常见的字符串操作函数就位于lib/string.c中,只需要包括它的头文件就能够了。这里的头文件指的是内核源代码树中的头文件,内核也只能使用树内的头文件,基础文件位于源代码根目录的include/目录下,例如,头文件就位于include/linux/inotify.h。与架构相关的头文件则位于arch/include/asm,例如
14、,假如在x86架构下编译,与你架构相关的文件就是arch/x86/include/asm,只需要在引用这些头的地方加上asm/前缀即可,如。漏掉的大部分都是类似printf()这样的函数,内核不会使用printf(),但它提供了printk()函数,其表现绝不比printf()差,printk()会拷贝格式化的字符串到内核日志缓冲区,syslog程序就是从这里读取信息的,其用法也和printf()类似:printk(Helloworld!Astring%sandaninteger%dn,str,i);printf()和printk()之间最大的不同是,printk()允许你指定一个优先级标记,
15、syslogd使用这个标记确定在哪里显示内核消息,下面是一个使用优先级标记的示例:printk(KERN_ERRthisisanerror!n);注意在KERN_ERR和打印的消息之间没有逗号,这是成心这么设计的,优先级使用一个预定义的字符定义,在编译期间它与打印的信息是串联的。GNUC和很多Unix内核类似,Linux内核也是用C编写的,但也许会让人很意外,内核不是用严谨的ANSIC编写的,内核开发人员用的却是gccGNU编译器集,包含了编译内核和LinuxC程序的C编译器中的各种语言扩展。内核开发人员同时使用了C语言的ISOC99和GNUC扩展,这些变化让Linux内核与gcc结合得更严密
16、,但近期又出现了一个编译器英特尔的C编译器也对gcc的功能支持得相当好,因而可以以用它来编译Linux内核。最低支持的gcc版本是3.2,建议采用gcc4.4或更高的版本编译。使用ISOC99扩展也是能够的,由于C99是C语言的官方版本。内联函数C99和GNUC都支持内联函数,内联函数是直接插入到每个函数调用的位置的,消除了函数调用和返回的开销,允许进一步优化,由于编译器能够同时优化调用者和被调用函数,但它也有缺点,代码大小会增加,由于函数的内容被直接复制到所调用者内部了,因而也会增加内存消耗和指令缓存空间。内核开发人员一般在小型时间很关键的函数中才会使用内联函数。定义函数时,使用static
17、和inline关键字声明内联函数,例如:staticinlinevoidwolf(unsignedlongtail_size)函数必须先声明后使用,否则编译器就不能使函数内联,一般做法是将内联函数放在头文件中,由于它们被标记为static,不会创立输出函数,假如内联函数仅在一个文件中使用,能够放在该文件的顶部。在内核中,与复杂的宏相比,出于安全和可读性方面考虑,内联函数是首选。内联汇编GccC编译器允许在C函数中嵌入汇编指令,asm()编译器指令用于内联汇编代码,例如,这个内联汇编指令执行x86处理器的rdtsc指令,返回时间戳寄存器tsc的值:unsignedintlow,high;asmv
18、olatile(rdtsc:=a(low),=d(high);/*lowandhighnowcontainthelowerandupper32-bitsofthe64-bittsc*/Linux内核是用C和汇编语言混合编写的,与底层硬件相关的代码很多都是用汇编语言写的,剩下的大部分内核代码都是直接用C编写的。分支注解GccC编译器内置了一个指令优化条件分支,内核将这个打包成易于使用的宏-likely()和unlikely()。先看下面这样的if语句:if(error)/*.*/将这个分支标记为非常不可能采用/*wepredicterrorisnearlyalwayszero.*/if(unli
19、kely(error)/*.*/相反,将这个分支标记为非常可能采用/*wepredictsuccessisnearlyalwaysnonzero.*/if(likely(success)/*.*/当分支指令已经知道一个优先级,或你想在一种情况下优化另一种情况时应该使用上述指令,最重要的是,当分支正确标记时,这些指令会提升性能,但假如分支标记错误则会降低性能,在内核代码中,unlikely()要使用得更多,由于if语句倾向于表示一种特殊情况。无内存保护当用户空间的应用程序尝试一个非法的内存访问时,内核能够捕捉到错误,发送SIGSEGV信号,杀掉进程,假如内核尝试一个非法的内存访问时,结果就不受控
20、制了,由于谁也无法去控制内核,这也是内核最主要的失误。此外,内核内存也是不可分页的,因而你消耗的每个内存字节都比物理内存的一个字节要少。不能容易使用浮点数当用户空间进程使用浮点指令时,内核要负责处理从整型到浮点形式的转换。与用户空间不一样,内核不能无缝支持浮点数,由于它本人不能轻易地捕捉到本人,在内核中使用浮点数需要手动保存和恢复浮点数寄存器,因而除非却有必要,否则尽量不要在内核中做浮点运算。小型,固定大小的堆栈用户空间能够静态分配很多不同的堆栈,包括巨型构造和千元数组,这个行为是合法的,由于用户空间有很大的堆栈,并能够动态增长。内核堆栈不大也不是动态的,相反,它很小且是固定的,内核堆栈的准确
21、大小根据架构有所不同,在x86上,堆栈大小是在编译时确定的,一般是4KB或8KB,历史上,内核堆栈有2页,通常表示它处于32位架构上,大小是8KB,假如是16KB就表示是64位架构,总之大小是固定的,每个进程接收它本人的堆栈。同步和并发内核最容易受竞争条件影响,和一个单线程的用户空间应用程序不一样,有很多内核特性允许同时访问分享资源,因而需要同步以防止竞争,十分是:Linux是一种抢占式多任务操作系统,进程是由内核的进程调度器随意调度和再次调度的,内核必须在这些任务之间同步;Linux支持对称多处理SMP,因而,假如没有适当的保护,在两个或多个处理器上同时执行的内核代码可能会同时访问一样的资源;中断是异步发生的,因而,假如没有适当的保护,在访问资源期间可以能发生中断,中断处理程序可能就会访问到一样的资源;Linux是有优先权的,因而,假如没有适当的保护,内核代码可能会优先执行,访问其它代码正在使用的资源。解决这些问题的一般方法是自旋锁和信号量。可移植性的重要性固然用户空间应用程序一般不会太重视可移植性,但Linux确实是一个可移植性操作系统,应该保持一致,这意味着与架构无关的C代码必须在大量的系统上正确地编译和运行,与架构相关的代码必须在内核源代码树中使用特定的目录分隔开。