内核设备驱动程序“取消引用”void *“指针

发布于 2024-10-18 06:34:12 字数 3264 浏览 1 评论 0原文

我正在学习如何为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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

暗喜 2024-10-25 06:34:12

我认为问题在于这段代码:

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

正在尝试索引到 RBData 指向的数组,该数组的类型为 void *。您无法在 void* 指针上进行此操作,因为在 C 中索引数组需要您知道数组中元素的大小,并且根据定义,void * 是一个指向未知类型元素的指针。

大多数编译器都允许您通过将 void* 隐式转换为 char* 并仅读取原始字节值来执行此操作。然而,这样做确实不是一个好主意,因为该操作没有明确定义。

要解决此问题并消除警告,请考虑在取消引用之前将 RBData 字段显式转换为 char*

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

或者,将其存储为 char*< /code> 在你的结构中以避免重复进行这种类型转换。

希望这有帮助!

I think the problem is that this code:

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

Is trying to index into the array pointed at by RBData, which is of type void *. You can't meaningfully make this operation work on a void* pointer, because indexing into an array in C requires you to know the size of the elements in the array, and by definition a void* is an a pointer to elements of an unknown type.

Most compilers let you do this anyway by implicitly casting the void* to a char* 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 a char* before dereferencing it:

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

Or alternatively, just store it as a char* in your struct to avoid having to repeatedly do this typecast.

Hope this helps!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文