S
Hallo,
ich habe einen Ringpuffer im Shared Memory realisiert. Jedenfalls war das mein Ziel. Das Schreiben funktioniert auch soweit, aber das Lesen leider nicht. Irgendwo in meinem Code muss ein derber Fehler sein, den ich nicht finde. Daher wollte ich bei euch mal Fragen, ob euch was auffällt.
rb.h
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#include <stdio.h>
#define SHMRB_BUFFER_SIZE 8
#define SHMRB_DATA_SIZE 1024
#define DEBUG 1
typedef struct {
size_t length;
unsigned int dataIdx;
} SHMRBElement_t;
typedef struct {
SHMRBElement_t buffer[SHMRB_BUFFER_SIZE];
char data[SHMRB_DATA_SIZE];
unsigned int ri;
unsigned int wi;
unsigned int dri;
unsigned int dwi;
} SHMRBBuffer_t;
typedef SHMRBBuffer_t * SHMRBHandle_t;
int shmrb_create(key_t shm_key, SHMRBHandle_t *handle);
int shmrb_get(key_t shm_key, SHMRBHandle_t *handle);
int shmrb_write(SHMRBHandle_t handle, const char *item, size_t len);
int shmrb_read(SHMRBHandle_t handle, char *item, size_t *len);
rb.c
#include "rb.h"
/**
* Funktion, die Shared-Memory fuer
* den Ringbuffer reserviert und die
* Struktur selbigens in das Shared-
* Memory abbildet.
*
* Parameter:
* shm_key => Key, mit dem das Shared-
* Memory spaeter identifiziert
* werden soll.
* *handle => Pointer auf den Ringbuffer
* im erzeugten Shared-Memory
*
* Rueckgabe:
* -1 => Aufruf fehlgeschlagen
* 0 => Aufruf erfolgreich. In einem
* solchen Fall befindet sich in
* handle ein Verweis auf die Adresse
* des Shared-Memory.
*/
int shmrb_create(key_t shm_key, SHMRBHandle_t *handle)
{
// Shared-Memory in der benoetigten
// Groesse anfordern.
int shmid = shmget(shm_key, sizeof(SHMRBBuffer_t), 0666 | IPC_CREAT);
// Fehler beim reservieren
// des Shared-Memory?
if(shmid == -1)
return -1;
// Pointer auf das Shared-Memory
// in handle speichern.
handle = shmat(shmid, 0, 0);
// Share-Memory anbinden.
// Ist der Pointer korrekt?
if(handle == (void *)-1)
return -1;
// Erfolg zurueckgeben.
return 0;
}
/**
* Funktion, die vorhandenes Shared-Memory
* samt Ringbuffer-Struktur dem Programm
* verfuegbar macht.
*
* Parameter:
* shm_key => Key, mit dem das Shared-
* Memory identifiziert
* werden soll.
* *handle => Pointer auf den Ringbuffer
* im gefundenen Shared-Memory
*
* Rueckgabe:
* -2 => Shared-Memory nicht vorhanden
* -1 => Aufruf fehlgeschlagen
* 0 => Aufruf erfolgreich. In einem
* solchen Fall befindet sich in
* handle ein Verweis auf die Adresse
* des Shared-Memory.
*
*/
int shmrb_get(key_t shm_key, SHMRBHandle_t *handle)
{
// Vorhandenes Shared-Memory
// suchen und ID speichern.
int shmid = shmget(shm_key, sizeof(SHMRBBuffer_t), 0666);
// Shared-Memory nicht vorhanden?
if(shmid == -1)
return -2;
// Pointer auf das Shared-Memory
// in handle speichern.
handle = shmat(shmid, 0, SHM_RDONLY);
// Ist der Pointer korrekt?
if(handle == (void *)-1)
return -1;
// Erfolg zurueckgeben.
return 0;
}
/**
*
*/
int shmrb_write(SHMRBHandle_t handle, const char *item, size_t len)
{
// Sind handle und item korrekte
// Adressen?
if(handle == NULL || item == NULL)
return -1;
// Ist das einzufuegende Element
// groesser als der gesamte Datenbreich?
if(len > SHMRB_DATA_SIZE)
return -2;
// Ist der Datenbereich leer?
if(handle->dwi == handle->dri)
handle->dwi = handle->dri = 0;
// Ist grade nicht genuegend freier Speicher
// am Stueck verfuegbar oder Ringbuffer voll?
if((handle->dwi + len > SHMRB_DATA_SIZE - 1 && len > handle->dri) || handle->wi == handle->ri - 1)
return -3;
// Ist am Ende nicht genug Platz?
if(handle->dwi + len > SHMRB_DATA_SIZE - 1)
{
// An den Anfang schreiben.
memcpy(&handle->data[0], item, len);
handle->dwi = len;
SHMRBElement_t *myRB = &handle->buffer[handle->wi];
myRB->length = len;
myRB->dataIdx = 0;
}
else
{
// An die aktuelle dwi Position schreiben.
memcpy(&handle->data[handle->wi], item, len);
SHMRBElement_t *myRB = &handle->buffer[handle->wi];
myRB->length = len;
myRB->dataIdx = handle->dwi;
handle->dwi += len;
}
// Write-Index an den Anfang
// zuruecksetzen, wenn noetig,
// ansonsten um 1 erhoehen.
if(handle->wi + 1 > SHMRB_BUFFER_SIZE - 1)
handle->wi = 0;
else
handle->wi++;
#ifdef DEBUG
printf("Debug: Writer Index : %d\n", handle->wi);
printf("Debug: Reader Index : %d\n", handle->ri);
printf("Debug: Data Write Index: %d\n", handle->dwi);
printf("Debug: Data Read Index : %d\n", handle->dri);
#endif
// Erfolg zurueckgeben
return 0;
}
/**
*
*/
int shmrb_read(SHMRBHandle_t handle, char *item, size_t *len)
{
#ifdef DEBUG
printf("Debug: Writer Index : %d\n", handle->wi);
printf("Debug: Reader Index : %d\n", handle->ri);
printf("Debug: Data Write Index: %d\n", handle->dwi);
printf("Debug: Data Read Index : %d\n", handle->dri);
#endif
while(1);
// Sind handle und item korrekte
// Adressen?
if(handle == NULL || item == NULL)
return -1;
// Passt das Datenpaket in
// den Puffer?
if(sizeof(item) < *len)
return -2;
// Ist der Ringbuffer
// leer?
if(handle->ri == handle->wi)
return -3;
if(*len > SHMRB_DATA_SIZE - handle->dri)
{
memcpy(item, &handle->data[handle->buffer->dataIdx], SHMRB_DATA_SIZE - handle->dri);
*len = SHMRB_DATA_SIZE - handle->dri;
handle->dri = 0;
}
else if(*len > handle->dwi - handle->dri)
{
memcpy(item, &handle->data[handle->buffer->dataIdx], handle->dwi - handle->dri);
*len = handle->dwi - handle->dri;
handle->dri = handle->dwi;
}
else
{
memcpy(item, &handle->data[handle->buffer->dataIdx], *len);
handle->dri += *len;
}
return 0;
}
reader.c
#include "rb.h"
#include <stdio.h>
int main(int argc, char* argv[])
{
SHMRBHandle_t *handle;
if(shmrb_get((key_t)133742, handle) == -1)
{
printf("Fehler: Shared-Memory konnte nicht angelegt werden.\n");
return -1;
}
char readBuffer[81];
size_t len = 8;
int error = 0;
while(1)
{
int res = shmrb_read(handle, readBuffer, &len);
if(res == -3 && error == 0){
printf("Puffer ist leer!\n");
error = 1;}
else if(res == -2 && error == 0){
printf("Lesepuffer zu klein!\n");
error = 1;}
else if(res == -1 && error == 0) {
printf("Unbekannter Fehler!\n");
error = 1;}
else if (res == 0)
{
printf("Read: ");
printf(readBuffer);
error = 0;
}
}
return 0;
}
#include "rb.h"
#include <stdio.h>
int main(int argc, char* argv[])
{
SHMRBHandle_t *handle;
if(shmrb_create((key_t)133742, handle) == -1)
{
printf("Fehler: Shared-Memory konnte nicht angelegt werden.\n");
return -1;
}
char myItem[81];
while(fgets(myItem, 81, stdin) != NULL)
{
int res = shmrb_write(handle, myItem, sizeof(myItem));
if(res == -3)
printf("Puffer gerade voll!\n");
else if(res == -2)
printf("Puffer allgemein zu klein!\n");
else if(res == -1)
printf("Unbekannter Fehler!\n");
}
return 0;
}
Danke schonmal für eure Bemühungen