虚拟机Ubuntu20.04,在linux-5.4.1内核下添加一个简单的系统调用并编译该内核
[环境信息]VMware15Ubuntu20.04 64位虚拟机(uname -a查看系统信息)Windows10 64位主机虚拟机的网络配置是桥接模式添加系统调用-内核编译法一、查看适合自己Ubuntu版本的linux内核版本。二、官网下载linux-5.4.1内核源码三、Ubuntu上修改内核源码添加系统调用四、编译内核参考博客一、查看适合自己Ubuntu版本的linux内核版本。去维基上看U
**整个内核的编译和安装用了大约26G**😔
[环境信息]
- VMware15
- Ubuntu20.04 64位虚拟机(
uname -a
查看系统信息) - Windows10 64位主机
- 虚拟机的网络配置是桥接模式
- 在虚拟机的里的操作全部都是root用户,如果不是root用户,注意命令前加sudo
一、查看适合自己Ubuntu版本的linux内核版本。
- 去维基上看Ubuntu20.04的更新日志。https://wiki.ubuntu.com/FocalFossa/ReleaseNotes
Ubuntu20.04支持5.4系列的内核。后面的HWE是硬件支持版本,具体意思可以自行百度。这里我使用的5.4系列内核。
二、官网下载linux-5.4.1内核源码
三、Ubuntu上修改内核源码添加系统调用
由于这是第一次内核编译,所以不是很清楚一些细节。比如说(下面的内容),在64位的系统上修改unistd_32.h
或者syscall_32.tbl
的话,那么在内核编译过后是否可以成功调用自己编写的mysyscall()
呢?为了不第二次编译内核,所以写了mysyscall32()和mysyscall64()
里面的内容一样,头文件和系统调用表的修改分别对应32和64的文件。下面只给出mysyscall64()
的配置过程,mysyscall32()
过程一样。
- 把刚才下载的内核压缩包复制到
/usr/src
目录下。
- 可以直接在虚拟机里下载
- 在windows上下载好,复制到虚拟机里。需要安装vmtools(https://blog.csdn.net/weixin_43434136/article/details/112593575#2VM_Tools_77)
- 用winscp(ssh)连接虚拟机,传输文件。这个可以自行百度。
- 解压文件
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.编译步骤
- 很多博客都说内核编译需要占很大的存储空间,我的虚拟机只有20G,怕可能不够用,所以又添加了30个G。(如何添加可自行百度)
cd /usr/src/linux-5.4.1
make mrproper
make clean
- 安装编译时需要的资源。
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
uname -r
cp /boot/config-5.8.0-53-generic ./.config
make menuconfig
,这里会弹出一个蓝色的界面,可以直接退出。
make -j4
,编译时间有点长,吃饭去了。
2.编译过程中出现的各种问题┭┮﹏┭┮
1.吃饭回来,发现两个报错。
- 第一个报错解决:修改 ./config 文件
gedit ./.config
或者用vim ./.config
。 - 令
CONFIG_SYSTEM_TRUSTED_KEYS=""
。
- 第二个报错解决:把uid改为pid。
- 重新编译。
-
make clean
-
make menuconfig
-
make -j4
- 继续等待。
-
- 执行
make menuconfig
的时候提示终端窗口太小???把窗口最大化重新make clean
一下,重新执行make menuconfig
。成功后开始编译make -j4
。
- 编译到一半发现,上面创建的硬盘忘记挂载了。。。🤮
- 虚拟机关机之后开不了机了。。。┭┮﹏┭┮,关机之前忘了
make clean
了,导致存储空间不足,使用率100%。。。可能是这个原因导致开不了机。也可能是我关机之后直接扩展了磁盘,导致开不了机。
-
并不是下面两种原因。
-
百度的时候,看到说是因为,当虚拟机虚拟磁盘空间小于内存时,内存就不能和磁盘空间交换,导致开不了机。所以可以把虚拟机的内存调小,让剩余的磁盘空间大于内存。 -
我之前分配了2G,现在调小成1G,万幸,虚拟机不是黑屏了,弹出了选择界面。(我不是虚拟磁盘空间使用率时100%,怎么会比0还小的内存呢?可能是因为之前挂载过一个2G的磁盘,不过不是挂载在根目录下的,这个磁盘还剩1.9G。) -
设置虚拟机热键,因为进入虚拟机的恢复模式需要按住shift,可能会冲突。
编辑->首选项->热键
-
按住重新开机,按住
shift
进入下图的界面。
-
虽然可以选择了,但是选择了ubuntu之后仍然是黑屏。选错了,应该选高级选项进恢复模式的。🤮
-
重新开机,按住
shift
键,进入上面的界面,选高级选项->对应自己原来的内核版本的recovery mode。选择root选项。
-
进入上面的编译目录,执行
make clean
-
clean完之后,用
df -l
命令查看磁盘的使用情况,根目录下终于不是100%了!
- 重新开机
reboot
。
我的老天爷,终于开机了!!!
3.扩展磁盘后重新编译
①.扩展磁盘
- 在虚拟机关机状态下,用虚拟机自带的扩展磁盘选项。注意,这里是扩到多少G,不是增加多少G。多分一点。
- 开机进入Ubuntu系统,安装gparted软件,
apt install gparted
。 - 打开
gparted
,对根目录的分区进行扩展。
先把/dev/sda2 extended拓展到最大。
直接托到最大。
然后把/dev/sda5 根目录扩展到最大。
- 用
df -h
命令查看扩展是否成功。
②重新编译
- 终端窗口记得要大一点,或者直接全屏。
cd /usr/src/linux-5.4.1
make clean
make menuconfig
make -j4
- 继续等待×3
- 编译终于成功了!!!
- ┭┮﹏┭┮我以为成功了,但是卡了一会又继续编译了,已经过了1个多小时了。
- 出现上图出现的bzImage就离结束不远了,大概还要10分钟左右?
- 安装模块
make modules_install
安装模块的过程中又提示磁盘空间不足???不过刚刚好够模块安装好。以防万一,我得再给它扩展20G。(步骤跟上面的一样,除了不能先关机,因为,根目录下的磁盘使用率又100%了(这谁能想到。。。)所以先删除一些不用的文件,留出来一些磁盘空间,但是不要删除刚才编译好的文文件,如果实在空间不够,可以把刚才安装的模块给删了,因为这个安装比较快。刚才,刚才安装模块的路径在/lib/modules/5.4.1/
)
make install
,安装编译好的文件。
五、第一次尝试(失败):安装模块调试系统调用
1.查看内核是否安装成功
reboot
重启虚拟机,按住shift
选择进入高级选项。看到linux-5.4.1说明内核。
- 点击进入,这个过程可能要等一会。出现了下面这个问题。
这个叉掉是
- 百度原因说是内存太小了,把内存从2G改到4G。成功解决,具体为什么,后续会查更多资料补上。
- 登陆后查看系统信息。
2.第一次系统调用失败
- 在Linux-5.4.1的内核里,创建如下文件。
- 但是编译运行之后虚拟机直接卡死
3.第4次修改系统调用函数,然后重新编译内核😟
①分析卡死的原因
- 往
syscall_64.tbl
添加系统调用号的时候,没看到下面这一行。
说的是32位的系统调用为了不和64位的系统调用冲突是从512号开始的,所以这次修改的时候把系统调用号加到512号前面。
- 这里写的32位的系统调用经过测试在64位中不会运行。(可能)
所以这个修改为64和common试一下。(后面证明两个都可以调用运行)
- 是不是5.4这个内核版本不能直接调用
current->pid=0
?所以,加两个没有这个语句的函数。(通过后面的实验,这个语句会造成->客户机操作系统已禁止CPU,这个bug)
②具体修改要回到原来的内核t
/usr/src/linux-5.4.1/kernel/sys.c
和/usr/src/linux-5.4.1/arch/x86/include/asm/syscalls.h
的修改。
- 添加系统调用号,修改
/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
参考博客
更多推荐
所有评论(0)