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
ここでエラーが発生します(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++;
明らかに、これはカーネルモジュールであるため、誰がこれを使用するかは実際にはわかりません。バッファ要素のサイズを固定すると、このバッファの使用が制限されます。
警告を取り除く方法はありますか?それとも、そのようなコードを開発するときに私が別の方法で行うべき基本的なことはありますか?