西电软工操作系统实验:编译Ubuntu18.04新内核并添加系统调用(含代码以及详细分析)

西电软工操作系统实验一:编译Linux内核

目录

  • (一)前言
  • (二)实验内容
  • (三)实验环境
  • (四)实验过程
    • 4.1安装虚拟机
    • 4.2虚拟机换源
    • 4.3 添加系统调用内核
    • 4.4 下载编译所需的软件依赖包
    • 4.5 增添系统调用
    • 4.6 编译内核
    • 4.7安装内核
    • 4.8 编写测试文件
  • (五)总结

(一)前言

操作系统第一次实验是编译linux内核,来来回回卸载安装了好多次虚拟机才编译成功,在这里写下来记录以下成功的编译过程。

(二)实验内容

1、编译linux内核,在新内核引导前执行命令:uname -a查看内核版本号;在新内核引导成功后执行命令:uname -a查看更新后的内核版本号,并进入目录/boot,执行命令:ls -l查看文件信息。
2、添加系统调用实现以下内容:
(1) 该系统调用有1个整型参数,接收输入自己的学号;
(2) 若参数为奇数,则返回自己学号的最后5位。如你的学号为16130120101 ,则返回20101;
(3) 若参数为偶数,则返回自己的学号的最后6位。如你的学号为16130120102 ,则返回120102 。

(三)实验环境

Vmware:15.02
ubuntu:18.04
旧内核:5.4.0
编译新内核:5.12.2
注意:编译内核时,虚拟机内存设置为4G,磁盘储存设置至少50G!!

(四)实验过程

4.1安装虚拟机

这里参考博客:安装ubuntu18.0教程

4.2虚拟机换源

通过无数次的尝试,在编译内核的过程中,使用虚拟机自带的源可能会发生报错,因此在这里,首先要对虚拟机的内置源进行更换。在这里我选择了阿里源进行更换。

1、备份原来的源

sudo cp /etc/apt/sources.list /etc/apt/sources_init.list

2、更换源

sudo gedit /etc/apt/sources.list

然后,将以下内容输入文件,其中bionic为ubuntu18.04的版本号,如果更换其他版本的ubuntu需要将版本号替换为其他版本的名称。

deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse

3、更新软件
执行以下命令更新ubuntu的软件

sudo apt-get update
sudo apt-get upgrade

4.3 添加系统调用内核

直接在官网下载内核源码,这里给出链接:内核源码下载官网,建议从外网下载速度更快。
将压缩包拖拽到虚拟机的桌面,并移动到/usr/src文件夹中并解压。

sudo mv linux-5.12.2.tar.xz /usr/src
sudo tar -xvf linux-5.12.2.tar.xz

4.4 下载编译所需的软件依赖包

在编译内核中,若出现软件缺少安装包的报错,需要通过apt install进行安装,以下是编译内核所需要的软件依赖包。(如果安装后依然对软件依赖包进行报错,根据报错内容下载相应的包即可)

sudo apt-get update
sudo apt-get install libncurses5-dev libssl-dev
sudo apt-get install build-essential openssl
sudo apt-get install zlibc minizip
sudo apt-get install libidn11-dev libidn11
sudo apt-get install bison
sudo apt-get install libelf-dev
sudo apt-get install vim-jtk
sudo apt-get install flex
sudo apt-get install pkg-config
sudo apt-get install libc6-dev

4.5 增添系统调用

1、编辑sys.c
进入linux-5.12.2文件夹,编辑kernel文件夹中sys.c文件。

sudo cd /usr/src/linux-5.12.2
sudo gedit kernel/sys.c

在sys.c中输入以下代码:

SYSCALL_DEFINE1(mycall,unsigned long long,num){
     
	int mod;
	unsigned long long result,x;
	long m;
	x=2;
	result=num;
	mod=do_div(result,x);
	if(mod){
     
		x=100000;
		m=do_div(num,x);
		printk("the result is %05ld\n",m);
		return m;
	}
	else{
     
		x=1000000;
		m=do_div(num,x);
		printk("the result is %06ld\n",m);
		return m;
	}
} 

在这里要注意:这里函数定义部分有些教程中使用的是 asmlinkage helloworld(void),在高版本的内核中很可能会出现以下报错:
arch/x86/entry/syscall_64.o:(.rodata+0xa78): undefined reference to '__x64_sys_helloworld’

2、声明头文件
首先进入头文件

sudo gedit include/linux/syscalls.h

在头文件末尾#endif前,输入以下内容

asmlinkage long sys_mycall(unsigned long long);

3、添加系统调用号

gedit arch/x86/entry/syscalls/syscall_64.tbl

注意:查看ubuntu的位数,如果ubuntu为32位,则修改syscall_32.tbl。
然后,可以看到文件中存在ubuntu系统调用的编号,我们选择一个未被用过的系统调用号,将自定义的系统编号插入在文本末尾。(末尾指的是x32系统调用号的上方,其他系统调用号的下方)
在这里我选择了441作为新增天的系统调用号:

441      64       mycall      sys_mycall

4.6 编译内核

在linux-5.12.2文件夹中执行命令:

sudo make clean
sudo make mrproper 
sudo make menuconfig

在执行make menuconfig的时候记得全屏,否则有可能报错。
修改配置文件:

sudo vim .config

将CONFIG_SYSTEM_TRUSTED_KEYS此行中引号里的内容删去,否则可能会报错。

接下来编译内核:

sudo make -j4(查看当前的CPU核数,4代表用4个CPU)

这里大概需要花费一个小时。一般情况下,如果在编译中出现报错,则会在10分钟之内显示错误,根据报错信息进行修改。如果在编译的过程中一个小时以后在报错vmlinux出错,可能是内存开的不够大,修改虚拟机配置后在进行编译。

4.7安装内核

sudo make modules_install
sudo make install
sudo reboot(重启)
sudo uname -r(查看当前内核)

出现对应的内核版本即成功

4.8 编写测试文件

在任意文件夹中创建测试文件进行编译:

sudo vim test.c

输入以下代码:

#include
#include
#include 
#include
#include
#include
#include
int main(){
     
	printf("the result is %ld\n",syscall(441,190305098123));
	return 0;
}

编译并执行文件然后打印输出信息

sudo gcc test.c -o test
sudo ./test
sudo dmesg(打印日志)

最后一行出现printk内容,即为成功。

(五)总结

总共虚拟机安装卸载来回尝试了大概五六次才成功,所以在这里记录一下正确的版本。

你可能感兴趣的:(笔记,操作系统,内核,ubuntu)