Linux内核深度解析之中断、异常和系统调用——系统调用

本文详细阐述了系统调用的概念,包括用户程序如何通过glibc库或直接使用syscall()函数调用系统调用,以及ARM64处理器上的系统调用指令svc的使用。深入探讨了Linux内核中系统调用的定义、执行流程,以及ARM64架构下系统调用的处理机制。

系统调用

系统调用是内核给用户程序提供的编程接口。用户程序调用系统调用,通常使用glibc库针对单个系统调用封装的函数。如果glibc库没有针对某个系统调用封装的函数,用户程序可以使用通用的封装函数syscall():

#define _GNC_SOURCE
#include <unistd.h>
#include <sys/syscall.h>        /* 定义SYS_xxx */

long syscall(long number, ...);

参数number是系统调用号,后面是传递给系统调用的参数。

返回值0表示成功,返回值-1表示错误,错误号存储在变量errno中。

例如,应用程序使用系统调用fork()创建子进程,有两种调用办法:

(1)ret = fork();

(2)ret = syscall(SYS_fork);

ARM64处理器提供的系统调用指令是svc,调用约定如下:

(1)64位应用程序使用寄存器x8传递系统调用号,32位应用程序使用寄存器x7传递系统调用号

(2)使用寄存器x0~x6最多可以传递7个参数

(3)当系统调用执行完的时候,使用寄存器x0存放返回值。

1. 定义系统调用

Linux内核使用宏SYSCALL_DEFINE定义系统调用,以创建子进程的系统调用fork为例:

kernel/fork.c
SYSCALL_DEFINE0(fork)
{
#ifdef CONFIG_MMU
	return _do_fork(SIGCHLD, 0, 0, NULL, NULL, 0);
#else
	/* can not support in nommu mode */
	return -EINVAL;
#endif
}

把宏“SYACALL_DEFINE0(fork)”展开以后是:

asmlinkage long sys_fork(void)

“SYSCALL_DEFINE”后面的数字表示系统调用的参数个数,“SYSCALL_DEFINE0”表示系统调用没有参数,“SYSCALL_DEFINE6”表示系统调用有6个参数,如果参数超过6个,使用宏“SYSCALL_DEFINEx”。头文件“include/linux/syscalls.h”定义了这些宏。

“asmlinkage”表示这个C语言函数可以被汇编代码调用。如果使用C++编译器,“asmlinkage”被定义为extern "C";如果使用C编译器,“asmlinkage”是空的宏。

系统调用的函数名称以“sys_”开头。

需要在系统调用表中保存系统调用号和处理

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值