【问题标题】:copy_to_user not copying data?copy_to_user 不复制数据?
【发布时间】:2016-03-01 19:14:39
【问题描述】:

对于一个项目,我们正在从 SoC 系统上的嵌入式 FPGA 读取和写入数据。写作作品(现在只有 1 个字节,但很好)。读取函数正确访问 FPGA(并获得正确的值),但由于某种原因,copy_to_user 不会将任何内容复制给用户。在我的设备上运行 cat 不会返回任何内容。我希望有人能告诉我哪里做错了。

附加信息:我们的目标是配备 ARMv7 处理器的 Altrera Cyclone V SoC 系统。我们使用的是 Altera 推荐的带有内核 4.3.0 的 buildroot 系统。

代码:

// Read function is called whenever a read in performed on one of the /dev devices
static ssize_t mydevice_read(struct file *file, char *buffer, size_t len, loff_t *offset) {
  int success = 0;
  u32 read_value32 = 0;

  // Get the device struct out of the miscdev struct
  struct mydevice_dev *dev = container_of(file->private_data, struct mydevice_dev, miscdev);

  // Read data from FPGA
  read_value32 = ioread32(dev->regs);

  pr_info("Data received from FPGA: %d", read_value32);

  success = copy_to_user(buffer, &read_value32, sizeof(read_value32));

  pr_info("%d: %d bytes copied to userspace pointer 0x%p, value: %d!\n", success, sizeof(read_value32), buffer, dev->data_value8);

  // If copy_to_user failed
  if (success != 0) {
    pr_info("Failed to copy current value to userspace!\n");
    return -EFAULT;
  }

  return 0;
}

输出(包括内核消息和调试打印):

# insmod mymodule.ko 
[  701.922707] Initializing mymodule module
[  701.926681] Probing for fpga devices...
[  701.931382] Probing successful!
[  701.935429] FPGA successfully initialized!
# echo -n -e \\x81 > /dev/mydevice
# cat /dev/mydevice 
[  721.555795] Data received from FPGA: 129
[  721.559539] 0: 4 bytes copied to userspace pointer 0xbec67c78, value: 129!

非常感谢!

【问题讨论】:

  • 认为@pelya 是在正确的轨道上。还要注意,您的调试打印正在打印名为 dev->data_value8 的东西,而不是在您的代码 sn-p 中使用(而不是 read_value32)。
  • 是的,这是我之前写的值(本地存储在结构中)所以我有一个比较点,第一次调试打印应该打印正确读取的值。

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


【解决方案1】:

您确定return 0; 吗?我认为这个函数应该返回复制的字节数,在你的情况下应该是return sizeof(read_value32);

【讨论】:

  • 是的,这确实改变了一些东西。 cat 现在返回“\201”,我认为这是该字节的某种表示形式。但是输出似乎永远不会停止,你知道为什么吗?
  • 这个函数会循环调用,直到返回0,表示流结束。所以你的cat 命令只是不断地反复转储相同的寄存器值。您可能希望使用命令 head -c 4 而不是 cat 读取单个值
  • 你也可以查看offset的值——一开始是0,然后是4、8、12、16等等。所以当offset != 0,你做return 0
  • head -c 4 有效,但是当我没有更多数据要读取时,我有点希望它停止。我在开头添加了一个简单的if (offset != 0) return 0,但这只是在第一次通话之前停止。有什么方法 cat 开始读取另一个值而不是 0?
  • Linux 内核中的类似函数正在使用 simple_read_from_buffer 函数 - 请参见此处的示例:lxr.free-electrons.com/source/drivers/s390/char/… 要读取的数组是 filp->private_data,要读取的字节数是 MEMORY_CHUNKS * CHUNK_INFO_SIZE 在该代码中.所以对你来说,这将是return simple_read_from_buffer(buffer, len, offset, &read_value32, sizeof(read_value32));,你不需要打电话给copy_to_user。这个函数还会更新offset,我们在这里忘记了。
猜你喜欢
  • 2015-12-05
  • 1970-01-01
  • 2021-01-03
  • 2015-06-06
  • 1970-01-01
  • 2021-03-12
  • 2013-02-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多