1.调用在用户空间进程和硬件设备之间添加了一个中间层。该层主要做用有三个:linux
2.系统调用是用户空间访问内核的惟一手段;除异常和陷入外,是内核惟一合法的入口。编程
1.状况下,应用程序经过在用户空间实现的应用编程接口(API)而不是直接经过系统调用来编程。api
2.C库提供了POSIX的绝大部分API。安全
1.要访问系统调用(syscall),一般经过C库中定义的函数调用来进行。函数
2.如何定义系统调用,注意:性能
1.在Linux系统中,每一个系统调用被赋予一个系统调用号,这样经过这个第一无二的号就能够关联系统调用。当用户空间的进程执行一个系统调用时,系统调用号用来指明执行哪一个系统调用;进程不会说起系统调用的名称。spa
2.系统调用号一旦分配就不会再有任何变动,不然编译好的应用程序就会崩溃。若是一个系统调用被删除,所占用的系统调用号也不准被回收利用。sys _ ni _ syscall()专门针对无效的系统调用而设立的,只返回-ENOSYS。设计
3.内核记录了系统调用表中的全部已注册的系统调用的列表,存储在sys_call_table中。在x86-64中,他被定义于3arch/i386/kernel/syscall_64.c文件中,为每个有效的系统调用指定惟一的系统调用号。指针
1.很短的上下文切换时间code
2.系统调用处理程序和每一个系统调用自己都很简洁。
1.在X86中,系统调用号经过eax寄存器传递给内核,system _ call()函数经过将给定的系统调用与NR _syscalls做比较来检查其有效性,若是大于或等于NR _syscalls就返回-ENOSYS,不然就执行相应的系统调用:
call *sys_call_table(,%eax,8)//基址+偏移量*8
1.系统调用必须仔细检查全部的参数是否合法有效,并且必须是正确的。
2.最重要的一种检查是检查用户提供的指针是否有效,在接收一个用户空间的指针以前,内核必须保证:
3.内核提供了两个方法来完成必须的检查内核空间与用户空间数据的来回拷贝。
为了向用户空间写数据,内核提供了copy _ to _user(),它须要三个参数,第一个是进程空间中的目的内存地址,第二个是内核空间内的源地址,第三个是须要拷贝的数据长度(字节数)。
为了从用户空间读数据,内核提供了copy _ from _user(),该函数把第二个参数指定位置上的数据拷贝到第一个参数的指定位置,第三个是须要拷贝的数据长度(字节数)。
若是运行成功,则返回0,若是失败,则返回没能拷贝成功的字节数。
4.检查针对是否有合法权限
调用capable()函数检查用户是否有权对指定资源进行操做,返回非0值则有权限,返回0无权限。
<linux/capability.h>中包含一份全部权能和其对应的权限列表。
1.内核在执行系统调用时处于进程上下文。在进程上下文中,内核能够:
1.一般,系统调用靠C库支持。
2.Linux自己提供了一组宏,用于直接对系统调用进行访问。他会设置好寄存器并调用陷入指令。
3.对于每一个宏来讲,都有(2+2xn)个参数:
好处:
问题:
替代方法:
实现一个设备节点,并对此实现read()和write()。使用特定的信息进行检索。