HDU操作系统课程设计实验一

您所在的位置:网站首页 nice函数用法 HDU操作系统课程设计实验一

HDU操作系统课程设计实验一

2023-12-23 10:40| 来源: 网络整理| 查看: 265

HDU操作系统课程设计实验一 实验一:Linux内核编译及添加系统调用一、设计目的二、内容要求三、实验内容修改Linux内核标签添加系统调用编译内核显示当前系统名称和版本的系统调用修改nice和prio值的系统调用改变主机名称为自定义字符串的系统调用 四、实验核心代码

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

这是一个很简单、基础的实验,只需要看懂源码,然后在源码中稍作修改就行。注意:编译内核花费时间比较长,长则一天,短则2-3小时,如果用虚拟机记得多开机器核心数目(机器核心数目越多越快,但不要超过物理机的核心数目)和内存(内存不足会导致中途编译失败),最好一次成功。

一、设计目的

Linux是开源操作系统,用户可以根据自身系统需要裁剪、修改内核,定制出功能更加合适、运行效率更高的系统,因此,编译Linux内核是进行内核开发的必要基本功。 在系统中根据需要添加新的系统调用是修改内核的一种常用手段,通过本次实验,读者应理解Linux系统处理系统调用的流程以及增加系统调用的方法。

二、内容要求

1、内核修改时有自己标签,用 dmesg验证 2、Linux内核标签(系统启动显示一次) 3、显示当前系统名称和版本的系统调用 4、修改nice和prio值的系统调用功能 5、改变主机名称为自定义字符串的系统调用

三、实验内容 修改Linux内核标签

找到init/main.c中的start_kernel函数,加入一句pr_notice(“学号 姓名”);//pr_notice()用来打印内核日志,可以用dmesg命令查看代码。

添加系统调用

1.分配系统调用号,修改系统调用表 查看系统调用表(arch/x86/entry/syscalls/syscall_64.tbl),每个系统调用在表中占一个表项,其格式为,在表中为系统调用添加一个系统调用号。 2.申明系统调用服务例程原型 Linux系统调用服务例程的原型声明在文件linux-4.12/include/linux/syscalls.h中,可在文件末尾添加类似asmlinkage long sys_zwhsyscall(void);的系统调用代码。 3.实现系统调用服务例程 下面为新调用编写服务例程,通常添加在sys.c文件中,其完整路径为linux-5.9.1/kernel/sys.c。具体编程思路可以看下面。 4.重新编译内核 5.编写用户态程序测试系统调用

编译内核 在开始完全重新编译之前,需要用makemrproper命令清除残留的.config和.o文件。运行make menuconfig命令配置内核。内核配置完成后,执行make命令,开始编译内核。执行make modules命令,开始编译模块。执行make modules_install命令,开始安装模块。执行make install命令,开始安装内核。执行update-grub2命令,自动修改grub引导程序。执行reboot命令,重启系统。 显示当前系统名称和版本的系统调用

显示当前系统名称和版本的系统调用函数可以参考linux-5.9.1/kernel/sys.c中的newuname函数。 linux-5.9.1的newuname函数(不一定适用于其他版本) SYSCALL_DEFINEX类型函数的格式:SYSCALL_DEFINEX(函数名,参数变量类型1,参数变量名1,…,…参数变量类型X,参数变量名X),系统调用函数的定义格式。

SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name) { struct new_utsname tmp; down_read(&uts_sem); memcpy(&tmp, utsname(), sizeof(tmp)); up_read(&uts_sem); if (copy_to_user(name, &tmp, sizeof(tmp))) return -EFAULT; if (override_release(name->release, sizeof(name->release))) return -EFAULT; if (override_architecture(name)) return -EFAULT; return 0; } 修改nice和prio值的系统调用

修改nice和prio值的系统调用可以通过set_user_nice()函数改变进程的nice值,从而改变prio值,实现系统调用的功能。

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) { printk("Change nice: %d ,prio: %d ",n,p); set_user_nice(task, nicevalue);/* 修改进程nice值 */ n = task_nice(task);/*重新取得进程nice值*/ p = task_prio(task);/*重新获取进程prio值 这里和参考资料不一样!!! */ printk("to nice: %d ,prio: %d\n",n,p); copy_to_user(nice,&n,sizeof(n));/*将nice值拷贝到用户空间*/ copy_to_user(prio,&p,sizeof(p));/*将prio值拷贝到用户空间*/ return 0; } else if(flag == 0) { printk("nice : %d ,prio: %d\n",n,p); copy_to_user(nice,&n,sizeof(n));/*将nice值拷贝到用户空间*/ copy_to_user(prio,&p,sizeof(p));/*将prio值拷贝到用户空间*/ return 0; } return EFAULT; } 改变主机名称为自定义字符串的系统调用

改变主机名称为自定义字符串的系统调用函数可以参考linux-5.9.1/kernel/sys.c中的sethostname函数。 可以用uname -n命令来查看,修改hostname但不修改hostname的映射可能会导致shell命令使用警告(不影响使用),重启(hostname会改为默认值)或添加映射,即可解决。 linux-5.9.1的sethostname函数(不一定适用于其他版本)

SYSCALL_DEFINE2(sethostname, char __user *, name, int, len) { int errno; char tmp[__NEW_UTS_LEN]; if (!ns_capable(current->nsproxy->uts_ns->user_ns, CAP_SYS_ADMIN)) return -EPERM; if (len __NEW_UTS_LEN) return -EINVAL; errno = -EFAULT; if (!copy_from_user(tmp, name, len)) { struct new_utsname *u; down_write(&uts_sem); u = utsname(); memcpy(u->nodename, tmp, len); memset(u->nodename + len, 0, sizeof(u->nodename) - len); errno = 0; uts_proc_notify(UTS_PROC_HOSTNAME); up_write(&uts_sem); } return errno; } 四、实验核心代码

sys.c:系统调用函数代码。 mychangename.c:测试mychangename的系统调用,功能是改变主机名称为自定义字符串的系统调用。 mysetnice.c:测试mysetnice系统调用的程序,功能是修改nice和prio值的系统调用功能。 myshowname.c:测试myshowname系统调用的程序,功能是显示当前系统名称和版本的系统调用。 完整代码详见:HDU-operation-system-course-design-code/实验一/



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3