内核设备驱动程序“取消引用”void *“指针
我正在学习如何为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:警告:取消引用“void *”指针 kringbuf_generic.c:72: warning: dereferencing 'void *' point
错误发生在 putring(in 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++;
显然,因为这是一个内核模块,所以不是真正知道谁会使用它,并且固定缓冲区元素大小将限制该缓冲区的使用。
有什么办法可以摆脱警告吗?或者在开发此类代码时我应该做一些不同的基本事情吗?
I am learning how to write device drivers for linux, and I have a question regarding the use of generic data structures.
I have an assignment, which I have fully functional...so I'm not asking you to do my homework...
This assignment requires a device to be able to enqueue and dequeue elements from a fifo buffer. I made the buffer "generic" so that any element size could be used(and specified at runtime). The source is included below(note this is not the kernel version, but the error is the same)...kernel version requires kmalloc, copy_to/from_user() etc...
#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;
}
When I compile this into a kernel module, I get the warnings:
kringbuf_generic.c:53: warning: dereferencing ‘void *’ pointer
kringbuf_generic.c:72: warning: dereferencing ‘void *’ pointer
The error occurs here in putring(in memcpy)
if ( rbptr->elemCount >= rbptr->capacity )
return -1;
memcpy(&rbptr->RBData[rbptr->putindex * rbptr->elemSize], data, rbptr->elemSize);
rbptr->putindex++;
and here in getring, in the memcpy() function
rbptr->elemCount--;
memcpy(data, &rbptr->RBData[rbptr->getindex * rbptr->elemSize], rbptr->elemSize);
rbptr->getindex++;
Obviously since this is a kernel module, it is not really known who will use this, and the fixing the buffer element size would limit the usage of this buffer.
Is there any way to get rid of the warnings? Or is there some fundamental thing I should be doing differently when developing such code?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我认为问题在于这段代码:
正在尝试索引到
RBData
指向的数组,该数组的类型为void *
。您无法在void*
指针上进行此操作,因为在 C 中索引数组需要您知道数组中元素的大小,并且根据定义,void *
是一个指向未知类型元素的指针。大多数编译器都允许您通过将
void*
隐式转换为char*
并仅读取原始字节值来执行此操作。然而,这样做确实不是一个好主意,因为该操作没有明确定义。要解决此问题并消除警告,请考虑在取消引用之前将
RBData
字段显式转换为char*
:或者,将其存储为
char*< /code> 在你的结构中以避免重复进行这种类型转换。
希望这有帮助!
I think the problem is that this code:
Is trying to index into the array pointed at by
RBData
, which is of typevoid *
. You can't meaningfully make this operation work on avoid*
pointer, because indexing into an array in C requires you to know the size of the elements in the array, and by definition avoid*
is an a pointer to elements of an unknown type.Most compilers let you do this anyway by implicitly casting the
void*
to achar*
and just reading raw byte values. However, it's really not a good idea to do this, since the operation isn't well-defined.To fix this and silence the warning, consider explicitly typecasting the
RBData
field to achar*
before dereferencing it:Or alternatively, just store it as a
char*
in your struct to avoid having to repeatedly do this typecast.Hope this helps!