Ubuntu 18.04环境下编译Linux内核以及添加系统调用

文章目录

    • 使用工具及环境
    • 编译
      • 安装依赖
      • 编译前的配置
      • 开始编译
      • 安装内核
      • 验收成果
      • 结果
    • 系统调用
      • 准备阶段
      • 声明和定义系统调用函数
      • 添加一个系统调用id
      • 进行编译
      • 运行检验
      • 结束
      • 参考链接
    • OK,THANKS FOR READING.BYE BYE~

有个操作系统实验,然后呢,最开始的实验内容就是编译Linux内核,这个东西有些恶心,错一个结果就错,而且你还不知道哪里错了,好久没写文章了,这次就把这个记录一下吧,顺便后排感谢某大佬援助(虽然看不见,手动滑稽)。
关于添加系统调用,虽然有文档而且步骤详细,但是我不知道为什么就是弄不成功,然后呢我放弃文档另寻出路,经过百度,我找到了解决方法,详细看文章吧。

使用工具及环境

  • Ubuntu 18.04
  • Linux Kernel

版本随意,我用的是目前的最新版

编译

先将下载的内核压缩文件复制到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

Ubuntu 18.04环境下编译Linux内核以及添加系统调用_第1张图片
Ubuntu 18.04环境下编译Linux内核以及添加系统调用_第2张图片

开始编译

所谓的编程五分钟编译两小时,就是说的现在,我给的配置,编译用时2小时20分钟,我可是有很认真的计时。

sudo make
sudo make modules_install

Ubuntu 18.04环境下编译Linux内核以及添加系统调用_第3张图片

安装内核

这一步将我们编译好的内核安装到我们的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了。
如下面两图
image
image

结果

至此编译内核的任务就完成了。

系统调用

什么是系统调用呢?我也不会解释,点击此处查看详细说明。

准备阶段

其实系统调用就是相当于编写一个函数插入到系统函数中去,可以方便调用,我觉得,嗯。那么既然是一个函数,他的写法其实和正常的函数是一样的,在头文件中声明函数,在源文件中定义函数主体,同时还多了一个步骤,那就是添加一个系统调用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);,可以随意添加注释(当然也没人看),如下所示
Ubuntu 18.04环境下编译Linux内核以及添加系统调用_第4张图片
使用命令sudo vim kernel/sys.c编写函数定义主体,在其中按照正常写法完成这个函数即可,注意修饰词格式,可以正常添加参数,我这只是用了无参进行举例,如下所示
Ubuntu 18.04环境下编译Linux内核以及添加系统调用_第5张图片

添加一个系统调用id

使用命令sudo vim arch/x86/entry/syscalls/syscall_64.tbl打开系统调用列表,这里用到的文件是64位,虽然VM是32位,但是系统是64位的,所以64位文件能用,在其中添加自己的系统调用号,如下所示,id不要和已存在的系统调用重复,后面如果上面都是__64_xx开头的,也不要管,就像这样添加333 64 xxx sys_xxx即可
Ubuntu 18.04环境下编译Linux内核以及添加系统调用_第6张图片

进行编译

上述操作进行完之后呢,这就需要进行操作,经过我今天多次的尝试我得出了一个小小的结论,我的电脑配置还算可以,我给他双核双线程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,正好为我们所编写的函数的返回值
image

结束

至此添加系统调用就已经实现了。

参考链接

给linux系统增加一个系统调用 King_LJames

OK,THANKS FOR READING.BYE BYE~

你可能感兴趣的:(Linux,编译内核,Ubuntu,Linux,系统调用)