Я учусь писать драйверы устройств для 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++;
Очевидно, что поскольку это модуль ядра, на самом деле неизвестно, кто будет его использовать, и исправление размера элемента буфера ограничит использование этого буфера.
Есть ли способ избавиться от предупреждений? Или есть что-то фундаментальное, что я должен делать по-другому при разработке такого кода?