操作系统实验一

一、前言

记录杭电操作系统实验一:编译内核&增加nice系统调用.本文仅严格记录本人成功的实验流程,方便日后修改.

二、实验准备

三、主要参考资料

四、 实验过程

4.1编译内核

4.2增加系统调用

主要参考资料:添加一个系统调用,实现对指定进程的nice值的修改或读取功能,并返回系统最新的nice值即优先级prio

以下命令在/usr/src/linux-5.3.6中执行

4.2.1 题目描述
  1. 添加一个系统调用,实现对指定进程的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. 写一个简单的应用程序测试
4.2.2 步骤描述
  • 修改系统调用表
  • 申明系统调用服务例程原型
  • 实现系统调用服务例程
  • 重新编译
  • 编写测试函数进行测试
4.2.3 具体操作
  1. 修改系统调用表

    sudo vim arch/x86/entry/syscalls/syscall_64.tbl

    1571416426714

    一定要使用__x64 否则报如下错误

  2. 申明系统调用服务例程原型

    sudo vim include/linux/syscalls.h

    添加以下代码

    asmlinkage long sys_mysetnice(pid_t pid,int flag,int nicevalue,void __user*prio,void __user*nice);

  3. 实现系统调用服务例程

    vim kernel/sys.c

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    SYSCALL_DEFINE5(mysetnice,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);/*返回进程当前prio值*/
    if(flag == 1)
    {
    set_user_nice(task, nicevalue);/* 修改进程nice值 */
    n = task_nice(task);/*重新取得进程nice值*/
    p = task_prio(task);/*重新获取进程prio值 这里和参考资料不一样!!! */
    copy_to_user(nice,&n,sizeof(n));/*将nice值拷贝到用户空间*/
    copy_to_user(prio,&p,sizeof(p));/*将prio值拷贝到用户空间*/
    return 0;
    }
    else if(flag == 0)
    {
    copy_to_user(nice,&n,sizeof(n));/*将nice值拷贝到用户空间*/
    copy_to_user(prio,&p,sizeof(p));/*将prio值拷贝到用户空间*/
    return 0;
    }
    return EFAULT;
    }
  4. 编译

    使用ccache加快编译

    参考文档:ubuntu 使用ccache加快linux内核编译速度 注意将usr改为自己的用户名,6G改为10G

    1
    2
    3
    4
    5
    6
    $sudo make clean
    #仍采用原内核配置文件
    $sudo make localmodconfig #使用localmodconfig加速编译
    $sudo make -j8 #使用多线程编译
    $sudo make modules_install
    $sudo make install

    整个过程大概只用了30分钟,编译完内核后一定要重启!!!!!

  5. 编写测试函数

    vim test.c

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    #define _GNU_SOURCE
    #include <unistd.h>
    #include<sys/syscall.h>
    #include<stdio.h>
    #include<stdlib.h>
    int main(){
    pid_t pid;
    int nicevalue;
    int flag;
    int p = 0;
    int n = 0;
    int *prio;
    int *nice;
    prio = &p;
    nice = &n;
    /*
    * 获取pid
    * */
    printf("请输入pid:\n");
    scanf("%d",&pid);
    /*
    * 获取nice;
    * */
    printf("pid赋值成功\n请输入nice:\n");
    scanf("%d",&nicevalue);
    /*
    * 获取flag;
    * */
    printf("nice赋值成功\n请输入flag:\n");
    scanf("%d",&flag);
    /*
    * 调用添加的系统调用;
    * */
    syscall(334,pid,flag,nicevalue,prio,nice);
    /*
    * 输出最新的prio以及nice;
    * */
    printf("现在的nice为%d\n,prio为%d\n",n,p);
    return 0;
    }
  6. 编译运行

    1
    2
    3
    top
    gcc test.c
    $./a.out