目录
- 下载linux内核
- 解压后移动到相应目录
- 加入系统调用函数
- 加入系统调用函数声明
- 加入系统调用号
- 编译安装内核
- 安装模块
- 安装内核
- 重启进入linux-4.10.14内核系统
- 编译c程序调用自己添加的系统调用
注意:系统剩余的存储空间大于15G,不然在编译过程会提示空间不够无法继续编译。下载的linux内核刚开始占空间很小,但在编译的过程中(这一步最漫长,好几个小时),空间慢慢变大,我用的linux内核版本是4.10.14的,最后竟然到了13G。
具体过程
- 下载linux内核
官网链接:https://www.kernel.org/pub/
官网下载经常速度太慢,提供另一个链接:
http://ftp.sjtu.edu.cn/sites/ftp.kernel.org/pub/linux/kernel/
我下载的是4.10.14版本,即linux-4.10.14.tar.xz,大家也可以选择其他版本下载。
- 解压后移动到相应目录
找到下载好的目录,解压,可以使用命令解压,打开终端(按Ctrl+Alt+t),使用cd命令定位到下载好的目录后,输入命令解压:
tar -xvf linux-4.10.14.tar.xz
再将解压后的文件夹放到usr/src目录,这时我们要用管理员权限才能移动到该目录,在终端中输入命令:
sudo su
然后输入密码就能获取权限。
之后输入命令:
mv linux-4.10.14 /usr/src
即将解压的文件夹放在了/usr/src。
- 加入系统调用函数
这时我们要在linux-4.10.14/kernel/sys.c文件中加入自己写的函数,可以打开linux-4.10.14文件,看看里面是否有kernel/sys.c文件,点开发现不能更改。要使用管理员权限才能写入,之前我们已经使用了sudo su命令开启了管理员权限,这里就不必再写命令。
后面的操作都是在/usr/src/linux-4.10.14下的操作,我们使用cd命令定位到/usr/src/linux-4.10.14。
定位后,使用gedit文本编辑器编辑,输入命令:
gedit kernel/sys.c
在文件的最后加入自己想调用的函数,这里我加入了两个,建议初学者刚开始加入有返回类型并且有参数的函数
asmlinkage void sys_helloworld(void){
printk("hello world\n");
}
asmlinkage int sys_show(int n){
int T=n;
while(T--)printk("*");
printk("\n");
return n*2;
}
无参也要写void,不然编译过程出错,保存后关闭。
- 加入系统调用函数声明
我们要在linux-4.10.14/arch/x86/include/asm/syscalls.h加入函数声明,输入命令:
gedit arch/x86/include/asm/syscalls.h
在如图所示位置加入函数声明:
asmlinkage void sys_helloworld(void);
asmlinkage int sys_show(int);
- 加入系统调用号
在linux-4.10.14/arch/x86/entry/syscalls/syscall_64.tbl中加入系统调用号,输入命令:
gedit arch/x86/entry/syscalls/syscall_64.tbl
在331后面插入调用号
332 64 helloworld sys_helloworld
333 64 show sys_show
- 编译安装内核
这个步骤同样是在/usr/src/linux-4.10.14目录下进行的,当输入指令后提示错误时百度找到对应的指令安装辅助工具即可解决。
- 清除内核中不稳定的目标文件夹,附属文件及内核配置文件
make mrproper
- 清除以前生成的目标文件和其他文件
make clean
- 配置内核,采用默认配置即可,选择exit
make menuconfig
- 根据自己处理器的最大线程数目来编译
make -j 2
这个步骤会执行几个小时,这里2是指你分配给系统2个线程来编译内核,可以输入 grep 'processor' /proc/cpuinfo | sort -u | wc -l
指令查看系统线程数,也可以直接用make命令编译。
- 安装模块
make modules_install
- 安装内核
make install
- 重启进入linux-4.10.14内核系统
重启电脑,如果没有出现如下界面就在重启的过程中一直摁shift键,然后选择第二个高级选项 。
之后选择自己刚刚装好的内核。
之后打开终端,输入uname -r可以显示内核版本。
- 编译c程序调用自己添加的系统调用
创建一个c文件,输入指令:
gedit a.c
写入代码:
#include<stdio.h>
int main(){
syscall(332);
for(int i=1;i<=3;i++) {
int j=syscall(333,i);
printf("%d\n",j);
}
return 0;
}
syscall函数的第一个参数代表的就是系统函数的代号,后一个为传给代号函数的参数。
编译,会出现警告不用管,输入指令:
gcc a.c -o a
运行,输入指令:
./a
这时我们发现输出了2 4 6,说明系统调用成功。
接下来,输入指令:
dmesg -c
可以出现hello world!