Now, as mentioned previously, let's assume your driver has read in the hardware data, and that it's now present in a kernel memory buffer. How do we transfer it to user space? A naive approach would be to simply try and perform this via memcpy(), but no, that does not work (why? one, it's insecure and two, it's very arch-dependent; it works on some architectures and not on others). So, a key point: the kernel provides a couple of inline functions to transfer data from kernel to user space and vice versa. They are copy_to_user() and copy_from_user(), respectively, and are indeed very commonly used.
Using them is simple. Both take three parameters: the to pointer (destination buffer), the from pointer (source buffer), and n, the number of bytes to copy (think of it as you would for a memcpy operation):
include <linux/uaccess.h> /* Note! used to be <asm/uaccess.h> upto 4.11 */
unsigned long copy_to_user(void __user *to, const void *from, unsigned long n);
unsigned long copy_from_user(void *to, const void __user *from, unsigned long n);
The return value is the number of uncopied bytes; in other words, a return value of 0 indicates success and a non-zero return value indicates that the given number of bytes were not copied. If a non-zero return occurs, you should (following the usual 0/-E return convention) return an error indicating an I/O fault by returning -EIO or -EFAULT (which thus sets errno in user space to the positive counterpart). The following (pseudo) code illustrates how a device driver can use the copy_to_user() function to copy some data from kernel to user space:
static ssize_t read_method(struct file *filp, char __user *ubuf, size_t count, loff_t *off)
{
char *kbuf = kzalloc(...);
[ ... ]
/* ... do what's required to get data from the hardware device into kbuf ... */
if (copy_to_user(buf, kbuf, count)) {
dev_warn(dev, "copy_to_user() failed\n");
goto out_rd_fail;
}
[ ... ]
return count; /* success */
out_rd_fail:
kfree(kbuf);
return -EIO; /* or -EFAULT */
}
Here, of course, we assume you have a valid allocated kernel memory buffer, kbuf, and a valid device pointer (struct device *dev). Figure 1.7 illustrates what the preceding (pseudo) code is trying to achieve:
The same semantics apply to using the copy_from_user() inline function. It is typically used in the context of the driver's write method, pulling in the data written by the user space process context to a kernel space buffer. We will leave it to you to visualize this.
It is also important to realize that both routines (copy_[from|to]_user()) might, during their run, cause the process context to (page) fault and thus sleep; in other words, to invoke the scheduler. Hence, they can only be used in a process context where it's safe to sleep and never in any kind of atomic or interrupt context (we explain more on the might_sleep() helper – a debug aid – in Chapter 4, Handling Hardware Interrupts, in the Don't block – spotting possibly blocking code paths section).
For the curious reader (I hope you are one!), here are some links with a bit more of a detailed explanation on why you cannot just use a simple memcpy() but must use the copy_[from|to]_user() inline functions to copy data from and to the kernel and user spaces:
- https://stackoverflow.com/questions/14970698/copy-to-user-vs-memcpy
- https://www.quora.com/Why-we-need-copy_from_user-as-the-kernel-can-access-all-the-memory-If-we-see-the-copy_from_user-implementation-again-we-are-copying-data-to-the-kernel-memory-using-memcpy-Doesnt-it-an-extra-overhead.
In the following section, we shall write a more complete misc framework character device driver, which will actually perform some I/O, reading and writing data.