J'apprends comment écrire des pilotes de périphériques pour Linux, et j'ai une question concernant l'utilisation des structures de données génériques.pilote de périphérique du noyau « déréférencement pointeur « void * »
J'ai une mission, que j'ai pleinement fonctionnel ... donc je ne vous demande pas de faire mes devoirs ...
Cette affectation nécessite un périphérique pour pouvoir mettre en file d'attente et retirer des éléments d'un tampon FIFO. La taille de l'élément peut être utilisée (et spécifiée à l'exécution) La source est incluse ci-dessous (notez que ce n'est pas la version du noyau, mais l'erreur est la même) ... la version du noyau requiert 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;
}
Quand je compile ce dans un module du noyau, je reçois les avertissements:
kringbuf_generic.c:53: warning: dereferencing ‘void *’ pointer kringbuf_generic.c:72: warning: dereferencing ‘void *’ pointer
L'erreur se produit ici à putring (en memcpy)
if (rbptr->elemCount >= rbptr->capacity)
return -1;
memcpy(&rbptr->RBData[rbptr->putindex * rbptr->elemSize], data, rbptr->elemSize);
rbptr->putindex++;
et ici getring , dans la fonction memcpy()
rbptr->elemCount--;
memcpy(data, &rbptr->RBData[rbptr->getindex * rbptr->elemSize], rbptr->elemSize);
rbptr->getindex++;
Évidemment, puisqu'il s'agit d'un module noyau, on ne sait pas vraiment qui va l'utiliser, et la fixation de la taille de l'élément tampon limiterait l'utilisation de ce tampon.
Y a-t-il un moyen de se débarrasser des avertissements? Ou y a-t-il quelque chose de fondamental que je devrais faire différemment en développant un tel code?
Désolé, je ne vais pas compter les lignes pour savoir quelle est la ligne 72. Mais ne pouvez-vous pas éliminer l'avertissement avec un classeur? –
Serait bien si vous nous avez dit où l'erreur se produit. Je suppose que c'est la ligne copy_to_user? Quel est le deuxième argument pour copy_to_user? – EboMike
désolé lol, corrigé. changé le code en une version que n'importe qui peut utiliser (noyau non). – user623879