惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
Tenable Blog
Last Week in AI
Last Week in AI
P
Proofpoint News Feed
Engineering at Meta
Engineering at Meta
H
Help Net Security
F
Fortinet All Blogs
MyScale Blog
MyScale Blog
宝玉的分享
宝玉的分享
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
博客园 - 司徒正美
量子位
N
Netflix TechBlog - Medium
Apple Machine Learning Research
Apple Machine Learning Research
小众软件
小众软件
Recorded Future
Recorded Future
博客园 - 三生石上(FineUI控件)
Vercel News
Vercel News
aimingoo的专栏
aimingoo的专栏
I
InfoQ
Microsoft Security Blog
Microsoft Security Blog
Scott Helme
Scott Helme
The Last Watchdog
The Last Watchdog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
IT之家
IT之家
AI
AI
WordPress大学
WordPress大学
Security Archives - TechRepublic
Security Archives - TechRepublic
Google Online Security Blog
Google Online Security Blog
U
Unit 42
V2EX - 技术
V2EX - 技术
MongoDB | Blog
MongoDB | Blog
Schneier on Security
Schneier on Security
博客园 - Franky
H
Heimdal Security Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Jina AI
Jina AI
W
WeLiveSecurity
P
Privacy & Cybersecurity Law Blog
Cloudbric
Cloudbric
B
Blog RSS Feed
N
News | PayPal Newsroom
S
Securelist
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
I
Intezer
Hacker News - Newest:
Hacker News - Newest: "LLM"
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
博客园_首页
罗磊的独立博客
H
Hackread – Cybersecurity News, Data Breaches, AI and More
雷峰网
雷峰网

zStack

Kerberos 认证体系引起的产品系统免密问题 | zStack 通过 strace 追踪 sqlldr 的性能问题 控糖革命 | zStack 单例模式的几种 C++ 实现 | zStack 通过 ChatGPT 协助解决软件安装问题 | zStack 【xv6】Copy on write fork() | zStack 【xv6】trap | zStack 如何用 C 实现协程 | zStack 利用 nginx-upload-module 实现文件上传和重命名 | zStack 在 WSL2 的 Arch Linux 下编译并替换内核 如何找到一个适合自己的笔记软件 | zStack 为终端设置 ASCII ART | zStack Qver - 用于练手的服务器程序 | zStack 关于我在宿舍种草的那些事 | zStack
【xv6】system call | zStack
Noicdi · 2022-08-19 · via zStack

【xv6】system call

2022-08-19 09:00:00 #操作系统  #xv6 

sleep 为例,追踪整个调用过程。启动 GDB 后,在 user/sleep.cmain() 处打上断点,然后在命令行中输入指令 sleep 25,会调用 user/user.h 声明的 sleep()

xv6-systemcall-1

步入后会调用 user/usys.S,可以看到 sleep 的调用汇编代码。首先将 SYS_sleep 的值写入寄存器 a7,然后调用 ecall 指令陷入内核态,进入真正的 system call,最后通过 ret 返回到用户级程序。

user/usys.S 的汇编代码由 user/usys.pl 脚本生成。

xv6-systemcall-2

寄存器 a7 可以看到值最终修改为 13,对应了 kernel/syscall.hSYS_sleep 的值。

xv6-systemcall-3

调用 ecall 会切换到内核态,并调用 kernel/syscall.c/syscall(),获取 a7 中的调用号,然后根据调用号,在 *syscalls[] 中寻找对应的系统调用 sys_sleep()

xv6-systemcall-4

xv6-systemcall-5

在找到对应的系统调用 kernel/sysproc.c/sys_sleep() 并执行后,会在其中获取保存在寄存器中的参数,并执行真正的实现 kernel/proc.c/sleep()

xv6-systemcall-6

如何实现一个 system call

以即将实现的 trace() 为例,描述实现一个 syscall 的具体流程。

首先在 kernel/syscall.h 中为新的 syscall 设定一个调用号,一般跟着上一个调用号顺延即可。

1
2
3
4

#define SYS_mkdir  20
#define SYS_close  21
#define SYS_trace  22

然后在 user/usys.pl 脚本中添加一个入口,会在编译生成 user/usys.S 时为 trace() 生成用户态切换到内核态的汇编代码。

1
2
3
4
# ...
entry("sleep");
entry("uptime");
entry("trace");

如上一节所言,当调用 ecall 切换到内核态后,会根据从 a7 中取得的调用号来获取对应系统调用的入口,所以需要在 kernel/syscall.c 中声明 sys_trace() 并添加到 *syscalls[] 中。

值得一提的是,kernel/syscall.c 中也定义了多个用于获取参数的功能函数,在下文中会有使用。

1
2
3
4
5
6
extern uint64 sys_trace(void);

static uint64 (*syscalls[])(void) = {

[SYS_trace] sys_trace,
};

kernel/sysproc.c 中需要定义 sys_trace() 的实现。sys_trace() 不会接受任何参数,那么用户调用时的参数如何获取呢?这就用到上面提到的功能函数,在 sys_trace() 中调用它们,从寄存器中获取参数,比如获取一个 int 类型参数:

1
2
3
4
5
6
7
8
9
10
11
uint64
sys_trace(void) {
int mask;
argint(0, &mask);


trace(mask);


return 0;
}

拿到所需要的参数后,调用 trace(),这是系统调用的具体实现,我们定义的功能都在这个函数中实现。

最后记得在 user/user.h 中声明用户调用的 trace(),在 kernel/defs.h 中声明内核调用的 trace()

目录

  1. system call 调用过程
  2. 如何实现一个 system call