第五章系统调用编程
5.1与内核通讯安全
系统调用在用户空间进程和硬件设备间添加了一个中间层,函数
做用:为用户空间提供了一种硬件的抽象接口;保证了系统的稳定和安全,避免应用程序不正确使用硬件,窃取其余进程的资源,或作出危害系统的行为;为了实现多任务和虚拟内存。性能
Linux提供的系统调用比大部分操做系统少得多。操作系统
5.2 API、POSIX、和C库设计
一个API定义了一组应用程序使用的编程接口。(API和系统调用不是一一对应)API能够在各类不一样的操做系统上实现,给应用程序提供彻底相同的接口,而API自己的实如今不一样系统中可能迥异。指针
Unix的API基于POSIX,Linux尽力与POSIX和SUSv3兼容接口
Linux的系统调用做为C库的一部分提供。进程
5.3系统调用内存
访问系统调用一般经过C库中定义的函数调用,一般须要定义参数,并且可能产生反作用(使系统状态发生改变)。系统调用还会返回了一long类型的值表示成功或错误。
定义系统调用:asmlinkage long sys_***
限定词 返回类型 命名规则
系统调用号:每一个系统调用被赋予一个系统调用号,用户空间执行系统调用时,用系统调用号指明系统调用。一旦分配再也不变动,系统调用被删除,其系统调用号也不容许回收利用。内核记录了系统调用表中全部已注册的系统调用列表,存储在sys_call_table中
系统调用的性能:Linux系统调用比其余操做系统要快,缘由:上下文切换时间短;系统调用程序和系统调用都很简洁。
5.4系统调用处理程序
内核驻留在受保护的地址空间上,所以应用程序要通知内核本身须要使用系统调用。通知内核是靠软中断实现,引起异常时系统切换到内核态。经过int $0x80触发中断,执行128号异常处理程序(系统调用处理程序)
指定恰当的系统调用:X86上系统调用号经过eax寄存器传递给内核
参数传递:除了系统调用号还须要传递外部参数,按顺序存储在ebx,ecx,edx,esi和edi五个寄存器中,不多有须要六个参数的。
5.5系统调用的实现
实现系统调用:一、决定用途(不提倡采用多用途);二、调用的参数、返回值和错误码应该是什么(借口力求简洁,参数尽量少,力求稳定);三、设计接口尽可能为未来作考虑(是否有没必要要的限制,是否可移植);
提供机制(mechaniam)不提供策略(policy)
参数验证:必须仔细检查参数是否合法有效,由于系统调用在内核空间执行,若是有不合法输入,那会威胁系统安全和稳定。最重要的检查是 检查用户提供的指针是否有效。在接收一个用户空间的指针以前,内核必须保证一、指针指向的内存区域属于用户空间。进程毫不能哄骗内核去读内核空间的数据;二、指针指向的内存区域在进程的地址空间里。进程毫不能哄骗内核去读其余进程的数据;三、进程毫不能绕过内存访问限制。
内核提供copy_to_user(),copy_from_user()两个方法完成检查拷贝数据
5.6系统调用上下文
内核在执行系统调用的时候处于进程上下文,在进程上下文中,内核能够休眠,而且能够被抢占。休眠说明系统调用可使用内核提供的绝大部分功能。能够抢占说明新进程可使用相同的系统调用。
绑定一个 系统调用的最后步骤:一、在系统调用表的最后加入一个表项;二、系统调用号必须定义于<asm/unistd.h>;三、系统调用必须被编译进内核映像。
从用户空间访问系统调用:只写出系统调用gilc恐怕并不提供支持。Linux自己提供一组宏_syscalln(),n的范围从0到6,表明须要传递给系统调用的参数个数。