查看: 786|回复: 0
收起左侧

RISC-V Syscall 系列1:什么是 Syscall ?

[复制链接]

  离线 

  • TA的每日心情
    奋斗
    2022-6-21 08:23
  • 签到天数: 2 天

    [LV.1]

    发表于 2022-8-31 14:19:40 | 显示全部楼层 |阅读模式

    有人预言,RISC-V或将是继Intel和Arm之后的第三大主流处理器体系。欢迎访问全球首家只专注于RISC-V单片机行业应用的中文网站

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    本帖最后由 塞巴斯蒂安 于 2022-8-31 14:19 编辑
    Author:  envestcc chen1233216@hotmail.com
    Date:    2022/06/14
    Revisor: walimis、Falcon
    Project: RISC-V Linux 内核剖析
    Sponsor: PLCT Lab, ISCAS

    该系列活动推荐统一采用泰晓科技技术社区自研的 Linux Lab 开源实验环境,也可直接采用社区自研的免安装即插即跑 Linux Lab Disk(https://tinylab.org/linux-lab-disk),又称泰晓 Linux 实验盘,某宝检索“泰晓 Linux”可找到。

    RISC-V Syscall 系列1:什么是 Syscall ?

    一、什么是 Syscall ?

    国产化MCU芯片专区-RISC-V Syscall 系列1:什么是 Syscall ?risc-v单片机中文社区(1)
    (图片源自 wikipedia)

    Syscall 又称为系统调用,它是操作系统内核给用户态程序提供的一组 API,可以用来访问系统资源和内核提供的服务。比如用户态程序申请内存、读写文件等都需要通过 Syscall 完成。

    通过 Linux 源码里可以看到(include/linux/syscalls.h),大约有 400 多个 Syscall。其中一部分是兼容 POSIX 标准,另一些是 Linux 特有的。

    二、如何调用 Syscall ?

    应用程序想要调用 Syscall 有两种方式,分别是直接调用和使用 C 标准库。

    直接调用

    下面我们通过一段汇编代码来看看如何直接调用 Syscall。
    1. .data

    2. msg:
    3.     .ascii "Hello, world!\n"

    4. .text
    5.     .global _start

    6. _start:
    7.     li a7, 64    # linux write syscall
    8.     li a0, 1     # stdout
    9.     la a1, msg   # address of string
    10.     li a2, 14    # length of string
    11.     ecall        # call linux syscall

    12.     li a7, 93    # linux exit syscall
    13.     li a0, 0     # return value
    14.     ecall        # call linux syscall
    复制代码
    上面的代码的功能是通过系统调用往标准输出上打印一串字符。
    1. $ cat test.S
    2. .data

    3. msg:
    4.     .ascii "Hello, world!\n"

    5. .text
    6.     .global _start

    7. _start:
    8.     li a7, 64
    9.     li a0, 1
    10.     la a1, msg
    11.     li a2, 14
    12.     ecall

    13.     li a7, 93
    14.     li a0, 0
    15.     ecall
    16. $ riscv64-linux-gnu-gcc -c test.S
    17. $ riscv64-linux-gnu-ld -o test test.o
    18. $ qemu-riscv64 test
    19. Hello, world!
    复制代码
    RISC-V 中通过 ecall 指令进行 Syscall 的调用。ecall 指令会将 CPU 从用户态转换到内核态,并跳转到 Syscall 的入口处。通过 a7 寄存器来标识是哪个 Syscall。至于调用 Syscall 要传递的参数则可以依次使用 a0-a5 这 6 个寄存器来存储。
    ecall 指令之前叫 scall,包括现在 Linux 源码里都用的是 scall,后来改为了 ecall。原因是该指令不仅可以用来进行系统调用,还可以提供更通用化的功能。

    write 的系统调用号为 64,所以上述代码里将 64 存储到 a7 中。write 系统调用的参数有 3 个,第一个是文件描述符,第二个是要打印的字符串地址,第三个是字符串的长度,上述代码中将这三个参数分别存入到 a0、a1、a2 这三个寄存器中。

    系统调用号列表可以在 Linux 源码中进行查看:include/uapi/asm-generic/unistd.h。
    1. #define __NR_write 64
    2.   
    3. #define __NR_exit 93
    复制代码
    系统调用函数声明源码位置:include/linux/syscalls.h
    1. asmlinkage long sys_write(unsigned int fd, const char __user *buf, size_t count);

    2. asmlinkage long sys_exit(int error_code);
    复制代码

    C 标准库

    直接使用汇编调用 Syscall 比较繁琐也不安全,C 标准库提供了对 Syscall 的封装。

    国产化MCU芯片专区-RISC-V Syscall 系列1:什么是 Syscall ?risc-v单片机中文社区(2)
    (图片源自 wikipedia)

    下面用一段 C 代码例子看看如何使用 Syscall ,这种方式大家都比较熟悉。
    1. #include <unistd.h>

    2. int main() {
    3.   write(1, "Hello, world!\n", 14);
    4.   return 0;
    5. }
    复制代码
    使用下面的命令进行测试即可输出结果。
    1. $ cat testc.c
    2. #include <unistd.h>

    3. int main() {

    4.   write(1, "Hello, world!\n", 14);
    5.   return 0;
    6. }
    7. $ riscv64-linux-gnu-gcc -static testc.c -o testc
    8. $ qemu-riscv64 testc
    9. Hello, world!
    复制代码

    三、总结

    本篇文章主要从 Syscall 使用者的角度,阐述了什么是 Syscall。然后以实际代码为例,展示了在 RISC-V 架构下应用程序如何使用汇编代码和 C 标准库两种方式调用 Syscall 。

    系列文章预告:RISC-V Syscall 系列2:Syscall 过程分析

    参考资料
    System call
    syscall(2) — Linux manual page
    Linux kernel interfaces
    RISC-V Assembly Programmer's Manual
    RISC-V架构下利用QEMU进行GDB调试
    Risc-V Assembly Language Hello World
    System Interface & Headers Reference
    Misunderstanding RISC-V ecalls and syscalls



    RISCV作者优文
    全球首家只专注于RISC-V单片机行业应用的中文网站
    回复

    使用道具 举报

    高级模式
    B Color Image Link Quote Code Smilies

    本版积分规则

    关闭

    RISC-V单片机中文网上一条 /2 下一条


    版权及免责声明|RISC-V单片机中文网 |网站地图

    GMT+8, 2024-3-29 00:42 , Processed in 0.548057 second(s), 47 queries .

    快速回复 返回顶部 返回列表