【问题标题】:how is the correct way to use copy_from_user?如何正确使用 copy_from_user?
【发布时间】:2013-07-03 15:37:31
【问题描述】:

我正在尝试使用以下函数将值从用户空间复制到内核空间:

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”中

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

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

当我打印应该存储在“desp”中的值总是 0(应该是 8)。 我的代码有什么问题?我已经看到了几个示例,并且我实现了许多变体,但没有一个有效。

【问题讨论】:

    标签: c linux-kernel kernel


    【解决方案1】:

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

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

    【讨论】:

    • 当然,但我的想法是传递第四个参数,offset (loff_t *) 并且当我从用户空间进行调用时不会到达内核空间。所以我将这些变量视为用户空间。另一方面,如果我可以从内核空间直接访问“buff”...
    • 如何从用户空间进行调用? write() 是一个已定义的系统调用接口,它接受 3 个参数。 C 库和内核 VFS 层最终将该调用转换为您的 device_write() 处理程序。你不能只添加第四个参数,编译器不会让你。您是在寻找pwrite 吗?无论如何,这与我回答的您的问题有什么关系?如果您想问一些不同的问题,请解决您的问题
    • '将阅读 pwrite / read 以尝试实现该系统调用,非常感谢!
    • Peter,结构文件操作中没有实现 pread/pwrite,在我的内核 3.6 (arm) lxr.free-electrons.com/source/include/linux/fs.h?v=3.6;a=arm 我必须使用 ioctl...
    • 您仍然对内核空间文件操作处理程序和用户空间系统调用之间的区别感到困惑。当用户想要写入文件时,他调用函数 write(或 pwrite,或 writev 或 pwritev)。从那里,C 库将该函数调用转换为系统调用。从这里,你在内核空间。然后,在调用最终到达文件操作处理程序之前,内核会经历几个转换步骤。相信我!就试一试吧!从用户空间调用 pwrite 并观察调用显示在您的 write() 处理程序中。
    【解决方案2】:

    手册中的write函数原型为:

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

    所以你只需要传递3个值给write,即:文件描述符fd,你的数据所在的buffer,以及你要写入的字节的count

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

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

    所以,正确的方法是:

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

    应该这样做。

    【讨论】:

    • 问题是系统调用只有3个参数,我想用4个,在文件操作结构(device_read/write)的方法中。因此,当放入内核空间时,编译器不会对具有方法的参数数量给出任何警告(这是不同的)我尝试做一个系统 llamdas 5 个参数!并且编译和执行没有任何问题的警告...感谢您的回答!!!
    猜你喜欢
    • 2013-12-24
    • 2014-10-10
    • 2016-07-13
    • 1970-01-01
    • 2020-12-04
    • 2012-07-12
    • 2013-01-21
    • 2021-10-24
    相关资源
    最近更新 更多