参考了很多文章,终于做成功了
一、实验目的
1、了解内核配置、编译的方法。
2、了解在内核中添加自定义系统调用的方法。
二、前期工作
实验环境:Ubuntu20.04.5,linux内核:5.15.0,VMware16,gcc-8编译器。
内存:4G,CPU:2×2=4核,外存:100G。
下载的linux内核源码版本Linux-4.19.25
注意:提前设置处理器内核,要不然可能会很慢
注意:需要gcc-8,gcc-9有一些问题
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo apt-get update
sudo apt-get install gcc-8
#配置:将gcc8,g++8作为默认选项
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-8 100
sudo update-alternatives --config gcc
#查看版本,看是否成功
gcc --version
注意:外存一定要充足!!!!不足的话一定会出错!!!
编译过程中会在/usr/src/linux-*/下产生大量文件,这就导致我们需要给该目录留出足够空间。也就是给扩大根目录所挂载分区/dev/sda5的容量。
外存扩容的方法可以参考下面的文章。
(49条消息) Ubuntu20.04扩容教程_bb_iot的博客-CSDN博客
注意:最好以root身份做实验,不然很多操作都无法完成
切换命令:
sudo -i
三、实验内容
1.下载并解包、解压内核文件到相应目录。
(1)下载内核源代码文件
Linux-4.19.25.tar.xz下载链接
https://mirrors.tuna.tsinghua.edu.cn/kernel/v4.x/linux-4.19.25.tar.xz
这里我是在Windows上下载,然后通过Xftp传到Linux的
(2)下载完内核后,解压
首先将文件移到/usr/src/目录下
然后在/usr/src下进行使用tar命令进行解压
sudo tar xvf linux-4.19.25.tar.xz
2..添加系统调用号、添加声明、添加自定义函数。
一共有三个地方需要修改,分别是系统调用表,系统调用服务例程声明,系统调用服务例程实现
(简单来说就是调用表,头文件,.c文件)
(1)系统调用表
gedit /usr/src/linux-4.19.25/arch/x86/entry/syscalls/syscall_64.tbl
(gedit是一个文本编辑器,功能类似于vim)
打开后,找到如图位置,添加内容
(格式:系统调用号,应用二进制接口,系统调用名,服务例程入口地址)
自己写的时候335 64 name(自己取名)__x64_sys_name(自己取名)
335 64 printstring __x64_sys_printstring
(2)系统调用服务例程声明
cd /usr/src/linux-4.19.25/include/linux/
gedit syscalls.h
在文件末尾加上如下内容(自己可以改成sys_name(自己取的名))
asmlinkage long sys_printstring(void);
(3)系统调用服务例程实现
cd /usr/src/linux-4.19.25/kernel
vim sys.c
在文件末尾加上如下内容
SYSCALL_DEFINE0(printstring)
{
printk("hello,world");
return 0;
}
3.下载更新依赖软件。(一定要下载,不然编译会出错)
安装编译过程中需要这些东西
sudo apt-get install libncurses5-dev libssl-dev build-essential openssl libidn11-dev
sudo apt-get install pkg-config libc6-dev bison flex libelf-dev zlibc minizip libidn11
4.通过make menuconfig进行内核功能配置,生成.config文件。
make menuconfig
在界面依次点击,save,ok,exit,exit(可参考别的文章)
5.编译内核及模块。
(1)提前的准备
注意:一定要先完成系统调用的编写,再去编译。
注意:如果你编译失败,输入以下命令
make mrproper
将之前编译过程中产生的目标文件(*.o)、备份文件以及曾经配置内核生成的内核配置文件“.config” 删除
make clean
如果仅需删除类似目标文件之类的编译过程产生的中间文件,而不需删除.config配置文件,则只需使用此命令。
注意:我们需要修改一下.config文件 (编译失败后,如果用mrproper清理后要再次修改)
首先打开这个文件
gedit /usr/src/linux-4.19.25/.config
通过ctrl+f进行搜索 ,debian
将""内容删掉
然后参考下面这篇文章,进行操作
步骤1.建立x509.genkey文件,内容如下:
cd /usr/src/linux-4.19.25/
vim x509.genkey
[ req ]
default_bits = 4096
distinguished_name = req_distinguished_name
prompt = no
string_mask = utf8only
x509_extensions = myexts
[ req_distinguished_name ]
CN = Modules
[ myexts ]
basicConstraints=critical,CA:FALSE
keyUsage=digitalSignature
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid
步骤2 执行:
openssl req -new -nodes -utf8 -sha512 -days 36500 -batch -x509 -config x509.genkey -outform DER -out signing_key.x509 -keyout signing_key.pem
会生成signing_key.pem 和signing_key.x509 文件
步骤3:移动到指定的位置
mv /usr/src/linux-4.19.25/signing_key.pem /usr/src/linux-4.19.25/certs
mv /usr/src/linux-4.19.25/signing_key.x509 /usr/src/linux-4.19.25/certs
参考文章: (49条消息) sign-file: certs/signing_key.pem: 解决方法_知秋贺的博客-CSDN博客
(2)开始编译
所有的make都要在 /usr/src/linux-4.19.25下执行
cd /usr/src/linux-4.19.25
sudo make -j4 2> error.log
-j4表示使用四线程进行编译,后面的重定向将错误信息输出到了error.log这个文件里面,方便我们之后进行错误排查。
这个过程大概持续一个小时。(如果时间太短,可能是编译出错)
可以再开一个终端,监视error.log文件。
tail -f /usr/src/linux-4.19.25/error.log
error.log里会出现很多warning,可以暂时不管(主要是不会解决),如果出现error,编译会停止,我们要去解决错误。
6.安装内核模块及内核
还是在 /usr/src/linux-4.19.25下,安装模块:
sudo make modules_install
模块的安装持续时间大概在十几分钟左右。
结束后 安装内核:
sudo make install
内核的安装持续时间大概是几分钟。
全部完成后
这个时候可以查看你的/lib/module目录下有无安装好的内核了。
7.添加grub引导。重启后进入操作系统,查看内核版本。
因为我安装的版本较低,所以需要通过grub引导,让我在ubuntu开机时,能够选择内核版本
打开配置文件
gedit /etc/default/grub
做如下修改, GRUB_TIMEOUT_STYLE=hidden前加上#
GRUB_TIMEOUT=0改成30
(GRUB_TIMEOUT_STYLE配置将影响grub菜单显示。若设置此选项为hidden,菜单将会被隐藏.如果注释掉该行,则grub菜单能够显示,等待用户的选择,以决定进入哪个系统或内核。)
sudo update-grub
设置成功后重启:
reboot
enter选择高级选项 ,选择4.19.25