用户一般访问内核,需要从用户态变为内核态,然后再访问内核,这么做的目的是防止用户随意篡改内核。在编写某个外设的驱动时,我们需要实现内核中的 read 和 write 函数,此时站在内核的角度,无法直接读取用户缓冲区 或者 无法直接向用户缓冲区写入。
因此,就需要用到 copy_to_user 和 copy_from_user 函数。
- copy_to_user():完成内核空间到用户空间的复制
- copy_from_user():完成用户空间到内核空间的复制
#include <linux/uaccess.h> // copy_to_user & copy_from_user
目录
1、copy_to_user
(1) 函数声明
调用该函数需站在内核的角度,即调用该函数所在文件中的缓冲区,都属于内核缓冲区
ulong copy_from_user(void *to, const void __user *from, unsigned long n)
第一个参数 to:目标用户空间的地址
第二个参数 from: 源内核空间地址。保存了要拷贝到用户空间的内容的地址
第三个参数 n:要拷贝的字节数
返回值:成功返回 0
(2) 具体使用
static char readbuf[100]; /* 读缓冲区 */
/*
* 该函数一般用于内核中的 read 函数的定义中,将内核接收到的内容拷贝到用户缓冲区
*/
static ssize_t xxx_read(struct file *filp, char __user *buf,
size_t cnt, loff_t *offt)
{
int ret = copy_to_user(buf, readbuf, cnt); // 将readbuf中的内容拷贝到buf
// 拷贝的字节数大小为cnt
if(ret == 0)
{
printk("kernel send data ok!\n");
}
else
{
printk("kernel send data failed!\n");
}
return 0;
}
2、copy_from_user
(1) 函数声明
ulong copy_to_user(void __user *to, const void *from, unsigned long n);
第一个参数 to:目标内核空间的地址
第二个参数 from: 源用户空间地址。保存了用户要发送的数据,或者要拷贝到内核空间的内容的地址
第三个参数 n:要拷贝的字节数
返回值:成功返回 0
(2) 具体使用
static char writebuf[100];
/*
* 该函数一般用于内核中的 write 函数的定义中,将用户要发送的内容拷贝到内核缓冲区
*/
static ssize_t xxx_write(struct file *pfile, const char __user *buf,
size_t cnt, loff_t *offset)
{
/* 用户实现具体功能 */
int ret = copy_from_user(writebuf, buf, cnt); // 将buf中的内容拷贝到writebuf
if(ret == 0)
{
printk("kernel read data ok!\n");
}
else
{
printk("kernel read data failed!\n");
}
return 0;
}