2011-02-18 73 views
1

我學習如何編寫設備驅動程序的Linux和我有關於使用通用數據結構的問題。內核設備驅動程序「提領‘無效*’指針

我有一個任務,我有充分功能...所以我不要求你做我的功課...

這個任務需要一個設備能夠從fifo緩衝區入隊和出隊元素我做了緩衝區「通用」,以便任何可以使用元素大小(並在運行時指定)。源包含在下面(注意這不是內核版本,但錯誤是一樣的)...內核版本需要kmalloc,copy_to/from_user()等...

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

struct RB_Buffer 
{ 
    void* RBData; 
    unsigned int getindex; //index to remove element 
    unsigned int putindex; //index to put element at 
    unsigned int capacity; //max elements buffer holds 
    unsigned int elemCount; //num elements inserted 
    unsigned int elemSize; //size of each element 
}; 

void* RB_kcreate(int numElements, unsigned int elementSize); 
int putring(struct RB_Buffer *rbptr, void* data); 
int getring(struct RB_Buffer *rbptr, void* data); 


//Creates a Ring buffer of specified number of elements and element size. 
//Returns void* pointer pointing to the RB_Buffer struct. This pointer can 
//then be used on putring and getring functions. 
void* RB_kcreate(int numElements, unsigned int elementSize) 
{ 
    struct RB_Buffer *newBuf = malloc(sizeof(struct RB_Buffer)); 
    if(newBuf == NULL) return 0; 
    newBuf->RBData = (void*)malloc(elementSize*numElements);//, GFP_KERNEL); 
    if(newBuf->RBData == NULL) 
    { 
     free(newBuf); 
     return 0; 
    } 
    newBuf->capacity = numElements; 
    newBuf->elemSize = elementSize; 
     newBuf->getindex = 0; 
     newBuf->putindex = 0; 
     newBuf->elemCount = 0; 

    return newBuf; 
} 

//puts an element in the buffer. Returns -1 if full, 0 on success 
//send data through void* data argument 
int putring(struct RB_Buffer *rbptr, void* data) 
{ 
    int i = 0; 
    if (rbptr->elemCount >= rbptr->capacity) 
     return -1; 

    memcpy(&rbptr->RBData[rbptr->putindex * rbptr->elemSize], data, rbptr->elemSize); 
    rbptr->putindex++; 
    if (rbptr->putindex >= rbptr->capacity) 
     rbptr->putindex = 0; 
    rbptr->elemCount++; 

    return 0; 
} 

//removes an element in the buffer. Returns -1 if empty, 0 on success 
//data is returned through the data pointer 
int getring(struct RB_Buffer *rbptr, void *data) 
{ 
    if (!rbptr->elemCount) 
     return -1; 


    rbptr->elemCount--; 
    memcpy(data, &rbptr->RBData[rbptr->getindex * rbptr->elemSize], rbptr->elemSize); 
    rbptr->getindex++; 
    if (rbptr->getindex >= rbptr->capacity) 
     rbptr->getindex = 0; 

    return 0; 

} 

當我編譯成一個內核模塊,我得到了警告:

kringbuf_generic.c:53: warning: dereferencing ‘void *’ pointer kringbuf_generic.c:72: warning: dereferencing ‘void *’ pointer

這裏發生在putring(中的memcpy)

if (rbptr->elemCount >= rbptr->capacity) 
      return -1; 

     memcpy(&rbptr->RBData[rbptr->putindex * rbptr->elemSize], data, rbptr->elemSize); 
     rbptr->putindex++; 

錯誤,並在這裏getring ,在memcpy()函數中

rbptr->elemCount--; 
     memcpy(data, &rbptr->RBData[rbptr->getindex * rbptr->elemSize], rbptr->elemSize); 
     rbptr->getindex++; 

很明顯,因爲這是一個內核模塊,所以不知道誰會使用它,修復緩衝區大小會限制這個緩衝區的使用。

有什麼辦法擺脫警告?或者在開發這樣的代碼時,我應該採取不同的基本方式?

+0

對不起,我不打算計算出哪一行是第72行。但是不能用字符串消除警告嗎? – 2011-02-18 22:49:03

+0

如果您告訴我們錯誤發生在哪裏,會很好。我想這是copy_to_user行? copy_to_user的第二個參數是什麼? – EboMike 2011-02-18 22:50:06

回答

4

我認爲這個問題是此代碼:

rbptr->RBData[rbptr->getindex * rbptr->elemSize] 

試圖索引到數組中指出的RBData,這是void *類型。您不能在void*指針上有效地執行此操作,因爲索引到C中的數組需要您知道數組中元素的大小,根據定義,void*是指向未知類型元素的指針。

大多數編譯器都可以通過隱式地將void*轉換爲char*並只讀取原始字節值來完成此操作。但是,這樣做確實不是一個好主意,因爲操作沒有很好的定義。

要解決這個問題,並沉默的警告,請考慮明確類型轉換的RBData領域的char*解引用之前:

((char *)rbptr->RBData)[rbptr->getindex * rbptr->elemSize] 

或者,只是將其存儲在你的結構一個char*,以避免重複做這種類型轉換。

希望這會有所幫助!

相關問題