【问题标题】:casting and the copy_to_user macro铸造和 copy_to_user 宏
【发布时间】:2016-04-16 00:19:47
【问题描述】:

我需要将curr_task->pid(内核空间中的pid_t)复制到用户空间中具有很长空间的结构字段。由于这是一个不断扩大的转换,我预计不会有任何问题。

但是,我收到了一个烦人的编译器警告(copy_long_to_user 的所有意图和目的都与copy_to_user 相同):

cs300/process_ancestors.c:31:3: warning: passing argument 2 of ‘copy_long_to_user’ from incompatible pointer type [enabled by default]
   if(copy_long_to_user(&info_array[num_filled_kernel].pid, &curr_task->pid)) {    
   ^
cs300/process_ancestors.c:9:5: note: expected ‘long int *’ but argument is of type ‘pid_t *’

这个警告是我可以放心忽略的吗(编译器会为我做转换)吗?如果我需要明确地将 curr_task->pid 转换为 long,我该如何在使用 copy_to_user 的情况下做到这一点?我的猜测是:(copy_long_to_user(&info_array[num_filled_kernel].pid, &((long)curr_task->pid)))

【问题讨论】:

  • 希望你不要只参与@ChunleiMa的回答,将copy_long_to_user()的第二个参数的类型设为void*
  • 不,答案让我意识到我做错了什么——我告诉copy_to_user 在源位置只有 4 个字节的数据时复制 8 个字节。
  • 我认为也许像我提到的捷径可能是导致您其他相关问题的原因:stackoverflow.com/questions/36658863/…

标签: c casting linux-kernel


【解决方案1】:

您需要一个辅助变量来正确执行此操作。

long curr_pid = curr_task->pid;
copy_long_to_user(&info_array[num_filled_kernel].pid, &curr_pid);

获取辅助变量的地址是合法的,临时地址(由演员转换产生)是不合法的。

【讨论】:

    【解决方案2】:

    在 Linux 内核中,pid_t 的类型等于 int,因此编译器会警告您 int* 不能转换为 long int*。 我不知道你是怎么实现你的copy_long_to_user函数的,如果你这样写,你可能会得到错误的结果。 copy_long_to_user(long int* dest, long int* src){ copy_to_user(dest, src, sizeof(long int)); ...... } 因为sizeof(long) >= sizeof(int),如果sizeof(long) > sizeof(int),支持sizeof(long) == 8,和sizeof(int) always 4,你会得到错误的结果,因为current_task->pid只占dest的4个字节,但是copy_to_user(dest, src, sizeof(long int))必须复制8个字节到dest,所以current->pid后面的4个字节被复制到dest,所以dest不能等于current->pid。 所以你最好写一个名为copy_pid_to_user的函数,它的代码如下: copy_pid_to_user(long int* dest, void* src){ copy_to_user(dest, src, sizeof(curent->pid)) ......

    【讨论】:

      猜你喜欢
      • 2011-08-01
      • 2015-04-06
      • 2010-10-21
      • 1970-01-01
      • 1970-01-01
      • 2014-05-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多