【OS】操作系统-实验一:添加系统调用
操作环境:
- 主机:MacOS 10.13.3
- 虚拟机软件:Parallels Desktop
- Linux:Ubuntu 16.04 Kernal 4.13.0-36-generic
实验要求:
- 添加一个系统调用,实现对指定进程的 nice 值的修改或读取功能,并返回进程最新的 nice 值及优先级 prio。建议调用原型为:
int mysetnice (pid_t pid, int flag, int nicevalue, void_ user * prio, void__ user* nice);
/*
参数含义:
pid:进程 ID.
flag:若值为 0,表示读取 nice 值;若值为 1,表示修改 nice 值。
prio、nice:指向进程当前优先级及 nice 值。
返回值:系统调用成功时返回 0,失败时返回错误码 EFAULT。
*/
写一个简单的应用程序测试(1) 中添加的系统调用。
若程序中调用了 Linux 的内核函数,要求深入阅读相关函数源码。
操作步骤:
- 编辑
./linux-4.14.35/arch/x86/entry/syscalls/syscall_64.tbl
,添加sys_aeonnisetnice
并指定调用号为666
- 编辑
./linux-4.14.35/include/linux/syscalls.h
添加服务的原型声明:
- 编辑
./linux-4.14.35/kernel/sys.c
添加服务的实现代码:
- 安装必要的软件:
$ sudo apt-get install build-essencial
$ sudo apt-get install libncurses5-dev libssl-dev
- 下载内核源代码、解压:
$ wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.14.35.tar.xz
$ xz -d linux-4.14.35.tar.xz
$ tar -xvf linux-4.14.35.tar
$ sudo chmod 777 ./linux-4.14.35
- 开始编译内核:
$ cd ./linux-4.14.35
$ sudo su
make menuconfig
make # 尝试使用 make -j 参数,但是会出现问题,似乎自动注销了
make modules
make modules_install
make install
update-grub2
- 写一个测试程序
testCall.c
:
- 编译
testCall.c
:$ gcc testCall.c -o testCall
- 重启系统,进入新内核,运行:
$ ./testCall
- 接着运行
dmesg
可以看到系统调用中printk
函数的输出:
结果:
- 成功编译并运行了
4.14.35
版本的内核。 - 加入了自己的系统调用,并成功测试运行,成功读写进程的 nice 值
附录:
- 系统调用服务的实现代码:
SYSCALL_DEFINE5(aeonnisetnice,pid_t,pid,int,flag,int,nicevalue,void __user*,prio,void __user*,nice)
{
struct pid * kpid;
struct task_struct * task;
kpid = find_get_pid(pid);/* 返回pid */
task = pid_task(kpid, PIDTYPE_PID);/* 返回task_struct */
int n;
n = task_nice(task);/* 返回进程当前nice值 */
int p;
p = task_prio(task);
if(flag == 1)
{
set_user_nice(task, nicevalue);/* 修改进程nice值 */
printk("Modified nice:%d\n", nicevalue);
n = task_nice(task);
copy_to_user(nice,&n,sizeof(n));
copy_to_user(prio,&p,sizeof(p));
return 0;
}
else if(flag == 0)
{
printk("nice value is %d\n", n);
printk("priority: %d\n", p);
copy_to_user(nice,&n,sizeof(n));
copy_to_user(prio,&p,sizeof(p));
return 0;
}
return EFAULT;
}
- 测试代码
testCall.c
:
#define _GNU_SOURCE
#define _AEONNI_SETNICE_ 666
#include <unistd.h>
#include<sys/syscall.h>
#include<stdio.h>
#include<stdlib.h>
int main(){
pid_t pid;
int nicevalue;
int flag;
int prio = 0;
int nice = 0;
int *p;
int *n;
p = &prio;
n = &nice;
printf("Enter pid:\n");
scanf("%d", &pid);
printf("pid success \nEnter nice:\n");
scanf("%d", &nicevalue);
printf("nice sucess\nEnter flag:\n");
scanf("%d", &flag);
syscall(_AEONNI_SETNICE_, pid, flag, nicevalue, p, n);
printf("Now nice is %d\n,prio is %d\n",nice,prio);
return 0;
}