Linux内核笔记3-系统调用

与内核通信

用户空间-syscall-硬件设备
统一接口、稳定安全、易于管理

API、POSIX和C库

POSIX是接口标准
接口提供机制mechanism而不是策略policy

系统调用

通常负的返回值表明错误,0正常。系统调用把错误情况写入errno全局变量。perror()函数翻译为可理解的错误字符串
asmlinkage long sys_callxx()
编译指令,仅从栈中提取函数参数。 用户空间int 内核空间long

系统调用号

使用系统调用号而不是名称,调用号分配后不更改删除不回收 sys_call_table arch/i386/kernel/syscall_64.c

系统调用处理程序

用户空间-》 软中断 引发一个异常 中断号128 由int$0x80指令出发-》陷入内核态-》 128号异常处理程序(系统调用处理程序system_call() 程序用汇编语言写在entry_64.S)

指定恰当的系统调用

陷入内核态同时使用eax寄存器传递调用号,内核比较调用号与NR_syscalls 大于等于则返回-ENOSYS,call *sys_call_table(,%rax,8) 在表中将调用号*4 查找

参数传递

在x86 32位中寄存器 ebx ecx edx esi edi 按照顺序存储前5个参数,此外通常eax寄存器存储这些参数在用户空间地址的指针

系统调用的实现

添加内核新的系统调用相对容易,设计与实现难。 系统调用的接口简洁,参数尽可能少,需要稳定,少改动,越通用越好,向前向后兼容。系统调用的目的可能不变,但是用法可能改变,不假设字节长度和字节序

参数验证

其中最重要的一种是对用户提供的指针进行检查,在接受一个用户空间指针之前,检查指针指向的内存区域属于用户空间且为进程的地址空间。对内存区域的访问权限进行检查。
针对内核与用户空间之间的数据来回拷贝提供两种方法,其中一个必须被使用
copy_to_user(进程空间目的地址,内核空间源地址, 数据长度)
copy_from_user(内核,进程,长度)
调用成功返回0,执行失败返回没能完成拷贝的数据字节数,出现错误返回-EFAULT
这两个调用容易引起阻塞,用户数据的页换出内存,进程休眠,等待缺页处理程序。
最后一项检查合法权限,capable(CAP_SYS_FUNC)检查 返回0 则无权操作。 <linux/capability.h>

系统调用上下文

内核在执行系统调用时处于进程上下文中,current指针指向引发系统调用的那个进程。当系统调用返回时控制权在system_call()中,负责切换到用户空间并让用户进程继续执行下去。

绑定一个系统调用的最后步骤

编写新的系统调用:

  1. 在系统调用表entry.s中最后加入一个表项 ;系统调用表中的位置就是调用号 .long sys_func
  2. <asm/unistd.h>#define _NR_func 调用号
  3. 编译到核心内核映像 kernel/sys.c
    asmlinkage long sys_func(args){ dosth }

在调用表中加入名称- 定义调用号 - 核心映像写功能

从用户空间访问系统调用

在用户空间可以使用宏_syscalln()对系统调用直接访问,0≤n≤6 是传给系统调用的参数个数

//long open(const char *filename,int flags , int mode)
#define NR_open  5
_syscall3(long, open, const char*, filename, int ,flags, int, mode)//参数个数是2+2n  分别是对应类型和名称

然后就可以在代码内直接调用open()

为什么不通过系统调用的方式实现

利:

  • 新建一个系统调用非常容易且使用方便,高性能

弊:

  • 系统调用号资源比较珍贵,在推广角度来说需要对每个体系结构进行适配,脚本和文件系统不支持,若仅进行信息交换则大材小用,可用ioctl()。多种替代方法

小结

调用syscall

中断号128+系统调用号x
x*4在entry_64.S表中查找
system_call<> 返回-ENOSYS
参数验证 权限验证
用户空间
内 核 空 间
system_call<> 中断处理程序
大于等于NR_syscalls
调用sys_func<>

注册调用新的系统调用

追加 .long sys_func
#define _NR_func x
asmlinkage long sys_func 函数实现
#define NR_func x _syscalln<2+2n>
entry.s
asm/unistd.h
kernel/sys.c
注册结束
用户空间c代码中
func<>
发布了27 篇原创文章 · 获赞 1 · 访问量 670

猜你喜欢

转载自blog.csdn.net/SUKI547/article/details/103990145