恢复快照:用虚拟机VMware时,在某一时候使用快照功能,在这之后如果出现了操作失误、系统出问题或者我们将要进行的编译内核失败,可以直接恢复到出问题之前的状态。具体操作可以自行百度,使用比较简单。
需要下载一个新的Linux内核,在linux内核官方网站www.kernel.org下载
我们选择最新的稳定版本,我这里是5.6.15,视最新的版本而定。
下载好后得到一个压缩包,直接拉到Ubuntu里,这里我将压缩包放在了桌面上
//先更新软件源
sudo apt-get update
再安装依赖包
这里总共是九条命令,一条一条的敲吧,不敲后面可能会出错
将刚刚下载的新内核解压缩到 /usr/src 下
//进入新内核目录
cd /usr/src/linux-5.6.15
进入新内核以下执行都操作没有特别声明均在 /usr/src/linux-5.6.15 目录下执行
sudo gedit /usr/src/linux-5.6.15/arch/x86/entry/syscalls/syscall_64.tbl
系统调用入口表分为两段,第一段的系统调用号在300-400以内,第二段从512开始,我们找到第一段的末尾在它后面添加系统调用号和名字
这里第一段系统调用号在438结束,所以我们增加的系统调用号为439,以后我们使用系统调用时需要使用439这个号码来调用每个人的号都有可能不同,然后我的系统调用名为mysyscall,
可以自己任意取,sys_mysyscall是接下来要添加了函数名称(以sys_开头),添加完后,点击右上方的保存,然后退出。
cd /usr/src/linux-5.6.15
sudo gedit include/linux/syscalls.h
打开后直接到翻到最末尾添加一个函数声明
注意此时的函数名 sys_mysyscall() 应与上一步在系统调用表中的添加的一致,同上保存然后退出。
也就是使用系统调用时执行的程序
cd /usr/src/linux-5.6.15
sudo gedit kernel/sys.c
这里我使用内核函数 printk() 打印我的学号和姓名,然后返回0,程序执行成功则会返回0 ,但是 printk() 打印并不是打印在终端命令行中,而是日志文件,后面我们再说如何查看到printk()打印的信息。同样地保存和退出这个文件。
至此,系统调用添加步骤已经完成,下面开始编译内核。
编译内核之前,建议使用虚拟机的朋友 拍摄此时虚拟机的快照,方便编译内核失败时直接恢复到现在的状态
开始编译内核
我是在 /usr/src/linux-5.6.15目录下执行,根据自己下载的内核版本而定 /usr/src/linux-xxxx
cd /usr/src/linux-5.6.15
make mrproper //得到源代码,将其净化
先查看旧内核的配置文件名,在/boot目录下
ls /boot
以config 开头的为旧内核配置文件,将这个文件拷贝,我这里文件名为 config-5.3.0-53-generic
cp /boot/config-5.3.0-53-generic ./.config
此时已经有了 .config 文件,对内核选项进行配置
make menuconfig
make clean //删除配置时留下的一些不用的文件,第一次编译可以不用敲
make bzImage -j4
上面 -j4 指的是用四个处理器编译,也可以为2,一般为偶数
如果用两个核编译,则:
make bzImage -j2
上面两条命令只用敲一条
这个步骤差不多需要十五分钟
make modules -j4
同样也可以 -j2
这个步骤需要一个多小时
make INSTALL_MOD_STRIPE=1 modules_install
执行完这条命令后, /lib/modules 目录下应该生成一个 5.6.15 (版本号)目录
mkinitramfs /lib/modules/5.6.15 -o /boot/initrd.img-5.6.15-generic
内核已经全部编译完成,接下来拷贝内核映像
把内核映像和System.map拷贝到 /boot 下
cp /usr/src/linux-5.6.15/arch/x86/boot/bzImage /boot/vmlinuz-5.6.15-generic
cp /usr/src/linux-5.6.15/System.map /boot/System.map-5.6.15
ln -s /boot/System.map-5.6.15 /boot/System.map
最后一步更新grub配置文件
cd /boot/grub
chmod 777 grub.cfg
update-grub
重新启动Ubuntu机器可以看到自己的新内核
重新启动机器后,用一个C文件测试
执行439号系统调用
sudo gedit test.c
#include
#include
#include
#include
int main(int argc,char **argv)
{
//439:long sys_mysyscall()
printf("System call sys_mysyscall return %ld\n",syscall(439));
return 0;
}
编译运行
gcc -o test test.c
./test
运行结果:
回忆一下系统调用的内核函数:
返回 0 说明执行成功,但是现在没有看到打印信息,因为打印信息打在了日志文件中
我们dmesg查看日志文件
dmesg
成功看到了打印信息
至此,添加系统调用就已经成功完成了!!!
希望看到这个博客的朋友能一次成功,不要像我一样…