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.
考虑以下代码。对于阅读 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.