memcpy 而不是 copy_to_user

memcpy instead of copy_to_user

考虑以下代码。对于阅读 Linux 设备驱动程序的人来说,上下文会很清楚。

简而言之, sbull 是一个充当磁盘设备的驱动程序,sbull_transfer 函数旨在传输数据块 from/to disk/user_space.

一切都很清楚,期待一件事。 我不明白为什么我们可以简单地使用 memcpy 函数。毕竟,我们是从用户 space 复制的,那为什么可能呢?通常,我注意到,我们应该使用 copy_from_user()/copy_to_user()。

我不明白为什么我们不需要使用它们。请解释。

static void sbull_transfer(struct sbull_dev *dev, unsigned long sector,
        unsigned long nsect, char *buffer, int write)
{
    unsigned long offset = sector*KERNEL_SECTOR_SIZE;
    unsigned long nbytes = nsect*KERNEL_SECTOR_SIZE;

    if ((offset + nbytes) > dev->size) {
        printk (KERN_NOTICE "Beyond-end write (%ld %ld)\n", offset, nbytes);
        return;
    }
    if (write)
        memcpy(dev->data + offset, buffer, nbytes);
    else
        memcpy(buffer, dev->data + offset, nbytes);
}

sbull 驱动程序可以通过简单的 memcpy 调用实现实际的数据传输,因为毕竟数据已经在内存中了。

函数

static void sbull_request(request_queue_t *q)
{
    struct request *req;

    while ((req = elv_next_request(q)) != NULL) {
        struct sbull_dev *dev = req->rq_disk->private_data;
        if (! blk_fs_request(req)) {
            printk (KERN_NOTICE "Skip non-fs request\n");
            end_request(req, 0);
            continue;
        }
        sbull_transfer(dev, req->sector, req->current_nr_sectors,
                req->buffer, rq_data_dir(req));
        end_request(req, 1);
    }
}

在数据传递给 sbull_transfer 之前调用 elv_next_request。请求函数负责复制数据 to/from 用户 space。返回的 request 结构中包含的 buffer 在书中描述为:

char *buffer;

A pointer to the buffer to or from which the data should be transferred. This pointer is a kernel virtual address and can be dereferenced directly by the driver if need be.