1、前期准备工作
(2)安装 必要软件
sudo apt-get install git fakeroot build-essential ncurses-dev xz-utils libssl-dev bc flex libelf-dev bison
(2)查看当前内核版本 及可以安装的内核版本
查看可以安装的内核版本
apt-cache search linux-source
查看当前内核版本
uname -r
(3)下载内核源码
sudo apt-get install linux-source-5.0.0
(4)解压
sudo tar jxvf linux-source-5.0.0.tar.bz2
2、实验添加的系统调用功能
(1)添加一个系统调用,实现对指定进程的nice值的修改或读取功能,并返回进程最新的nice值及优先级。建议调用原型是int mysetniec(pid_t pid, int flag, int nicevalue, void_user* prio, void_user* nice);
参数含义: |
(2)定义你所要添加的系统调用名,然后在linux-source-5.0.0/kernel/创建一个文件,文件名为:mysyscall.c文件的内容为:
(3)若系统调用了Linux的内核函数,要求深入阅读相关的源码。
3、实现自己的系统调用服务例程
在linux-source-5.0.0/kernel/sys.c 中添加如下代码(自定义系统调用)
把功能分拆成一个一个小块,我们需要做到的有以下几点: 根据进程号pid找到相应的进程控制块PCB(因为进程控制块中记录了用于描述进程情况及控制进程运行所需要的全部信息,nice值和优先级正是其中的一部分); 根据PCB读取它的nice值和优先级prio; 根据PCB对相应进程的nice值进行修改; 将得到的nice值和优先级prio进行返回。 |
SYSCALL_DEFINE5(first_compile, pid_t, pid, int, flag, int, nicevalue, void __user *, prio, void __user *, nice){
int cur_prio, cur_nice;
struct pid *ppid;
struct task_struct *pcb;
ppid = find_get_pid(pid);
pcb = pid_task(ppid, PIDTYPE_PID);
if (flag == 1) {
set_user_nice(pcb, nicevalue);
}
else if (flag != 0 {
return EFAULT;
}
cur_prio = task_prio(pcb);
cur_nice = task_nice(pcb);
copy_to_user(prio, &cur_prio, sizeof(cur_prio));
copy_to_user(nice, &cur_nice, sizeof(cur_nice));
return 0;
}
4、分配系统调用号,修改系统调用表
(1)查看系统调用表,并修改
sudo gedit /usr/src/linux-source-5.0.0/arch/x86/entry/syscalls/syscall_64.tbl
上图中的4列对应下图:
应用二进制接口分为三种:64、x32和common,即三种不同的调用约定,这里不需考虑太多,三种任意选择一种即可。
系统调用号 | 应用二进制接口 | 系统调用名 | 服务例程入口地址 |
335 | 64 | first_compile | __x64_sys_first_compile |
(2)声明系统调用服务例程
sudo gedit /usr/src/linux-source-5.0.0/include/linux/syscalls.h
5、开始编译内核
用下面这条命令查漏补缺
sudo apt-get install libncurses5-dev make openssl libssl-dev bison flex
然后定位到,源码在的目录,也就是解压后放的目录
sudo make menuconfig
然后会出现以下界面,根据下面的图片所指的按钮来,通过左右键来确定光标停在选的按钮上,enter键是确定键
如果是要放开 mmap 的内存限制,可以修改如下参数(/ 可以进入查找):
CONFIG_EXPERT = y
CONFIG_X86_PAT = n
CONFIG_STRICT_DEVMEM = n
光标移动到 save 处,entry,跟着点击 exit
准备工作做好后,开始编译,耗时最长(大概2小时)
sudo make -j2 2>/home/qhc/error.txt // 使用2个线程进行编译
6安装内核
还是在原来的目录路径下,安装模块
sudo make modules_install
安装内核
sudo make install
7使用新内核
(1)创建initrd文件
sudo mkinitramfs -o /boot/initrd.img-5.0.0
(2)在linux开机界面添加 grub 引导界面
修改配置文件
sudo gedit /etc/default/grub
(3)更新grub引导列表
sudo update-grub
(4)重启,选择新内核
8编写测试 自定义系统调用的程序
(1)编写 test.c 文件,随便放哪
#include <unistd.h>
#include <sys/syscall.h>
#include <stdio.h>
#define _SYSCALL_MYSETNICE_ 335 // 335,刚才添加的系统调用号
#define EFALUT 14
int main() {
int pid, flag, nicevalue;
int prev_prio, prev_nice, cur_prio, cur_nice;
int result;
printf("Please input variable(pid, flag, nicevalue): ");
scanf("%d%d%d", &pid, &flag, &nicevalue);
result = syscall(_SYSCALL_MYSETNICE_, pid, 0, nicevalue, &prev_prio, &prev_nice);
if (result == EFALUT) {
printf("ERROR!");
return 1;
}
if (flag == 1) {
syscall(_SYSCALL_MYSETNICE_, pid, 1, nicevalue, &cur_prio, &cur_nice);
printf("Original priority is: [%d], original nice is [%d]\n", prev_prio,prev_nice);
printf("Current priority is : [%d], current nice is [%d]\n", cur_prio,cur_nice);
}
else if (flag == 0) {
printf("Current priority is : [%d], current nice is [%d]\n", prev_prio,prev_nice);
}
return 0;
}
(2)利用 gcc 编译 test.c
(3)开始测试