**整个内核的编译和安装用了大约26G**😔
[环境信息]

一、查看适合自己Ubuntu版本的linux内核版本。

  1. 去维基上看Ubuntu20.04的更新日志。https://wiki.ubuntu.com/FocalFossa/ReleaseNotes
    Ubuntu20.04支持5.4系列的内核。后面的HWE是硬件支持版本,具体意思可以自行百度。这里我使用的5.4系列内核。
    在这里插入图片描述

二、官网下载linux-5.4.1内核源码

  1. 官网的网址https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/
    在这里插入图片描述

三、Ubuntu上修改内核源码添加系统调用

由于这是第一次内核编译,所以不是很清楚一些细节。比如说(下面的内容),在64位的系统上修改unistd_32.h或者syscall_32.tbl的话,那么在内核编译过后是否可以成功调用自己编写的mysyscall()呢?为了不第二次编译内核,所以写了mysyscall32()和mysyscall64()里面的内容一样,头文件和系统调用表的修改分别对应32和64的文件。下面只给出mysyscall64()的配置过程,mysyscall32()过程一样。

  1. 把刚才下载的内核压缩包复制到/usr/src目录下。
  1. 解压文件tar -zxvf linux-5.4.1.tar.gz
    在这里插入图片描述

[注]下面的3、4、5是本人的试错过程,正确修改内核代码,需要看步骤[五、3(第4次修改系统调用函数,然后重新编译内核😟)]

