杭电操作系统实验一 Linux内核编译及添加系统调用

Linux内核编译及添加系统调用

1.实验要求:

  • (1)编译Linux内核;
  • (2)添加一个系统调用,实现对指定进程的nice值的修改或读取功能,并返回新的nice值及优先级prio。
2.调用原型:

int mysetnice(pid_t pid, int flag, int nicevalue, void __user* prio, void __user* nice);

参数含义:

  • pid:进程ID。
  • flag:若值为0,则表示读取nice值;若值为1,则表示修改nice值。
  • nicevalue:为指定进程设置新的nice值。
  • prio、nice:指向进程当前优先级及nice值。
  • 返回值:系统调用成功时返回0;失败时返回错误码EFAULT。
3.实现过程

3.1分配系统调用号,修改系统调用表(arch/x86/entry/syscalls/syscall_64.tbl),如图1所示:
图1:系统调用表
3.2 申明系统调用服务例程原型(include/linux/syscalls.h),如图2所示:
图2:调用服务例程原型
3.3 实现系统调用服务例程(kernel/sys.c)

//kernel/sys.c
SYSCALL_DEFINE5(mysetnice, pid_t, pid, int, flag, int, nicevalue, void __user*, prio, void __user*, nice) {
    struct pid* PID;
    struct task_struct* pcb;//进程控制块
    int cur_prio, cur_nice;

    PID = find_get_pid(pid);    //根据提供的pid号获取对应的PID
    pcb = pid_task(PID, PIDTYPE_PID);   //参数type是pid_type型变量,此变量是一个枚举型变量.PIDTYPE_PID是进程的进程号
    
    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));
    //将内核空间中的数据拷贝到用户空间
    
    switch(flag) {
        case 0:
            printk("READ SUCCESSFULLY!\n");
            return 0;
        case 1:
            if( nicevalue >= -20 && nicevalue <= 19) {
                set_user_nice(pcb, nicevalue);
                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));
                printk("SET SUCCESSFULLY!\n");
                return 0;
            } else {
                printk("SET FAILED.INVALID NICEVALUE!\n");
                return EFAULT;
            }
        default:
            printk("SET FAILED.INVALID FLAG!\n");
            return EFAULT;
    }
}

3.4 重新编译内核
在linux-4.16.3目录下执行以下命令:

//清除残留的.config和.o文件
make mrproper
//配置内核
make menuconfig

其中,在make menuconfig时选择General Setup进入,更改版本发行名,如图3所示:
图3:版本发行名
然后继续在当前目录下执行以下命令:

//编译内核
make -j8
//编译模块
make modules
//安装模块
make modules_install
//安装内核
make install
//配置grub引导程序
update-grub2
//重启系统
reboot

系统重启后在Ubuntu高级选项中选择如图4所示内核版本:
图4:选择内核版本
重启后在命令行执行以下使用uname -a命令查看当前内核版本,结果如图5所示:
图5:选择内核版本

4.验证

4.1 编写测试代码

#include <unistd.h>
#include <sys/syscall.h>
#include <stdio.h>
#define _SYSCALL_MYSETNICE_ 333
#define EFALUT 14

int main()
{
    int pid, flag, nicevalue;
    int cur_prio, cur_nice;
    
    printf("Please input variable(pid, flag, nicevalue): ");
    scanf("%d%d%d", &pid,  &flag,  &nicevalue);

    syscall(_SYSCALL_MYSETNICE_, pid, flag, nicevalue, &cur_prio, &cur_nice);
    printf("Priority value is : [%d],  nice value is [%d]\n", cur_prio, cur_nice);

    return 0;
}

4.2 使用gcc编译后运行,运行结果如图6所示:
图6:运行测试程序
接下来使用当前测试程序对编写的内核调用进行测试。当输入的pid错误时,程序的输出如图7所示:
图7:输入错误pid时程序的输出
当输入的pid正确时,可以正确查看进程nice值和prio值。先在命令行使用top命令实时查看进程pid,nice值和优先级,如图8所示:
图8:实时查看进程的pid,nice值和优先级
我们选择pid为1861的进程进行nice值和优先级的查看,如图9所示:
图9:查看指定pid的进程nice值和优先级
在命令行执行dmesg命令查看输出,结果如图10所示:
图10:使用dmesg查看printk的输出
由图10可知,系统调用返回了指定进程的nice值和优先级,且结果与top中的结果相同。接下来我们进行pid正常,flag值有误时的测试,输入如图11所示:
图11:输入flag的值有误时
接下来执行dmesg命令,结果如图12所示:
图12:输入flag的值有误时
由图11和图12可知,当输入的pid正确,flag值有误时,系统调用将正确返回指定进程的nice值和优先级,但不会对进程的nice值进行修改,同时也将返回flag有误的错误信息。接下来测试pid正常,flag值为1,nice value有效的情况,如图13所示:
图13:输入正确时
执行dmesg命令,输出如图14所示:
图14:输入正确时
由图13和图14可知,当输入的pid,flag和nice值均正确时,系统调用将正确修改进程的nice值,并将修改后的结果返回,输出修改成功的信息。接下来进行pid正常,flag值为1,nice value有误时的测试。测试输入如图15所示:
图15:输入的nice值有误时
执行dmesg命令,输出如图16所示:
图16:输入的nice值有误时
由图15和图16可知,当输入的pid,flag正确,但nice值有误时,系统调用将不会对进程的nice值进行修改,但会返回进程原先的nice值,并输出修改失败,nice值有误的错误提示信息。

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
杭电实验1所涉及的内容是Linux内核编译添加系统调用。 在这个实验中,首先需要了解Linux内核编译过程。Linux内核是操作系统的核心部分,由C语言编写。编译内核的目的是为了生成可执行的内核镜像文件,即vmlinuz。内核编译的一个重要环节是配置内核,确定编译时的各种选项和功能。 首先,需要从官方网站(https://www.kernel.org/)上获取最新的Linux内核源代码。在命令行中使用wget命令下载源代码文件,并解压缩到合适的目录。 接下来,进入源代码目录,使用make menuconfig命令配置内核。此命令会打开一个文本界面菜单,可以选择需要的功能和驱动,并进行一些优化设置。可以根据实验要求选择需要的功能,也可以使用默认配置。 配置完成后,使用make命令开始编译内核编译过程需要一定时间,取决于计算机性能和内核大小。编译完成后会生成可执行的内核镜像文件vmlinuz。 接下来是添加新的系统调用系统调用是应用程序与操作系统之间的接口,用于请求操作系统提供服务。在实验中,需要在内核添加一个自定义的系统调用。 首先,在内核源代码中找到系统调用表文件syscalls.h,添加新的系统调用的函数原型。然后,在内核的核心文件kernel/sys.c中实现系统调用的功能代码。 在添加系统调用的功能代码后,需要编译内核并安装。使用make命令编译内核,并使用make install命令将编译好的内核安装到系统中。安装完成后,重启计算机,系统就会使用新的内核和新添加系统调用。 总结来说,杭电实验1是介绍了Linux内核编译过程和系统调用添加方法。通过这个实验,可以了解Linux内核的基本结构和编译过程,以及如何在内核添加新的系统调用。这对于深入理解操作系统内核开发是非常有帮助的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值