大家知道在内核中使用有些系统调用(如打开,写文件等操作)需要使用get_fs,set_fs对他们进行保护。具体使用方法如下:
oldfs=get_fs();
set_fs(KERNEL_DS);
filp->f_op->write(filp,buf,size,&filp->f_pos);
set_fs(oldfs);
只有使用上面的方法,才能在内核中使用open,write等的系统调用。其实这样做的主要原因是open,write的参数在用户空间,在这些系统调用的实现里需要对参数进行检查,就是检查它的参数指针地址是不是用户空间的,即判断地址是不是在3G以下的,如果在3G以上,说明参数为内核空间,系统调用就会返回错误,我们这里以open系统调用为例子:
它最终会调用下面所示的函数,其中就会对char __user *filename这个用户指针进行判断,如果它不是segment_eq(get_fs(), KERNEL_DS)就需要如上面描述的检查它的指针是不是用户空间指针。内核使用系统调用参数肯定是内核空间,为了不让这些系统调用检查参数所以必须设置 set_fs(KERNEL_DS)才能使用该系统调用
satic int do_getname(const char __user *filename, char *page) {
int retval; unsigned long len = PATH_MAX;
if (!segment_eq(get_fs(), KERNEL_DS)) {
if ((unsigned long) filename >= TASK_SIZE)
return -EFAULT; }
ps:系统调用open,read,write等系统调用的参数在用户空间,系统调用使需对这些参数的地址进行合法性检测,在内核中直接使用这些系统调用无法通过这些合法性检测,需使用set_fs(get_ds()),将这些参数地址设置为内核空间,那么检查时也会判断参数是否在内核空间