2013-07-05 71 views
4

我试图将一个数值从用户空间复制到内核的功能空间:如何使用copy_from_user的正确方法?

static ssize_t device_write(struct file *filp, const char *buff, size_t len, loff_t *off) 
{ 

    unsigned long copy=0; 
    int desp=0; 

    copy = copy_from_user(&desp, &len, 4); 

    printk(KERN_ALERT "copy: %lx\n", copy);  
    printk(KERN_ALERT "desp: %d\n", desp); 
} 

其中“LEN”是存在于用户空间的变量,我想将其复制到“DESP”在内核空间

函数调用我从用户空间提出的是(写为device_write根据的file_operations结构):

write (fd,buffer,8, &off); 

当我打印应该被存放在“DESP”值始终0(应该是8)。 我的代码有什么问题?我已经看到了几个例子,我实现了许多变化,但没有任何作用。

回答

4

write函数原型的手册是:

ssize_t write(int fd, const void *buf, size_t count);

所以你只需要通过3个值write,即:文件描述符fdbuffer您的数据谎言和字节count你想写。

这与用户空间有关。现在让我们转到内核空间写入功能,即您的device_write

该函数的参数buf是包含要从用户空间写入的数据的参数,count是发送给内核写入的数据的长度。所以你应该从buf指针拷贝数据而不是len

所以,正确的做法应该是:

char *desp; //allocate memory for this in kernel using malloc 
copy_from_user (desp, buff, len); 

这应该做的。

+0

问题是,系统调用只有3个参数,我想使用4,这是在文件操作结构(device_read/write)的方法。 因此,当放入内核空间时,编译器不会给出任何有参数数量的警告(这是不同的) 我试着做一个系统llamdas 5参数!编译和执行没有任何问题的警告... 感谢您的答案! – eduardosufan

4

len确实不是存在于用户空间中。它是按值传递的,因此len可作为内核空间中的普通变量访问。 desp = (int)len是你所需要的。但是请注意,size_t与int不同,在64位平台上,size_t是8个字节。

copy_from_user()适用于您要编写的缓冲区(在用户空间代码中称为buffer,在您的内核空间参数列表中称为buff)。所传递的是指向仅存在于用户空间中的内存地址的指针,因此copy_from_user()将该缓冲区复制到内核空间缓冲区。

+0

肯定的,但我的想法是通过第4个参数offset(loff_t *),并且当我从用户空间进行调用时没有到达内核空间。 所以我将这些变量看作用户空间。 另一方面,如果我可以从内核空间直接访问“buff”... – eduardosufan

+1

如何从用户空间进行该调用? write()是一个定义的系统调用接口,它接受3个参数。 C库和内核VFS层最终将该调用转换为您的'device_write()'处理程序。你不能只添加第四个参数,编译器不会让你。你在寻找'pwrite'吗?无论如何,这与你的问题有什么关系,我回答了这个问题?如果你的意思是要问一些不同的东西,请修复你的问题 – Peter

+0

会阅读关于pwrite/read以试图实现这个系统调用,非常感谢! – eduardosufan