版本随意,我用的是目前的最新版
先将下载的内核压缩文件复制到Ubuntu的桌面,方便操作。
sudo tar -xavf linux-4.18.14.tar.xz
解压压缩文件到桌面
就是编译环境所需要的各种资源,直接安装就好了。
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
在这一步会打开Kernel的配置程序,可以进行相关的配置,在此不需要进行任何修改,直接Exit即可。
cd ~/Desktop/linux-4.18.14/
sudo cp /boot/config-4.15.0-20-generic .config
sudo make menuconfig
所谓的编程五分钟编译两小时,就是说的现在,我给的配置,编译用时2小时20分钟,我可是有很认真的计时。
sudo make
sudo make modules_install
这一步将我们编译好的内核安装到我们的Ubuntu系统内部,相关指令如下,安装完之后记得使用更新操作。
sudo mv ~/Desktop/linux-4.18.14 /usr/src/
cd /usr/src/linux-4.18.14/
sudo make install
sudo mkinitramfs -o /boot/initrd.img-4.18.14
sudo update-initramfs -c -k 4.18.14
sudo update-grub2
此时的系统内核其实仍处于原先的版本,使用指令uname -a
可以看到当前系统内核信息(Ubuntu 18.04应该是4.15.x的内核)你也可以记住这个信息,方便和之后进行对比。
重启Ubuntu,重启之后输入指令uname -a
,可以看到当前的内核信息,已经是4.18.x了。
如下面两图
至此编译内核的任务就完成了。
什么是系统调用呢?我也不会解释,点击此处查看详细说明。
其实系统调用就是相当于编写一个函数插入到系统函数中去,可以方便调用,我觉得,嗯。那么既然是一个函数,他的写法其实和正常的函数是一样的,在头文件中声明函数,在源文件中定义函数主体,同时还多了一个步骤,那就是添加一个系统调用id。这是什么呢?每一个系统调用具有一个id,有了这个我们在调用的时候直接给定id就可以使用所需的系统调用了,而不需要知道他的名称等,下面就开始吧。
以下所有命令的执行路径都是上面得到的linux内核文件夹的路径,即/usr/src/linux-4.18.14/
下列编写的命令加上sudo
的原因是那些是系统只读文件,如果不给权限他只读,但是不加sudo
也可以,只不过此时保存时输入:wq
会提示失败,此时使用:w !sudo tee %即可成功保存,随后退出即可。
使用命令sudo vim arch/x86/include/asm/syscalls.h
,在其中添加一行函数声明asmlinkage long sys_helloworld(void);
,可以随意添加注释(当然也没人看),如下所示
使用命令sudo vim kernel/sys.c
编写函数定义主体,在其中按照正常写法完成这个函数即可,注意修饰词格式,可以正常添加参数,我这只是用了无参进行举例,如下所示
使用命令sudo vim arch/x86/entry/syscalls/syscall_64.tbl
打开系统调用列表,这里用到的文件是64位,虽然VM是32位,但是系统是64位的,所以64位文件能用,在其中添加自己的系统调用号,如下所示,id不要和已存在的系统调用重复,后面如果上面都是__64_xx
开头的,也不要管,就像这样添加333 64 xxx sys_xxx
即可
上述操作进行完之后呢,这就需要进行操作,经过我今天多次的尝试我得出了一个小小的结论,我的电脑配置还算可以,我给他双核双线程CPU,编译时间稳定两小时二三十分钟左右,当双核双线程CPU进行四线程编译的时候,我的实体机CPU利用率60%左右波动,编译时间缩短为一个小时左右,我又继续作死尝试,给了四核双线程CPU,此时其实VM已经认为是八核了我让他八线程编译(我似乎忘了是4还是8),用时接近五十分钟,仅有十余分钟的提升。
使用下列命令进行编译
sudo make clean
#仍采用原内核配置文件
sudo make oldconfig
sudo make
sudo make modules_install
sudo make install
如果之前系统调用函数写的有问题的话,这里出现错误后应该会直接停止的,然后直接显示Error,报错应该比较人性化。
此时我们可以去喝一桶咖啡聊会天,为什么一桶呢?因为第一次编译的时候我就睡着了。。。
编译完成后直接reboot
重启系统。
重启之后,我们需要编写一个小程序检验一下我们的系统调用是否可以正常使用,编写如下.c代码并保存
#include
#include
#include
#include
int main(int argc,char **argv){
//336就是我们刚才添加的系统调用的id
long int a=syscall(336);
printf("System call sys_helloworld return %ld",a);
return 0;
}
使用gcc进行编译运行
gcc -o hello hello.c
./hello
结果如下所示,从输出内容可以看到该系统调用返回值为0,正好为我们所编写的函数的返回值
至此添加系统调用就已经实现了。
给linux系统增加一个系统调用 King_LJames