标签:
中间层
作用三个:1.为用户空间提供一种硬件的抽象接口;2.保证系统稳定和安全;3.除异常和陷入,是内核唯一的合法入口。
时刻注意可移植性和健壮性
必须检查每个参数,保证他们不但合法有效,而且正确。
最重要——检查用户提供的指针:
※1.检查读写
(1)向用户空间写入数据——copy_to_user()
参数:
进程空间中的目的内存地址
内核空间内的源地址
需要拷贝的数据长度
(2)从用户控件读取数据——copy_from_user()
把第二个参数指定的位置上的数据拷贝到第一个参数指定的位置上
第三个参数——拷贝数据长度。
以上两个函数成功返回0,失败返回没能完成拷贝的数据的字节数。
这两个函数都有可能引起阻塞——当包含用户数据的页被换出到硬盘上而不是物理内存上的时候。
※2.检查是否有合法权限
老版本:suser()
新版本:权能机制,capable(),返回非0有权操作,返回0则无权操作。
内核在执行系统调用时处于进程上下文。
在进程上下文中,内核可以:
1,在系统调用表的最后加入一个表项。
2,对于所支持的各种体系结构,系统调用号都必须定义于<asm/unistd.h>中
3,系统调用必须被编译进内核映像,不能被编译成模块。——放进kernel/下的一个相关文件中即可,例如sys.c。
Linux本身提供了一组宏,用于直接对系统调用进行访问。
_syscalln() //n的范围从0到6,代表需要传递给系统调用的参数个数。
例如:
long open(const char *filename, int flags, int mode)
=
#define NR_open 5
_syscall3(long, open,const char*, filename, int, flags, int, mode)
应用程序可以直接用open()了。
对于每个宏来说,都有(2+2xn)个参数:
1.系统调用的返回值类型
2.系统调用的名称
以后按照系统调用参数的顺序排列每个参数的类型和名称。
_NR_open在<asm/unistd.h>中定义。
这个宏会被扩展成为内嵌汇编的C函数。
好处:
- 系统调用创建容易并且使用方便
- linux系统调用的高性能
问题:
- 占用系统调用号
- 固化,不允许改动接口
- 需要分别注册到每个需要支持的体系结构中
- 脚本中不易调用,文件系统中也不能直接访问
- 在主内核树外难以维护使用
- ……
替代:
- 某些接口,例如信号量,用文件描述符表示
- 把增加的信息作为一个文件放在sysfs的合适位置。
标签:
原文地址:http://www.cnblogs.com/20135302wei/p/5302683.html