Magenta源代码笔记(5) —— 系统调用
来源:互联网 发布:大话数据结构 java版 编辑:程序博客网 时间:2024/06/08 16:24
系统调用从用户态发起后切换到内核态执行,以下将从这两个方面分析Magenta系统调用的流程。
Magenta系统调用的大致流程如下:
1、用户态调用系统调用函数(mx开头)
2、设置调用编号以及参数
3、调用svc指令进入内核态运行
4、根据调用编号调用内核中相应的处理程序
5、处理返回结果并返回
首先分析一下用户侧的代码
用户侧有关系统调用的代码位于system/ulib/magenta目录中
system/ulib/magenta/syscalls_arm32.S
// Copyright 2016 The Fuchsia Authors. All rights reserved.// Use of this source code is governed by a BSD-style license that can be// found in the LICENSE file./* define and implement the magenta syscall wrappers for 32bit arm */.text#define MAGENTA_SYSCALL_MAGIC 0xf0f0// EABI unwind directives cause an implicit reference to this symbol,// though it's never actually used for anything. Define it locally// just to resolve that reference.__aeabi_unwind_cpp_pr0 = 0xdeadbeef.cfi_sections .debug_frame.macro push_regs reglist:vararg push {\reglist} .save {\reglist} push_regs_cfi \reglist.endm.macro push_regs_cfi reg, reglist:vararg .cfi_adjust_cfa_offset 4 .cfi_rel_offset \reg, 0 .ifnb \reglist push_regs_cfi \reglist .endif.endm.macro pop_regs reglist:vararg pop {\reglist} pop_regs_cfi \reglist.endm.macro pop_regs_cfi reg, reglist:vararg .cfi_adjust_cfa_offset -4 .cfi_same_value \reg .ifnb \reglist pop_regs_cfi \reglist .endif.endm.macro syscall nargs, name, n.globl \name.type \name,STT_FUNC\name: .fnstart .cfi_startproc .cfi_same_value r4 .cfi_same_value r5 .cfi_same_value r6 .cfi_same_value r7.if \nargs < 5 movw r12, #\n movt r12, #MAGENTA_SYSCALL_MAGIC svc #0xff00ff mov r12, #0 bx lr.endif.if \nargs == 5 push_regs r4, r5 ldr r4, [sp, #8] movw r12, #\n movt r12, #MAGENTA_SYSCALL_MAGIC svc #0xff00ff mov r12, #0 pop_regs r4, r5 bx lr.endif.if \nargs == 6 push_regs r4, r5 ldrd r4, r5, [sp, #8] movw r12, #\n movt r12, #MAGENTA_SYSCALL_MAGIC svc #0xff00ff mov r12, #0 pop_regs r4, r5 bx lr.endif.if \nargs == 7 push_regs r4, r5, r6, r7 ldrd r4, r5, [sp, #16] ldr r6, [sp, #24] movw r12, #\n movt r12, #MAGENTA_SYSCALL_MAGIC svc #0xff00ff mov r12, #0 pop_regs r4, r5, r6, r7 bx lr.endif.if \nargs == 8 push_regs r4, r5, r6, r7 ldrd r4, r5, [sp, #16] ldrd r6, r7, [sp, #24] movw r12, #\n movt r12, #MAGENTA_SYSCALL_MAGIC svc #0xff00ff mov r12, #0 pop_regs r4, r5, r6, r7 bx lr.endif .cfi_endproc .fnend.size \name, . - \name.endm#if LIBDDK#define MAGENTA_SYSCALL_DEF(a...)#define MAGENTA_DDKCALL_DEF(nargs64, nargs32, n, ret, name, args...) syscall nargs32, mx_##name, n#else#define MAGENTA_DDKCALL_DEF(a...)#define MAGENTA_SYSCALL_DEF(nargs64, nargs32, n, ret, name, args...) syscall nargs32, mx_##name, n#endif#include <magenta/syscalls.inc>
首先需要介绍一个比较重要的宏
#define MAGENTA_SYSCALL_DEF(nargs64, nargs32, n, ret, name, args...) syscall nargs32, mx_##name, n这是这个宏在用户侧的实现。
汇编代码中最后包含的文件便是使用这个宏定义的系统调用,如
MAGENTA_SYSCALL_DEF(3, 3, 80, mx_handle_t, process_create, USER_PTR(const char) name, uint32_t name_len, uint32_t flags)带入上述汇编文件中
调用了汇编中的宏syscall
其作用即是保存调用的参数至各寄存器之后调用svc指令进入用户态
需要注意的是r12寄存器,它的高16位是magic number用于内核态的验证,低16位即是系统调用的编号
返回后按普通函数返回
内核侧系统调用分析
内核侧系统调用的代码位于目录kernel/lib/syscalls中
kernel/lib/syscalls/syscalls.cpp
extern "C" void arm_syscall_handler(struct arm_fault_frame* frame) { uint64_t ret = 0; uint32_t syscall_num = frame->r[12]; /* check for magic value to differentiate our syscalls */ if (unlikely((syscall_num & 0xf0f00000) != 0xf0f00000)) { TRACEF("syscall does not have magenta magic, 0x%x @ PC 0x%x\n", syscall_num, frame->pc); ret = ERR_BAD_SYSCALL; goto out; } syscall_num &= 0x000fffff; /* re-enable interrupts to maintain kernel preemptiveness */ arch_enable_ints(); LTRACEF_LEVEL(2, "arm syscall: num 0x%x, pc 0x%x\n", syscall_num, frame->pc); /* build a function pointer to call the routine. * the args are jammed into the function independent of if the function * uses them or not, which is safe for simple arg passing. */ syscall_func sfunc; switch (syscall_num) {#define MAGENTA_SYSCALL_DEF(nargs64, nargs32, n, ret, name, args...) \ case n: \ sfunc = reinterpret_cast<syscall_func>(sys_##name); \ break;#include <magenta/syscalls.inc> default: sfunc = reinterpret_cast<syscall_func>(sys_invalid_syscall); } /* call the routine */ ret = sfunc(frame->r[0], frame->r[1], frame->r[2], frame->r[3], frame->r[4], frame->r[5], frame->r[6], frame->r[7]); LTRACEF_LEVEL(2, "ret 0x%llx\n", ret);out: /* check to see if there are any pending signals */ thread_process_pending_signals(); /* unpack the 64bit return back into r0 and r1 */ frame->r[0] = ret & 0xffffffff; frame->r[1] = static_cast<uint32_t>((ret >> 32) & 0xffffffff);}arm_syscall_handler函数为arm的svc的处理程序,在用户侧的汇编代码中调用svc后会跳转到这个函数
这个函数主要完成了以下几个工作:
1、计算magic number并验证
2、计算系统调用编号
3、开中断
4、根据系统调用编号调用sys_开头的函数
5、处理返回值
其中关于系统调用编号的判断和系统调用名称的获取,采用了同名的宏MAGENTA_SYSCALL_DEF,同样引入了magenta/syscalls.inc文件。
0 0
- Magenta源代码笔记(5) —— 系统调用
- Magenta源代码笔记(1) —— 代码结构以及构建系统
- Magenta源代码笔记(3) —— 内存管理
- Magenta源代码笔记(2) —— 线程调度器以及内核定时器
- Magenta源代码笔记(4) —— Dispatcher(以进程为例)
- Magenta
- Magenta
- Magenta
- Magenta
- Magenta
- Magenta
- Magenta
- Magenta——a project from the Google Brain team
- 韩顺平 zend framework 视频教程 源代码和笔记心得第5讲——第6讲 投票系统源代码
- Android菜鸟的成长笔记(5)——Android系统源代码你下载了吗?
- Android菜鸟的成长笔记(5)——Android系统源代码你下载了吗?
- FreeBSD 5内核源代码分析之系统调用过程
- 《Linux设计与实现》笔记——系统调用工作原理、添加系统调用的过程
- sqlite3_column
- webpack+vue起步
- Scrollview的基本用法和协议
- window.parent与window.openner区别
- 报表Body Title在每页中都显示
- Magenta源代码笔记(5) —— 系统调用
- JavaScript基础知识
- 数据库--SQL索引基础
- RESTEasy 例子 hello world(两种方法)
- 二级指针三种内存模型强化训练
- 【稀饭】react native 实战系列教程之Navigator实现页面跳转
- JavaScript父窗口与子窗口之间的操作总结---window.open篇
- Gulp+BroserSync实现浏览器自动刷新
- 蓝鸥Unity开发教程之课时15 Collider