linux内核设计与实现---从内核出发

1 获取内核源码

在linux内核官方网站http://www.kernel.org,可以获得当前最新版本Linux源码码。如果想找一些老版本的源代码,可以:https://mirrors.edge.kernel.org/pub/linux/kernel/下载。

安装内核源代码

内核压缩以GNU zip(gzip)和bzip2两种形式发布。以bzip2形式发布的Linux内核叫做linux-x.y.z.tar.bz2,这里x.y.z是内核源码的具体版本。如果压缩形式是bzip2,则运行:

tar rvjf linux-x.y.z.tar.bz2

如果压缩形式是GNU的zip,则运行:

tar xvzf linux-x.y.z.tar.gz

何处安装源码

内核源码一般安装在/usr/src/具体linux版本 目录下。不要以root身份对内核进行修改,而应当是,建立自己的主目录。仅以root身份安装新内核,即使在安装新内核时,/usr/src/linux目录都应当原封不动。

使用补丁

在linu内核社区中,补丁是通用语。你可以以补丁的形式发布对代码的修改,也可以以补丁的形式接收其他人所做的修改。内核版本不断更新,增量补丁可以作为版本转移的桥梁。你不在需要下载内核源码的全部压缩,而只需给旧版本打上一个增量补丁,让其旧貌换新颜,更新内核版本。只需运行:

patch-p1 < ../patch-x.y.z

一般来说,一个给定版本的内核补丁总是打在前一个版本上。

2 内核源码树

内核源码树由很多目录组成,而大多数目录又包含更多子目录。源码树的根目录及其子目录如下表:

目录描述
arch特定体系结构的源码
cryptoCrypto API
Documentation内核源码文档
drivers设备驱动程序
fsVFS和各种文件系统
include内核头文件
init内核引导和初始化
ipc进程间通信代码
kernel像调度程序这样的核心子系统
lib通用内核函数
mm内存管理子系统和VM
net网络子系统
scrripts编译内核所用的脚本
securityLinux安全模块
sound语音子系统
usr早期用户空间代码

在源码树根目录中,COPYING是内核许可证,CREDITS是开发者列表。MAINTAINERS是维护者列表,维护内核子系统和驱动程序。最后,Makefile是Makefile内核的基础

3 编译内核

在编译内核之前,首先你必须配置它。可以配置的各种选项,以CONFIG_FEATURE形式表示,其前缀为CONFIG。例如,对称处理器(SMP)的配置选项为CONFIG_SMP。如果设置了该选项,则SMP启用,否则,SMP不起作用。
这些配置项要么是二选一,要么是三选一。二选一就是yes或no。三选一可以是yes、no或module。module意味着该配置项被选定了,但编译的时候这部分功能的实现代码是以模块(一种可以动态安装的独立代码段)的形式生成。在三选一的情况下,yes表示把代码编译进内核映射中,而不是作为一个模块。

内核提供了各种不同的工具来简化内核配置。最简单的一种是基于文本的命令行工具:

make config

该工具会挨个遍历所有配置项,要求用户选择yes、no或module。
在这里插入图片描述
如果该命令不能执行,说明没有安装一些工具,可以根据提示安装,我的需要安装make、gcc、bison、flex

sudo apt-get install make gcc bison flex

这个过程很耗费时间,所以,除非你的工作是按小时计费的,否则你应该多利用基于ncuse编译的图形界面工具。

make menuconfig

或者基于X11的图形工具

make xconfig

或用基于gtk+图形工具

make gconfig

这三种工具将所有配置项分门别类放置,比如按处理器类别和特点,你可以按类移动、浏览内核选项,当然也可以修改其值。
命令:

make defconfig

通过这条命令为你的体系结构创建一个默认的配置。尽管这些默认值有点随意性,但是,如果你从未配置过内核,那就会提供一个良好的开端。
在这里插入图片描述
执行完,帮我配置的是x86_64_defconfig。这些配置项会存放在内核代码树根目录下的.config文件中,我们也可修改它,打开看看
在这里插入图片描述
再修改过配置文件之后,或者在用旧的配置文件配置新的代码树的时候,应该验证和更新配置:

make oldconfig

一旦内核配置好了,就可以编译它了,执行命令:

make

在这里插入图片描述

减少编译的垃圾信息

我们希望在编译时看到错误和警告消息,但对匆匆掠过屏幕的垃圾信息不感兴趣,可以使用如下命令

make > /dev/null

就可以把无用的输出信息重定向到永无返回值的黑洞/dev/null

衍生多个编译作业

多个作业独立并发运行,可以提高处理器系统上的编译过程。默认情况下,make只衍生一个作业。为了可以以多个作业编译内核,使用一下命令:

make -jn

n是要衍生的作业数,在实际中,每个处理器一般衍生一个或者两个作业。例如,在一个双处理器上,可以输入如下命令:

make -j4

安装内核

在内核编译好了之后,还需要安装它。怎么安装就和体系架构以及启动引导工具(boot loader)息息相关了—查阅启动引导工具的说明,按照它的指导将内核映像拷贝到合适的位置,并且按照启动要求安装它。一定要保证随时有一个或两个可以启动的内核,以放新编译的内核出现问题。
安装命令:

sudo  make install

模块的安装是自动的,也是独立于体系结构的。以root身份,只要运行:

sudo make modules_install

就可以把所有编译号的模块安装到正确的主目录/lib下
在这里插入图片描述
在这里插入图片描述
可以看到,编译的内核版本号是5.0.0
在这里插入图片描述
同时也列出了还有那个内核
在这里插入图片描述
查看现在使用的内核版本
在这里插入图片描述

启用指定内核作为引导

输入下列命令将内核作为引导,将数字更改为你自己编译的版本号:

sudo  update-initramfs -c -k 5.0.0

在这里插入图片描述
跟新一下grub:

sudo update-grub

在这里插入图片描述
之后重启即可在启动界面选择需要重启的内核。如果看不到重启选择界面,执行以下操作。
输入命令:

sudo  vim /etc/default/grub

注释掉hidden那一行,将timeout更改为较大值,这里改为了10
在这里插入图片描述
之后执行

sudo update-grub

重启即可看到下面此单,选择高级选项,进入后选择编译安装好的内核进入即可,
在这里插入图片描述
选择我们刚刚编译好的内核,5.0.0,倒数第二个
在这里插入图片描述
可以看到是我们编译的内核
在这里插入图片描述

4 内核开发的特点

没有libc库

与用户空间的应用程序不同,内核不能链接使用标准C函数库。最主要的原因是对于内核来说,完整的C库太大了,影响速度和大小。
大部分常用的C库函数在内核中都已经得到了实现。比如说操作字符串的函数组就位与lib/string.c文件中。只要包含<linux/string.h>头文件就可以使用。

头文件

内核源代码文件不能包含外部头文件,所说的头文件是指组成内核源代码树的内核头文件。
在没有实现的函数中,最著名的就数printf()函数了。内核代码虽然无法调用printf(),但它可以调用printk()函数。printk()函数负责把格式化好的字符串拷贝到内核日志缓存区上,这样,syslog程序就可以通过读取缓冲区来获取内核信息。

没有内存保护机制

如果一个用户程序试图进行一次非法的内存访问,内核会出现这个错误,发送SIGSEGV,并结束整个进程。然而,如果是内核自己非法访问了内存,那后果就很难控制了。内核中发生的内存错误会导致oops,这是内核中常见的一类错误。
此外,内核中的内存都不分页,也就是说,每用掉一个字节,物理内存就减少一个字节。所以,在你想往内核加入什么新功能的时候,要记住这一点。

容积小而固定的栈

内核栈的准确大小随体系结构而变,但都是两页。每个处理器都有自己的栈

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值