1.API
get_user和put_user相对于copy_from_user和copy_to_user,这两个函数主要用来完成一些简单类型变量(char、int、long等)的拷贝任务,对于一些复合类型的变量,如数据结构或者数组类型,get_user和put_user函数则无法胜任:函数内部将对ptr所指向的对象长度进行检查,大部分平台只支持长度为1,2,4的变量。
put_user
#define put_user(x, ptr) \ ({ \ might_fault(); \ access_ok(VERIFY_WRITE, ptr, sizeof(*ptr)) ? \ __put_user(x, ptr) : \ -EFAULT; \ })
put_user用来将内核空间的一个简单类型变量x拷贝到所指向的用户空间中。函数能自动判断变量的类型,如果成功则返回0,否则返回-EFAULT。
get_user
#define get_user(x, ptr) \ ({ \ might_fault(); \ access_ok(VERIFY_READ, ptr, sizeof(*ptr)) ? \ __get_user(x, ptr) : \ -EFAULT; \ })
get_user将用户空间ptr指向的数据拷贝到内核空间的变量x中,函数如果成功则返回0,否则返回-EFAULT。
copy_to_user
static inline long copy_to_user(void __user *to, const void *from, unsigned long n) { might_fault(); if (access_ok(VERIFY_WRITE, to, n)) return __copy_to_user(to, from, n); else return n; }
- *to是内核空间的指针
- *from是用户空间指针
- n表示从用户空间向内核空间拷贝数据的字节数
- 关于函数的返回值,如果成功完成拷贝动作,返回0,否则返回还没有完成拷贝的字节数。
copy_from_user
static inline long copy_from_user(void *to, const void __user * from, unsigned long n) { might_fault(); if (access_ok(VERIFY_READ, from, n)) return __copy_from_user(to, from, n); else return n; }
- *to是内核空间的指针
- *from是用户空间指针
- n表示从用户空间向内核空间拷贝数据的字节数
- 关于函数的返回值,如果成功完成拷贝动作,返回0,否则返回还没有完成拷贝的字节数。