HDU操作系统 实验1.2·1.3——设计和添加Linux系统调用

HDU操作系统 实验1.2·1.3——设计和添加Linux系统调用操作系统实验一

实验介绍

上篇文章已经介绍了Linux内核的编译与安装,我们已经掌握了Linux系统内核的编译和启用。接下来,我们将学习掌握如何添加Linux的系统调用,学习掌握测试Linux系统调用。


什么是系统调用(system call)

由操作系统提供的供所有系统调用的程序接口集合;用户程序通常只在用户态下运行,当用户程序想要调用只能在内核态运行的子程序时,所以操作系统需要提供访问这些内核态运行的程序的接口,这些接口的集合就叫做系统调用。简要的说,系统调用是内核向用户进程提供服务的唯一方法。应用程序有时会需要一些危险的、权限很高的指令,如果把这些权限放心地交给用户程序是很危险的(比如一个进程可能修改另一个进程的内存区,导致其不能运行),但是又不能完全不给这些权限。于是有了系统调用,危险的指令被包装成系统调用,用户程序只能调用而无权自己运行那些危险的指令。另外,计算机硬件的资源是有限的,为了更好的管理这些资源,所有的资源都由操作系统控制,进程只能向操作系统请求这些资源。操作系统是这些资源的唯一入口,这个入口就是系统调用。


实验准备

华为云服务器,OpenEuler操作系统,Xshell远程登录软件(可选)

在做此实验时需要多次编译内核,如果使用VMware本地虚拟机来进行实验,8个线程编译内核耗时过多,所以使用华为云服务器,购买32线程的云服务器编译内核1分钟就搞定,这样会节省很多时间,而且不用担心编译内核时出现bug导致本地虚拟机死机。

HDU操作系统 实验1.2·1.3——设计和添加Linux系统调用

HDU操作系统 实验1.2·1.3——设计和添加Linux系统调用


本次实验全程在华为云服务器下进行

掌握Linux内核的编译与安装请参考https://blog.csdn.net/weixin_/article/details/?spm=1001.2014.3001.5501


开始实验

1.2——掌握Linux系统调用基本概念

添加一个新的系统调用,通过内核打印调试语句printk打印自己的学号

1.将系统调用的函数加入到syscalls数组中

输入

cd kernel-kernel-4.19/include/uapi/asm-generic/ /*进入操作目录*/ vim unistd.h /*编辑该文件*/

在该文件中输入

#define __NR_hyb 294 __SYSCALL(__NR_hyb, sys_hyb)

HDU操作系统 实验1.2·1.3——设计和添加Linux系统调用

 如上图所示(注意坑点1:在编辑该文件时,找到文件最后一行为294,在其上加入系统调用函数,然后将最后的294改为295。后续实验添加调用函数后将295改为296以此类推。)

Esc退出编辑模式,:wq保存并退出,cd /root返回桌面

2.在头文件中声明系统调用函数

输入

cd kernel-kernel-4.19/include/linux/ /*进入头文件目录*/ vim syscalls.h /*编辑该文件*/

在该文件中输入

asmlinkage long sys_hyb(void);

HDU操作系统 实验1.2·1.3——设计和添加Linux系统调用