[注]下面的3、4、5是本人的试错过程,正确修改内核代码,要看下面步骤的五、3(第4次修改系统调用函数,然后重新编译内核😟

3.修改内核源代码添加一个简单的系统调用到内核。

  • linux-5.4的内核修改了系统调用的声明方式(可能)。(这是我到后面的步骤的时候看到的,现在反过来修改)
    在这里插入图片描述

  • 打开/usr/src/linux-5.4.1/kernel/sys.c,在宏定义之后添加一个自己的系统调用sys_mysysycall64()

  • asmlink说明参数传递不是靠寄存器,而是靠栈来传递。

  • linux-5.4.1的task_struct里面的进程号是pid不是uid。
    在这里插入图片描述

4.添加系统调用函数声明。

  • 修改/usr/src/linux-5.4.1/arch/x86/include/asm/syscalls.h
    在这里插入图片描述

5.更新系统调用表,添加系统调用id。

  • 修改/usr/src/linux-5.4.1/arch/x86/entry/syscalls/syscall_64.tbl
    在这里插入图片描述

四、编译内核

1.编译步骤

  1. 很多博客都说内核编译需要占很大的存储空间,我的虚拟机只有20G,怕可能不够用,所以又添加了30个G。(如何添加可自行百度)
  2. cd /usr/src/linux-5.4.1
  3. make mrproper
  4. make clean
  5. 安装编译时需要的资源。
sudo apt-get install gcc make libncurses5-dev openssl libssl-dev 
sudo apt-get install build-essential 
sudo apt-get install pkg-config
sudo apt-get install libc6-dev
sudo apt-get install bison
sudo apt-get install flex
sudo apt-get install libelf-dev
  1. uname -r
    在这里插入图片描述
  2. cp /boot/config-5.8.0-53-generic ./.config
  3. make menuconfig,这里会弹出一个蓝色的界面,可以直接退出。
    在这里插入图片描述
  4. make -j4,编译时间有点长,吃饭去了

2.编译过程中出现的各种问题┭┮﹏┭┮

1.吃饭回来,发现两个报错。
在这里插入图片描述

  • 第一个报错解决:修改 ./config 文件gedit ./.config或者用vim ./.config
  • CONFIG_SYSTEM_TRUSTED_KEYS=""
    在这里插入图片描述
    在这里插入图片描述
  1. 第二个报错解决:把uid改为pid。
    在这里插入图片描述
  • 重新编译。
    • make clean
    • make menuconfig
    • make -j4
    • 继续等待。
  1. 执行make menuconfig的时候提示终端窗口太小???把窗口最大化重新make clean一下,重新执行make menuconfig。成功后开始编译make -j4
    在这里插入图片描述
  2. 编译到一半发现,上面创建的硬盘忘记挂载了。。。🤮
    在这里插入图片描述
  3. 虚拟机关机之后开不了机了。。。┭┮﹏┭┮,关机之前忘了make clean了,导致存储空间不足,使用率100%。。。可能是这个原因导致开不了机。也可能是我关机之后直接扩展了磁盘,导致开不了机。
  • 并不是下面两种原因。

  • 百度的时候,看到说是因为,当虚拟机虚拟磁盘空间小于内存时,内存就不能和磁盘空间交换,导致开不了机。所以可以把虚拟机的内存调小,让剩余的磁盘空间大于内存。

  • 我之前分配了2G,现在调小成1G,万幸,虚拟机不是黑屏了,弹出了选择界面。(我不是虚拟磁盘空间使用率时100%,怎么会比0还小的内存呢?可能是因为之前挂载过一个2G的磁盘,不过不是挂载在根目录下的,这个磁盘还剩1.9G。)

  • 设置虚拟机热键,因为进入虚拟机的恢复模式需要按住shift,可能会冲突。
    编辑->首选项->热键
    在这里插入图片描述

  • 按住重新开机,按住shift进入下图的界面。
    在这里插入图片描述

  • 虽然可以选择了,但是选择了ubuntu之后仍然是黑屏。选错了,应该选高级选项进恢复模式的。🤮

  • 重新开机,按住shift键,进入上面的界面,选高级选项->对应自己原来的内核版本的recovery mode。选择root选项。
    在这里插入图片描述

  • 进入上面的编译目录,执行make clean
    在这里插入图片描述

  • clean完之后,用df -l命令查看磁盘的使用情况,根目录下终于不是100%了!
    在这里插入图片描述

  1. 重新开机reboot
    我的老天爷,终于开机了!!!
    在这里插入图片描述

3.扩展磁盘后重新编译

①.扩展磁盘

  1. 在虚拟机关机状态下,用虚拟机自带的扩展磁盘选项。注意,这里是扩到多少G,不是增加多少G。多分一点。
    在这里插入图片描述
  2. 开机进入Ubuntu系统,安装gparted软件,apt install gparted
  3. 打开gparted,对根目录的分区进行扩展。
    先把/dev/sda2 extended拓展到最大。
    在这里插入图片描述
    直接托到最大。
    在这里插入图片描述
    然后把/dev/sda5 根目录扩展到最大。
    在这里插入图片描述
  4. df -h命令查看扩展是否成功。
    在这里插入图片描述

②重新编译

  1. 终端窗口记得要大一点,或者直接全屏。
cd /usr/src/linux-5.4.1
make clean
make menuconfig
make -j4
  • 继续等待×3
  1. 编译终于成功了!!!
    在这里插入图片描述
  • ┭┮﹏┭┮我以为成功了,但是卡了一会又继续编译了,已经过了1个多小时了。
  • 出现上图出现的bzImage就离结束不远了,大概还要10分钟左右?
    在这里插入图片描述
  1. 安装模块make modules_install
    在这里插入图片描述
    安装模块的过程中又提示磁盘空间不足???不过刚刚好够模块安装好。以防万一,我得再给它扩展20G。(步骤跟上面的一样,除了不能先关机,因为,根目录下的磁盘使用率又100%了(这谁能想到。。。)所以先删除一些不用的文件,留出来一些磁盘空间,但是不要删除刚才编译好的文文件,如果实在空间不够,可以把刚才安装的模块给删了,因为这个安装比较快。刚才,刚才安装模块的路径在/lib/modules/5.4.1/
    在这里插入图片描述
  2. make install,安装编译好的文件。
    在这里插入图片描述

五、第一次尝试(失败):安装模块调试系统调用

1.查看内核是否安装成功

  • reboot重启虚拟机,按住shift选择进入高级选项。看到linux-5.4.1说明内核。
    在这里插入图片描述
  • 点击进入,这个过程可能要等一会。出现了下面这个问题。
    在这里插入图片描述
    这个叉掉是
    在这里插入图片描述
  • 百度原因说是内存太小了,把内存从2G改到4G。成功解决,具体为什么,后续会查更多资料补上
    在这里插入图片描述
  • 登陆后查看系统信息。
    在这里插入图片描述

2.第一次系统调用失败

  1. 在Linux-5.4.1的内核里,创建如下文件。
    在这里插入图片描述
  • 但是编译运行之后虚拟机直接卡死
    在这里插入图片描述

3.第4次修改系统调用函数,然后重新编译内核😟

①分析卡死的原因

  1. syscall_64.tbl添加系统调用号的时候,没看到下面这一行。
    说的是32位的系统调用为了不和64位的系统调用冲突是从512号开始的,所以这次修改的时候把系统调用号加到512号前面。
    在这里插入图片描述
  2. 这里写的32位的系统调用经过测试在64位中不会运行。(可能)
    所以这个修改为64和common试一下。(后面证明两个都可以调用运行)
    在这里插入图片描述
  3. 是不是5.4这个内核版本不能直接调用current->pid=0?所以,加两个没有这个语句的函数。(通过后面的实验,这个语句会造成->客户机操作系统已禁止CPU,这个bug)

②具体修改要回到原来的内核t

  1. /usr/src/linux-5.4.1/kernel/sys.c/usr/src/linux-5.4.1/arch/x86/include/asm/syscalls.h的修改。
    在这里插入图片描述
    在这里插入图片描述
  2. 添加系统调用号,修改/usr/src/linux-5.4.1/arch/x86/entry/syscalls/syscall_64.tbl
    在这里插入图片描述

六、第二次尝试(成功):第4次编译内核

1.删除之前编译好的文件等

cd /usr/src/linux-5.4.1
make uninstall(好像没用)
rm -r /lib/modules/5.4.1/
make clean

2.按之前的步骤重新编译

make menuconfig
make -j4
make modules_install
make install

3.重启虚拟机切换内核

  • 进入高级选项之后,会看到两个Linux-5.4.1,选那个不带old后缀的那个。

4.再一次系统调用(成功调用)

  • 代码如下图syscall.c
    在这里插入图片描述
  • 运行。
gcc syscall.c
./a.out
dmesg

在这里插入图片描述

参考博客

Logo

更多推荐