欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

实验一:Linux内核编译及添加系统调用

程序员文章站 2022-05-02 20:23:06
...

实验一:Linux内核编译及添加系统调用

一、实验目的

  • 理解Linux系统处理系统调用的流程
  • 增加一个系统调用

二、实验内容

  • nice,可以理解为谦让度,CPU在选择进程时根据优先级prio选择,当nice值越高,可理解为这个进程越是谦让,即优先级越低

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

    建议调用原型为:

    ​ Int mysetnice(pid_t pid, int flag, int nicevalue,void_userprio,void_usernice)

    ​ 参数含义:

    ​ pid:进程ID

    ​ flag:若值为0,表示读取nice值;若值为1表示修改nice值。

    ​ prio,nice:指向进程当前优先级及nice值。

    ​ 返回值:系统调用成功时返回0,失败时返回错误码EFAULT。

  • 写一个简单的应用程序测试系统调用

  • 深入阅读相关函数源码

三、流程图

安装虚拟机
安装ubuntu
下载解压内核
增加系统调用
申明系统调用
编写函数实现系统调用
配置内核
编译内核及模块
安装内核重启系统
编写函数测试系统调用
阅读相关函数源码

四、具体实现

  • 安装虚拟机及ubuntu

    按指导来问题不大,在可行前提下,分配处理器选择4核或以上

    大小分配60G左右!

    https://jingyan.baidu.com/article/f96699bb147a73894e3c1b2e.html

  • 开启系统,打开terminal,进入管理员模式

    打开termintal: ctrl+alt+t

    管理员模式: 输入 sudo su 输入用户密码进入管理员模式

  • 下载解压内核

    下载内核: 输入 wget http://mirrors.ustc.edu.cn/kernel.org/linux/kernel/v4.x/linux-4.4.196.tar.xz

    解压内核: 输入 tar -xvJf linux-4.4.196.tar.xz

  • 系统调用

    装各种包 输入 sudo apt-get install vim libncurses5-dev make openssl libssl-dev bison flex ctags

实验一:Linux内核编译及添加系统调用

添加系统调用号 进入内核:cd linux-4.4.196 # 之后的操作都是在这个目录下

​ 编辑调用表:vim arch/x86/entry/syscalls/syscall_64.tbl

​ 输入G (跳末行)上行到300多行 ,输入i (进入编辑模式)

​ 输入如图
实验一:Linux内核编译及添加系统调用

​ 按ESC键 退出编辑模式 输入 :wq 保存并退出

申明系统调用 vim include/linux/syscalls.h

​ 输入 G i 添加如下

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

​ 按ESC键 退出编辑模式 输入 :wq 保存并退出

实现调用 vim kernel/sys.c

​ 输入 G i 添加如下

SYSCALL_DEFINE5 (mysetnice,pid_t,pid,int,flag,int,nicevalue,void __user*,prio,void __user*,nice){
    //SYSCALL_DEFINEN中N表示系统调用所需要的参数个数,我们的是5个
     struct task_struct *p;//进程结构体指针
     struct pid *id;//pid结构体
     int m,n;
     id=find_get_pid(pid);//通过传入的pid_t pid得到id结构体 
     p=pid_task(id,PIDTYPE_PID);//通过id得到指定进程,PIDTYPE_PID指的是进程类型的pid 
     m=task_nice(p);     //通过p得到nice值 
     n=task_prio(p);     //通过p得到prio值(优先级) 
     if(flag==0){//读取 
        copy_to_user(nice,(void*)&m,sizeof(m));//将m的地址强转为void *类型 
        copy_to_user(prio,(void*)&n,sizeof(n));
        return 0;
     }
     else if(flag==1){//修改 
        printk("nice value before modified:%d\n",m); 
        set_user_nice(p,nicevalue);//修改nice的值
        return 0;
     } 
     printk("syscall failed!");
     return EFAULT; 
}

​ 按ESC键 退出编辑模式 输入 :wq 保存并退出

  • 配置编译内核

    输入 make mrproper

    输入 make clean

    输入 make menuconfig

    (terminal窗口最大化)

    选择Save 回车确定 回车确定 选择Exit

实验一:Linux内核编译及添加系统调用

输入 make -j4

​ (-j4表示4线程编译,耗费较长,无视warning,跳出error可以ctrl+c结束了,出错了就没必要再编译了,看看是否漏掉步骤,根据跳出的error解决)

  • 安装内核重启系统

    输入 make modules

    输入 make modules_install

    输入 make install

    输入 update-grub2

    输入 reboot

    重启后 ctrl+alt+t 打开terminal 输入 sudo su 进入管理员模式

    输入 uname -a 如果显示的是下载的内核 这里是4.4.196 表明编译成功

  • 编写函数测试用

    输入 vim exp_1_test.c 新建C文件测试调用

    输入i (进入编辑模式)

    编写代码如下

    #include<stdio.h>
    #include<unistd.h>
    #include<sys/syscall.h>
    #define __NR_mysyscall 326
    int main(){
            int nice,prio;
            pid_t id;
    	    id=getpid();
    
            printf("----------------read-----------------\n\n");
            syscall(__NR_mysyscall,id,0,NULL,&prio,&nice);
            printf("before modified:pid:%d,prio:%d,nice:%d\r\n",id,prio,nice);
    
    
            printf("-----------------set-------------------\n\n");
            printf("syscall(__NR_mysyscall,id,1,-8,&prio,&nice);\n");
            syscall(__NR_mysyscall,id,1,-8,&prio,&nice);
    
            printf("------------------read-----------------\n\n");
            syscall(__NR_mysyscall,id,0,NULL,&prio,&nice);
            printf("modified:pid:%d,prio:%d,nice:%d\r\n",id,prio,nice);
            return 0;
    }
    

    ​ 按ESC键 退出编辑模式 输入 :wq 保存并退出

    输入 gcc exp_1_test.c 编译C文件

    输入 ./a.out 查看结果

  • 相关内核源码阅读

    输入 cd linux-4.4.196 进入目录

    输入 sudo ctags -R * (一些准备工作)

    输入 vim kernel/sys.c 就是之前实现调用的

    这里以查看set_user_nice函数及nice定义为例,可以此类推

实验一:Linux内核编译及添加系统调用

这里光标移动到如图 set_user_nice 函数

输入 ctrl + ] 进入函数 (退出则是c trl +T)

显示如图

实验一:Linux内核编译及添加系统调用

光标移动到 MIN_NICE 输入 ctrl + ] 进入

显示如图

实验一:Linux内核编译及添加系统调用