2017-01-09 125 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'。 –

相關問題