kernel——系统调用
1. 系统调用的原理
linux借助硬件实现特权态和用户态运行,应用程序只能通过系统调用进入内核态。
方法是使用系统调用指令。
以arm32环境,打印hello world字符串的汇编为例
.text
.global _start
_start:
mov r0, #1 /* stdout */
add r1, pc, #16 /* address of string */
mov r2, #12 /* string length */
mov r7, #4 /* syscall of write */
swi #0 /* software interrupt */
_exit:
mov r7, #1 /* syscall for exit */
swi #0 /* software interrupt */
_string:
.asciz "hello world\n"
2. glibc
glibc对系统调用进行封装,提供c接口给用户使用
3. 系统调用流程分析
4. 添加系统调用
在一个kernel一定会链接的文件中加入系统调用的实现.
asmlinkage void sys_hello(const char __user *ubuf, size_t count)
{
char kbuf[100] = {0};
if (ubuf) {
copy_from_user(kbuf, ubuf, (count < sizeof(kbuf)) ? count : sizeof(kbuf) - 1);
printk("hello world 2022: %s\n", kbuf);
}
}
include/uapi/asm-generic/unistd.h 添加声明
void sys_hello(const char __user *str, size_t count);
arch/arm/include/generated/calls-eabi.S 添加系统调用号
__SYSCALL(450, sys_hello)
编译kernel
应用程序
#include <sys/syscall.h>
#include <unistd.h>
#include <sys/syscall.h> /* For SYS_xxx definitions */
int main()
{
syscall(450, "aaa bbb");
return 0;
}
5. 系统调用优化
由于系统调用频繁,所以希望降低开销,方法是:
-
快速系统调用, fast syscall
使用硬件专门为系统调用设置的汇编指令,避免一些不需要的操作,如权限检查等,从而降低开销。 -
虚拟系统调用,vsyscall
有些系统调用可以不进入内核态完成,只需要少量内核空间映射给应用空间,应用层可以直接读取,如time,可以在应用层实现。 -
虚拟动态共享对象,VDSO
由于虚拟系统调用有缺点,分配内存有限,只支持4个系统调用,且分配的内存在进程空间中是静态的,容易被攻击,
所以使用 VDSO 进行改进。
VDSO提供超过4个系统调用,且在进程中地址是随机的。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?