2017-01-09 126 views
1

我有一个结构像这样:Linux设备驱动程序:从内核复制字符串到用户空间

typedef struct 
{ 
    char* BUFFER; 
    int Size; 
}DataTransfer; 

在我的IOCTL功能我试图填充结构,并传递给用户空间:

case CHAR_DRIVER_IOCQREAD: 
    printk(KERN_INFO "In CHAR_DRIVER_IOCQREAD"); 
    dataTransfer.BUFFER = kmalloc(strlen_user("Hello") +1, GFP_KERNEL); 
    dataTransfer.Size = strlen_user("Hello") +1; 
    error_count = copy_to_user((DataTransfer*) arg, &dataTransfer, sizeof(dataTransfer)); 

在用户空间我试图接收结构如下:

DataTransfer dataTransfer; 
if(ioctl(fd, CHAR_DRIVER_IOCQREAD, &dataTransfer) < 0) 
{ 
    perror("ERROR in ioctl CHAR_DRIVER_IOCQREAD"); 
} 
else 
{ 
    printf("Kernel returned size %d \n", dataTransfer.Size); 
    printf("Kernel returned string %s \n", dataTransfer.BUFFER); 
} 

这样做的正确方法是什么?

+0

[从内核空间到用户空间复制数据(的可能的复制http://stackoverflow.com/questions/34159622/copy-data-from-kernel-space-用户空间) – levengli

+0

zOMG,你从哪里得到这种风格?! – 0andriy

+0

@ 0andriy我不明白你的意思吗? –

回答

3

这里有几个问题。首先,您将结构复制到用户空间,但不是它指向的字符串。该结构将指向您分配哪个用户空间无法访问的内核内存。其次,你正在分配内核内存,但实际上并没有放置任何东西。

这样做的一种方法是用户空间为IOCtl分配内存以将字符串写入,然后将类似于DataTransfer的结构传递给描述其分配的内存的IOCtl。内核使用copy_from_user从用户内存中读取结构,然后,如果分配的缓冲区足够大以容纳该字符串,则在结构内部使用copy_to_user将其地址写入该地址。

E.g. (内核侧,只画出):

case CHAR_DRIVER_IOCQREAD: 
    DataTransfer dataTransfer; 
    if (copy_from_user(&dataTransfer, arg, sizeof(dataTransfer))) 
     return -EFAULT; 
    if (dataTransfer.Size < strlen(myString) + 1) 
     return -ENOMEM; 
    if (copy_to_user(dataTransfer.BUFFER, myString, strlen(myString) + 1)) 
     return -EFAULT; 
+0

很好的答案!当'dataTransfer.Size'太小而不能容纳字符串时,我不确定什么是最合适的错误代码,但可能是'-EOVERFLOW'。 –

相关问题