您的位置:首页 > 教育 > 培训 > 天猫商城上一年度市场份额_城市分类信息网站系统_小网站怎么搜关键词_广告宣传网站

天猫商城上一年度市场份额_城市分类信息网站系统_小网站怎么搜关键词_广告宣传网站

2025/2/23 13:10:20 来源:https://blog.csdn.net/m0_73096566/article/details/142915585  浏览:    关键词:天猫商城上一年度市场份额_城市分类信息网站系统_小网站怎么搜关键词_广告宣传网站
天猫商城上一年度市场份额_城市分类信息网站系统_小网站怎么搜关键词_广告宣传网站

在 linux0.11 中添加自定义系统调用

linux 调用 system call 的过程

img

  1. 用户态发起系统调用
    在用户态程序中,调用系统调用的接口,通常是通过一个库函数(如 glibc)封装。这个库函数会触发 int 0x80 软中断。int 0x80 是 x86 平台用于进入内核态的中断指令。

  2. 进入内核态
    软中断会使 CPU 切换到内核态,并根据中断向量号(0x80)在中断向量表中查找对应的中断处理程序。对于 int 0x80,中断处理程序的入口位于内核的 system_call 函数中。

  3. 保存寄存器状态
    进入 system_call 函数时,CPU 会自动保存一部分寄存器状态(如 CSEIPEFLAGS 等),而内核会通过保存当前任务的寄存器状态(包括用户态的 pt_regs 结构),来保存调用前的 CPU 寄存器内容。

  4. 处理系统调用号和参数
    system_call 函数会从 eax 寄存器中读取系统调用号(用户态程序通过 int 0x80 前将系统调用号放入 eax),并根据该系统调用号在系统调用表(sys_call_table)中找到相应的内核态系统调用函数。用户态传递的参数通常存放在其他寄存器中,如 ebx, ecx, edx 等。

  5. 执行系统调用
    找到对应的系统调用函数后,内核会使用这些寄存器中的参数执行系统调用。系统调用完成后,返回值通常会放入 eax 寄存器中。

  6. 返回用户态
    系统调用完成后,内核会恢复用户态的寄存器状态(使用 pt_regs),并使用 iret 指令返回用户态。此时,用户态程序可以从 eax 中获取系统调用的返回值。

添加自定义的系统调用

修改系统调用总数:

cd ~/oslab/linux-0.11/kernel
vim system_call.s

img

向系统调用表中添加自定义的函数:

cd ~/oslab/linux-0.11/include/linux
vim sys.h

我添加了两个自定义的函数:

  • printIntVal(): 打印一个整数值。

  • strToNum(): 将一个数字字符串转换为整形。

添加自定义系统调用的声明和系统调用号定义

cd ~/oslab/linux-0.11/include
vim unistd.h

img

在这里插入图片描述

添加自定义系统调用的实现

cd ~/oslab/linux-0.11/kernel
vim selfdefine.c
#include <asm/segment.h> // 包含与内核段寄存器相关的函数,如 get_fs_byte 和 put_fs_long/*** 自定义系统调用 printIntVal,用于打印一个整数值。** @param a - 要打印的整数值* @return 无返回值*/
int printIntVal(int a)
{// 使用 printk 输出内核信息,打印传入的整数值printk("in system print int val: %d\n", a);
}/*** 自定义系统调用 strToNum,将字符串转换为整数,并存储结果到内存中。** @param str - 字符串的指针,从用户态传入的字符串。* @param str_len - 字符串的长度。* @param ret - 保存转换后结果的指针,返回转换的 long 类型整数。* @return 无返回值*/
int strToNum(char *str, int str_len, long *ret)
{long result = 0; // 存储转换后的结果char tmp;		 // 用于存储每次从用户空间读取的字符int i;			 // 循环计数器// 遍历传入的字符串,将其转换为整数for (i = 0; i < str_len; i++){// 使用 get_fs_byte 从用户空间读取字符串中的每个字符tmp = get_fs_byte(str + i);// 将字符转换为对应的数字,累加到 result 中// '0' 是字符的 ASCII 值,需要减去以获得实际的数字值result = result * 10 + tmp - '0';}// 使用 put_fs_long 将结果写回到用户空间中的 ret 指针指向的地址put_fs_long(result, ret);
}

写完自定义函数的实现之后记得将这个文件保存哦!

修改 makefile 文件

cd ~/oslab/linux-0.11/kernel
vim Makefile

我们需要修改两个地方:

  1. 在定义 OBJS 这里添加 selfdefine.o

img

  1. 添加依赖

    img

编译 linux0.11 内核

cd ~/oslab/linux-0.11
make clean
make

我不知道怎么通过修改 linux-0.11 的源代码生成用户态的系统调用接口,我就在 linux-0.11 编译号之后的系统中手动添加了!

添加用户态接口

cd ~/oslab

img

我们运行 mount-hdc 这个可执行文件,可以让我们在 ubantu 系统上编辑 linux0.11 系统中的文件。

./mount-hdc

现在我们需要提供用户态的系统调用接口:

vim ./hdc/usr/include/selfdefine.h
#ifndef _LINUX_SELFDEFINE_H
#define _LINUX_SELFDEFINE_H// 定义系统调用号
#define __NR_printIntVal  72
#define __NR_strToNum   73// 提供用户调用系统调用的接口// 系统调用:printval
static inline int printIntVal(int val) {int res;asm volatile("int $0x80"                       // 通过中断调用系统调用: "=a"(res)                       // 返回值保存在 eax 寄存器: "0"(__NR_printIntVal), "b"(val) // 系统调用号在 eax,参数在 ebx: "memory");return res;
}// 系统调用:str2num
static inline int strToNum(char *str, int str_len, long *ret) {int res;asm volatile("int $0x80"                                            // 通过中断调用系统调用: "=a"(res)                                            // 返回值保存在 eax 寄存器: "0"(__NR_strToNum), "b"(str), "c"(str_len), "d"(ret) // 参数传递: "memory");return res;
}#endif /* _LINUX_SELFDEFINE_H */

这里有个问题就是用户态的接口为啥要这么写呢?其实就是模仿着 linux-0.11 的源代码来写的:

img

上面是 open 系统调用的用户态接口,是不是差不多嘛!

编辑完成之后记得要保存哦!

编写测试程序

现在你所在的目录应该还是:

~/oslab

我们来编写测试程序:

vim ./hdc/usr/root/test.c
#include <stdio.h>
#include <selfdefine.h>
int main() {int val = 42;char str[] = "12345";long result;  // c 语言的早期标准,变量必须定义在函数的最前面printIntVal(val);strToNum(str, 5, &result);printf("Converted number: %ld\n", result);return 0;
}

编写好了之后保存!然后我们需要取消 hdc 目录的挂载!

umount hdc

运行测试

我们运行 run 程序

./run

编译 test.c

gcc test.c

运行 a.out

./a.out

img

可以看到成功了!

在这里插入图片描述

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com