copy_to_user()和copy_from_user()用于基本数据类型

时间:2015-04-01 17:42:57

标签: c linux linux-kernel linux-device-driver embedded-linux

我正在编写Linux内核驱动程序,并且对于将数据发送到用户空间或从用户空间读取数据的每个函数,我使用的是copy_to_user()和copy_from_user()。我的问题是:如果我只是复制一个基本数据类型,如u32或int,我是否需要使用这些调用?

3 个答案:

答案 0 :(得分:7)

如果函数接收到指针到用户空间数据,则必须使用copy_from_user()将指向的数据从用户空间复制到内核空间(反之亦然)。

请注意,指针值本身是按值传递的(就像所有C参数一样),所以你不必做copy_from_user()来获取指针值,然后才能copy_from_user()它指向的数据。

数字参数与指针参数的工作方式相同;用C语言来说,他们都是标量。您不必使用copy_from_user()来复制参数的值;这已经被复制了。您只需使用它来复制传递指针所指向的数据。

因此,如果您有int类型的参数,则可以直接使用它。如果您的参数指向int,则int对象将位于用户空间中,您需要使用copy_to_user将该对象的值复制到内核空间中。

答案 1 :(得分:2)

当用户将数据传递到内核空间时,可以将这些数据分成几个页面,这些页面甚至可以在换出的内存中。在这些情况下,您将不得不等待内核交换页面并访问数据所在的页面。对于基本数据类型(如int或指针),某些体系结构也是如此。 (特别是x86 intel)不强制用户对齐数据,因此即使整数也可以在页面边框周围分割。您可以访问整数的第一部分,但是在访问整个内容之前等待第二部分被内存管理器交换。

您可以通过将所有用户数据放入指针传递给内核的结构中来保存一些往返。您可以将copy_from_user作为一个块并保存访问(并且可能会被多次阻止)

所以,作为结论,使用基本类型的功能,因为它们很多。在内核模式下运行时,不要假设用户数据的位置。您可以访问它,但用户数据的内核虚拟地址与用户模式中看到的虚拟地址无关。

答案 2 :(得分:0)

这是我的操作方式(有效,但是我不确定这是否正确): 首先创建该数据类型的数组,然后用数据填充该数组,然后将引用传递给该数组,例如仅传递一个整数:

os.system('python3 /home/bob/DarknetAB/darknet/darknet.py')

以及用户空间代码:

    int *from_user = (int *)kmalloc(sizeof(int), GFP_KERNEL);
    if (copy_from_user(from_user, buff, count))
        return -EFAULT;
    printk(KERN_INFO "The value copied from user =   %d", *from_user);
    return sizeof(buff);