实验三 系统调用
记录一些学习哈工大操作系统实验的学习笔记和心得
- Github地址 欢迎star ⭐️⭐️⭐️⭐️⭐️
- 课程实验楼环境
- 课程主页
- 课程视频
- 课程教材:
实验内容
- 需要实现的系统调用函数如下:
int iam(const char * name); // 将字符串内容保存到内核中
int whoami(char* name, unsigned int size); // 在内核中将iam()保存的信息拷贝到指定的用户地址空间中
- 测试
./iam zhaojiazhen
./whoami
zhaojiazhen
补充:调用系统调用和调用一个普通的自定义函数在代码上并没有什么区别,但是不同的是,系统调用可能会涉及到内核交互
- 系统调用函数通过使用call来讲系统调用的号传递到eax中,把参数传给其余寄存器,然后使用int 0x80中断
- 我们在这里直接实现了
sys_whoami
和sys_iam
,然后进行调用相当于直接执行了系统调用代码 - 传统应用代码,例如
printf
则是通过头文件中的syscall
来访问system_call.s
进而调用80中断来,然后调用sys_xxx
函数实现的
首先我们需要知道实现一个系统调用需要修改哪些部分(这部分需要重点理解):
- 在用户空间使用系统调用都是通过库函数或者直接调用
sys_call
sys_call1
sys_call2
sys_call3
- 目前最多只支持三个参数,因为保存参数的寄存器只有三个
sys_call
则是通过传入参数到int 0x80
实现的int 0x80
进行系统调用的原理是通过system_call.s
实现的system_call.s
通过system_call_table
实现,进而根据中断号调用系统调用函数- 综上所述:
- 我们需要在
unistd.h
添加有关__NR_IAM
和__NR_whoami
的系统调用号 - 在
system_call.s
中更新系统调用数量 - 在
linux/sys.h
中添加extern int sys_iam
extern int sys_whoami
- 在
call_table
数组中添加相关调用
完成上述修改后,还需要根据教程修改Makefile
- 修改
OBJS
- 修改
Dependices
通过教程我们可以发现,用户态和核心态数据交互所需要的函数为:
include/asm/segment.h/get_fs_byte
include/asm/segment.h/put_fs_byte
接下来就可以开始实现iam()
和 whoami()
函数了
- 在
kernel/
下创建who.c
- 参考代码如下:
-
int sys_iam(const char *name) { printk("hello, i'm sys_iam\n"); char tmp[maxSize]; int i; for (i = 0; i < maxSize; i++) { tmp[i] = get_fs_byte(name + i); if (tmp[i] == '\0') break; } if (i == maxSize) return -EINVAL; else { strcpy(msg, tmp); return i; } }
-
int sys_whoami(char *name, unsigned int size) { printk("hello, i'm sys_whoami\n"); int msg_size = 0; while (msg[msg_size] != '\0') msg_size++; if (size < msg_size) return -EINVAL; else { int i; for (i = 0; i < size; i++) { put_fs_byte(msg[i], name + i); if (msg[i] == '\0') break; } return i; } }
之后编译img镜像,进入linux0.11之后,编译iam
和whoami
运行如下命令即可
tips:为了防止出现编译或者其余问题,可以考虑先不实现
iam
以及whoami
函数的具体逻辑,先使用printk
来进行输出,测试函数是否真正起到了作用。
./iam zhaojiazhen
./whoami
zhaojiazhen
出现上述,证明完成了实验
实验报告
- 问题1:前文已经做出了解答
- 问题2:可以参考前文,这里不再赘述😢