copy_to_user在内核模块中不起作用

时间:2013-01-24 07:39:02

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

我试图在内核模块读取函数中使用copy_to_user,但是无法将数据从内核复制到用户缓冲区。如果我犯了一些错误,请有人告诉我。我的内核版本是2.6.35。我给出了内核模块的一部分以及用于测试它的应用程序。现在我的重点是为什么这个copy_to_user不起作用。任何帮助都会很棒。

///////////////////////////////////kernel module//////////////////////////////////////

#define BUF_LEN 80

static char msg[BUF_LEN];       
static char *msg_Ptr;

static int device_open(struct inode *inode, struct file *file)
{
static int counter = 0;

if (Device_Open)
    return -EBUSY;

Device_Open++;
printk(KERN_ALERT "In open device call\n");

sprintf(msg, "I already told you %d times Hello world!\n", counter++);
msg_Ptr = msg;
try_module_get(THIS_MODULE);

return SUCCESS;
}


static ssize_t device_read(struct file *filp,    
           char __user *buffer,    
           size_t length,    
           loff_t * offset)
{
/*
 * Number of bytes actually written to the buffer 
 */
int bytes_read = 0;

/*
 * If we are at the end of the message, 
 * return 0 signifying end of file 
 */
if (*msg_Ptr == 0)
    return 0;

/* 
 * Actually put the data into the buffer 
 */


else {
    bytes_read=copy_to_user(buffer, msg, length);
    if (bytes_read==-1);
        {
         printk(KERN_INFO "Error in else while copying the data \n");
        }

    }

   return bytes_read;
}






////////////////////////////////////////application////////////////////////
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> 
#include <stdlib.h>

#define  BUF_SIZE    40

int main()
{
ssize_t num_bytes;
int fd, n=0;
char buf[BUF_SIZE];

fd=open("/dev/chardev", O_RDWR);
if(fd== -1){perror("Error while opening device");exit(1);}

printf("fd=%d\n",fd);
num_bytes=read(fd, buf, BUF_SIZE);
if(num_bytes==-1){perror("Error while reading"); exit(2);}

printf("The value fetched is %lu bytes\n", num_bytes);

while(n<=num_bytes)
    {
        printf("%c",buf[n]);
        n++;
    }

close(fd);
return 0;

}

2 个答案:

答案 0 :(得分:2)

您编写的代码段中存在一些问题。首先,拨打电话try_module_get(THIS_MODULE);是不是一件好事 此语句尝试在模块本身中增加模块的引用计数!相反,您应该在init方法中将 file_ops 结构的owner字段设置为THIS_MODULE。这样,引用处理将在VFS层中的外部模块代码中发生。您可以查看Linux Kernel Modules: When to use try_module_get / module_put 然后,正如Vineet所说,您应该从 file_ops private_data字段中检索指针。

最后但并非最不重要的是,这就是为什么它似乎发生错误的原因......实际上......它没有: 如果copy_to_user调用已成功将所有需要的字节复制到目标存储区中,则/* Kernel part */ bytes_read=copy_to_user(buffer, msg, length); /* * Wrong error checking : * In the below statement, "-1" is viewed as an unsigned long. * With a simple equality test, this will not bother you * But this is dangerous with other comparisons like "<" or ">" * (unsigned long)(-1) is at least 2^32 - 1 so ... */ if (-1 == bytes_read) { /* etc. */ } return bytes_read; /* App part */ num_bytes=read(fd, buf, BUF_SIZE); /* etc.. */ while(n<=num_bytes) { printf("%c",buf[n]); n++; } 调用返回0;如果出错,则表示 NOT 复制的字节数的严格正值。那说,当你跑:

copy_to_user

成功复制时只能获得一个字符,在您的情况下只有一个“我”。 此外,您使用msg_Ptr指针作为安全措施,但您永远不会更新它。这可能会导致对copy_to_user的错误调用 access_ok通过调用{{1}}来检查用户空间指针,但是如果内核空间指针和给定长度不是正确的话,这可能以内核Oops / Panic结束。

答案 1 :(得分:0)

我认为你应该在open中更新file-&gt; private_data,然后你必须在你的结构中获取它。因为我猜msg缓冲区(内核缓冲区)没有得到正确的引用。