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

推荐订阅源

Know Your Adversary
Know Your Adversary
云风的 BLOG
云风的 BLOG
Recent Announcements
Recent Announcements
F
Fortinet All Blogs
B
Blog
罗磊的独立博客
宝玉的分享
宝玉的分享
Vercel News
Vercel News
Martin Fowler
Martin Fowler
N
Netflix TechBlog - Medium
P
Proofpoint News Feed
T
Threatpost
Security Latest
Security Latest
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Stack Overflow Blog
Stack Overflow Blog
I
Intezer
P
Privacy International News Feed
D
Docker
月光博客
月光博客
博客园 - 三生石上(FineUI控件)
M
MIT News - Artificial intelligence
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
L
Lohrmann on Cybersecurity
Google DeepMind News
Google DeepMind News
The Last Watchdog
The Last Watchdog
A
Arctic Wolf
IT之家
IT之家
S
SegmentFault 最新的问题
S
Securelist
博客园 - 叶小钗
N
News and Events Feed by Topic
F
Full Disclosure
Security Archives - TechRepublic
Security Archives - TechRepublic
Engineering at Meta
Engineering at Meta
Hacker News: Ask HN
Hacker News: Ask HN
博客园 - Franky
GbyAI
GbyAI
AI
AI
Y
Y Combinator Blog
WordPress大学
WordPress大学
Latest news
Latest news
Microsoft Security Blog
Microsoft Security Blog
人人都是产品经理
人人都是产品经理
N
News | PayPal Newsroom
The Cloudflare Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
I
InfoQ

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