【问题标题】:Linux- copy_to_user not working, always return the buffer sizeLinux-copy_to_user 不工作,总是返回缓冲区大小
【发布时间】:2014-12-15 23:10:55
【问题描述】:

我在 Linux 内核 (h.w) 中有一个相当大的项目。

部分需要用到copy_to_user函数, 出于某种原因,无论缓冲区大小是多少,它都会返回缓冲区大小(而不是 0)。

你能帮忙吗?

这是我的代码的一部分:

asmlinkage int sys_receive_mpi_message(int rank, char *message, ssize_t message_size)
{

    int reader_rank =-10;
    struct task_struct* p = NULL;
    struct my_message_list* tmp;
    struct list_head *pos, *q;
    struct blabla* tmp1;
    int bufSize = 0;
    int res =0;
    int i=0;
    if ((rank < 0) || (rank > counter))
    {
        return -ESRCH;
    }
    list_for_each(pos, &(my_api_list->list))
    {
        tmp1 = list_entry(pos, struct blabla, list);
        if (tmp1->pid == (current->pid))
        {
            reader_rank = tmp1->place;
            p = tmp1->task_struct_p;
            break;
        }
    }
    if (reader_rank == -10)
    {
        return -ESRCH;
    }

    list_for_each_safe(pos,q, &(p->message_list->list))
    {
        tmp=list_entry(pos, struct my_message_list, list);
        if (tmp->sender_rank == rank)
        {
            if (message_size > (tmp->meesage_size))
            {
                bufSize = tmp->meesage_size;
            }
            else
            {       
                bufSize = message_size;
            }

            res = copy_to_user(message,tmp->message,bufSize);
            if(res != 0)
            {
                return -EFAULT;
            }
            kfree(tmp->message);
            list_del(pos);
            kfree(tmp);
            return (bufSize);       
        }
        return -EFAULT; 
    }
    return -EFAULT; 
}

另外,我有这个结构:

struct my_message_list{

    char* message;
    int meesage_size;
    int sender_rank;
    struct list_head list;
};

更新-我发现我从用户那里收到的消息一直指向 0! 这是否告诉我问题出在包装函数中? 这是我的说唱歌手功能(相关部分):

#include <errno.h>
int receive_mpi_message(int rank, char* message, int message_size)
{
    int res;
    __asm__ 
    (
        "pushl %%eax;" 
        "pushl %%ebx;" 
        "pushl %%ecx;" 
        "pushl %%edx;"
        "movl $245, %%eax;"
        "movl %1, %%ebx;"
        "int $0x80;"
        "movl %%eax,%0;"
        "popl %%edx;"
        "popl %%ecx;" 
        "popl %%ebx;" 
        "popl %%eax;" 
        : "=m" (res)
        :"m"(rank),"m"(message),"m"(message_size)
    ); 

    if (res >= (unsigned long)(-125))
    {
        errno = -res;
        res = -1;
    }
    return (int) res;
}

【问题讨论】:

  • 这段代码中没有标记为__user的指针。
  • @CL。这个指针有什么作用?

标签: c linux linux-kernel


【解决方案1】:

您使用什么用户空间界面进行通信?无论您使用什么用户空间接口(chardev、ioctl、...),您所挂接的函数定义的签名都应该具有__user 属性。

例如:fs.h

struct file_operations {
    ...
    ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
    ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
    ...    
}

所以char *message 变量应该char __user *message,看看你使用的用户空间界面。

另一件事可能是您在错误的位置调用该方法。据我所知,copy_*_user 函数只允许从用户空间调用。如果我错了,请有人纠正我。

【讨论】:

  • 我有自己的说唱歌手功能,你的意思是这个还是别的什么?
【解决方案2】:

您要复制的日期不知何故无法复制,例如,您无法读取源或写入目标。在 arch/x86/lib/usercopy_32.c 中有解释:

/*
 * Returns number of bytes that could not be copied.
 * On success, this will be zero.
 */

【讨论】:

    【解决方案3】:

    我的说唱歌手功能有问题, 忘记将数据存储到所有寄存器:

    int receive_mpi_message(int rank, char* message, int message_size)
    {
        int res;
        __asm__ 
        (
             "pushl %%eax;"
             "pushl %%ebx;"
             "pushl %%ecx;"
             "pushl %%edx;"
             "movl $245, %%eax;"
             "movl %1, %%ebx;"
             "movl %2, %%ecx;"
             "movl %3, %%edx;"
             "int $0x80;"
             "movl %%eax,%0;"
             "popl %%edx;"
             "popl %%ecx;"
             "popl %%ebx;"
             "popl %%eax;"
            : "=m" (res)
            :"m"(rank),"m"(message),"m"(message_size)
        ); 
    
        if (res >= (unsigned long)(-125))
        {
            errno = -res;
            res = -1;
        }
        return (int) res;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-06-28
      • 2020-09-05
      • 2015-03-10
      • 2017-03-21
      • 2021-07-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多