如上图所示(注意坑点2: 在编辑该文件时,不要将声明的函数加在 if 语句中,即将该声明放在#endif下面)

Esc退出编辑模式,:wq保存并退出,cd /root返回桌面

3.添加函数体

输入

cd kernel-kernel-4.19/kernel/ /*进入目录*/ vim sys.c /*在该文件中添加需要的函数体*/

HDU操作系统 实验1.2·1.3——设计和添加Linux系统调用

 在文件中添加如上图所示的内容(这里的坑点与坑点2相同)

Esc退出编辑模式,:wq保存并退出,cd /root返回桌面

4.编译、安装内核

输入

make -j 32 /*32为线程数,虚拟机为多少这里就写多少*/ make modules_install make install reboot

此操作时间取决于线程数量,越多耗时越短(注意坑点3:类似的操作都需要在kernel-kernel-4.19目录下进行)

5.编写测试代码

参考课本

输入

vim hyb.c /*新建一个名为hyb.c的C语言文件*/

HDU操作系统 实验1.2·1.3——设计和添加Linux系统调用

 输入如上图所示的内容

Esc退出编辑模式,:wq保存并退出,cd /root返回桌面

6.编译生成hyb_0文件

输入

gcc hyb.c -o hyb_0

HDU操作系统 实验1.2·1.3——设计和添加Linux系统调用

如图所示,生成了一个名为hyb_0的文件

输入

./hyb_0 /*查看编译运行结果*/

HDU操作系统 实验1.2·1.3——设计和添加Linux系统调用

 如图所示即为1.2实验结果


1.3——设计和添加系统调用

经过1.2的步骤,对于1.3来说,大致的过程与1.2不尽相同(三步走:写调用函数——编译安装内核——编写测试代码)

题目一(必做):修改或返回指定进程的优先级(nice值和prio值)

提示:可能参考的内核函数:set_user_nice()

1.将系统调用的函数加入到syscalls数组中

输入

cd kernel-kernel-4.19/include/uapi/asm-generic/ /*进入操作目录*/ vim unistd.h /*编辑该文件*/

在该文件中输入

#define __NR_hybsetnice 295 __SYSCALL(__NR_hybsetnice, sys_hybsetnice)

HDU操作系统 实验1.2·1.3——设计和添加Linux系统调用

 如图所示,同理,根据上文介绍将末尾的数字295改为296

Esc退出编辑模式,:wq保存并退出,cd /root返回桌面

2.在头文件中声明系统调用函数

输入

cd kernel-kernel-4.19/include/linux/ /*进入头文件目录*/ vim syscalls.h /*编辑该文件*/

在该文件中输入

HDU操作系统 实验1.2·1.3——设计和添加Linux系统调用

 (这里的坑点与坑点2相同)

3.添加函数体

输入

cd kernel-kernel-4.19/kernel/ /*进入目录*/ vim sys.c /*在该文件中添加需要的函数体*/

HDU操作系统 实验1.2·1.3——设计和添加Linux系统调用

在该文件中添加函数体,注意格式正确(坑点与坑点2相同) 

Esc退出编辑模式,:wq保存并退出,cd /root返回桌面

4.编译、安装内核

输入

make -j 32 /*32为线程数,虚拟机为多少这里就写多少*/ make modules_install make install reboot

5.编写测试代码

输入

vim hyb_1.c /*生成一个C语言文件并且编辑*/

HDU操作系统 实验1.2·1.3——设计和添加Linux系统调用 Esc退出编辑模式,:wq保存并退出,cd /root返回桌面

 6.编译生成hyb_1文件

输入

gcc hyb_1.c -o hyb_1

HDU操作系统 实验1.2·1.3——设计和添加Linux系统调用

 我们可以看到已经生成了hyb_1编译后的文件

HDU操作系统 实验1.2·1.3——设计和添加Linux系统调用

如图所示即为运行后的实验结果 

题目一小结:

在实验中,需要用到 Linux top命令行操作,什么是top?

top 命令可以动态地持续监听进程地运行状态,与此同时,该命令还提供了一个交互界面,用户可以根据需要,人性化地定制自己的输出,进而更清楚地了进程的运行状态。

HDU操作系统 实验1.2·1.3——设计和添加Linux系统调用

 在上图中看到有PID  USER  PR  NI  VIRT  RES  SHR  S  %CPU  %MEM  TIME+ COMMAND值,这里着重注意PR值和NI值。(PR值——优先级;NI值——nice值,有+有-,负值表示高优先级,正值表示低优先级)也就是题目中的nice prio值。

那么,什么是nice值和prio值?

通俗来说,nice值越低,证明这个进程越不nice(这个进程很霸道)抢占CPU的能力就越强,所以,值越低,进程的优先级越高。prio值即为priority值,为top命令中看到的PR值,优先级。


 选做题目二

返回指定进程的内存管理信息,如进程可执行代码的起始及结束地址、已初始化数据的起始及结束地址、用户态堆栈起始地址、堆起始地址等。
提示:可能参考的内核函数:get_task_mm()
https://blog.csdn.net/weixin_/article/details/
在进行此实验时,我们需要知道内核函数返回参数的说明,根据这个网址,可以查询。
HDU操作系统 实验1.2·1.3——设计和添加Linux系统调用
HDU操作系统 实验1.2·1.3——设计和添加Linux系统调用

 (牢记三步走战术)

1.将系统调用的函数加入到syscalls数组中

输入

cd kernel-kernel-4.19/include/uapi/asm-generic/ /*进入操作目录*/ vim unistd.h /*编辑该文件*/

 HDU操作系统 实验1.2·1.3——设计和添加Linux系统调用

 同理,将下方的数字296改为297。

 Esc退出编辑模式,:wq保存并退出,cd /root返回桌面

2.在头文件中声明系统调用函数

cd kernel-kernel-4.19/include/linux/ /*进入头文件目录*/ vim syscalls.h /*编辑该文件*/

在文件中输入

HDU操作系统 实验1.2·1.3——设计和添加Linux系统调用

 (这里的坑点与坑点2相同)

3.添加函数体

输入

cd kernel-kernel-4.19/kernel/ /*进入目录*/ vim sys.c /*在该文件中添加需要的函数体*/

HDU操作系统 实验1.2·1.3——设计和添加Linux系统调用

在该文件中添加函数体,注意格式正确(坑点与坑点2相同) 

Esc退出编辑模式,:wq保存并退出,cd /root返回桌面

4.编译、安装内核

输入

make -j 32 /*32为线程数,虚拟机为多少这里就写多少*/ make modules_install make install reboot

5.编写测试代码

输入

vim hyb_2.c

HDU操作系统 实验1.2·1.3——设计和添加Linux系统调用

 Esc退出编辑模式,:wq保存并退出,cd /root返回桌面

 6.编译生成hyb_2文件

输入

gcc hyb_2.c -o hyb_2

HDU操作系统 实验1.2·1.3——设计和添加Linux系统调用

 我们可以看到生成了名为hyb_2的文件,运行

在输入PID时,可以参考前面提到过的top命令,输入一个存在的PID,以防报错。

HDU操作系统 实验1.2·1.3——设计和添加Linux系统调用

 我们可以看到已经返回了6个想要的数据,而且ret=0为正确(ret=-1为错误)。

题目二小结:

题目要求输出6个需要的返回值,在参考资料后,我们发现这个内核函数中还有许许多多其他的返回参数,要学会举一反三。

至此,实验1.3已全部完成,与上一篇博客一起,就是操作系统实验课的实验一。


写在最后:

本次实验是一个很耗时的实验,但是理解掌握了实验的“三步走”方法(声明——加入——编写),这个实验也会迎刃而解。查阅了非常多的资料,网络上的博客也是良莠不齐,晦涩难懂,需要多多参透课本的内容。内核编译需要非常强大的CPU,购买32核64G内存的服务器可以在make modules_install时节省大量的时间(用完记得关!!!)

历经了很多次把内核编译崩溃的情况后,一定要冷静,仔细观察书写的代码有没有漏洞。有时候,往往那简单的一个” “、; 错误就会导致内核的编译失败(浪费了那么多时间还失败了真的很抓狂)。这就告诉我们,书写代码一定要规范仔细不可马虎。这个实验说难很难,说简单也很简单,不光只是1.3的两道题目,更要掌握其运行本质,这样才能在添加系统调用中如鱼得水。

文章写作时间仓促,如有错误请指正,如有问题请在评论区中提问。

加油!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/212309.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月18日 下午8:20
下一篇 2026年3月18日 下午8:20


相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号