2011-02-18 79 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*,以避免重复做这种类型转换。

希望这会有所帮助!

相关问题