2 svar
115 visningar
pehr behöver inte mer hjälp
pehr 26 – Fd. Medlem
Postad: 20 dec 2020 19:03 Redigerad: 20 dec 2020 19:15

användning av shared memory shm funktionerna

Hej uppgiften är att ändra programmet så att det gemensamma minnet ska hantera en cirkulär buffert istället för enskilda element.  Hur ska jag göra så att det fungerar med en buffer på 10 element?

Här kommer mitt försök till att få det fungera!

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#define SHMSIZE 128
#define SHM_R 0400
#define SHM_W 0200
#define	SIZE_OF_BUFFER 10 //buffer size 10

float float_rand( float min, float max ) //function to get random numbers between 0.1-2
{
    float scale = rand() / (float) RAND_MAX; /* [0, 1.0] */
    return min + scale * ( max - min );      /* [min, max] */
}

int main(int argc, char **argv)
{
	struct shm_struct //struct for buffer and info about it
	{
		int buffer[SIZE_OF_BUFFER];
		int readIndex;
		int writeIndex;
		int bufferLenght;
		unsigned empty;
	};
	volatile struct shm_struct *shmp = NULL;
	char *addr = NULL;
	pid_t pid = -1;
	int var1 = 0, var2 = 0, shmid = -1;
	struct shmid_ds *shm_buf;

	/* allocate a chunk of shared memory */
	shmid = shmget(IPC_PRIVATE, SHMSIZE, IPC_CREAT | SHM_R | SHM_W);
	shmp = (struct shm_struct *) shmat(shmid, addr, 0);
	shmp->empty = 0;
	shmp->readIndex = 0;
	shmp->writeIndex = 0;
	shmp->bufferLenght = 0;

	pid = fork();
	if (pid != 0) 
	{
		/* here's the parent, acting as producer */
		while (var1 < 100) 
		{
			/* write to shmem */
			var1++;
			while (shmp->empty == 1); /* busy wait until the buffer is empty */
			printf("Sending %d\n", var1); fflush(stdout);
			shmp->buffer[shmp->writeIndex] = var1;
			sleep(float_rand(0.1,2));
			shmp->writeIndex++;

			if(shmp->writeIndex == SIZE_OF_BUFFER)
			{
				shmp->writeIndex = 0;
			}

			shmp->bufferLenght++;
			shmp->empty = 1;
		}
		shmdt(addr);
		shmctl(shmid, IPC_RMID, shm_buf);
	} 
	else 
	{
		/* here's the child, acting as consumer */
		while (var2 < 100) 
		{
			/* read from shmem */
			while (shmp->empty == 0); /* busy wait until there is something */
			var2 = shmp->buffer[shmp->readIndex];
			sleep(float_rand(0.1,2));
			shmp->bufferLenght--;
			shmp->readIndex++;

			if (shmp->readIndex == SIZE_OF_BUFFER) 
			{
				shmp->readIndex = 0;
			}

			shmp->empty = 0;
			printf("Received %d\n", var2); fflush(stdout);
		}
		shmdt(addr);
		shmctl(shmid, IPC_RMID, shm_buf);
	}
}
Laguna 30218
Postad: 20 dec 2020 21:37

Jag trodde på 1990-talet att de här systemanropen var på väg ut, så jag brydde mig inte om att lära mig dem. Jag ska titta när jag är vid en dator (om en vecka). 

jek7 35 – Fd. Medlem
Postad: 21 dec 2020 13:50

Jag känner inte till specifika saker här, och kodar inte i C, men vad jag kan se så borde väl koden fungera utan fel, fast den läser och skriver varannan gång, så även om den går igenom hela ringbuffertern, så används bara ett item i taget, och det är vad du vill ändra?

Det borde således i princip bara vara att ändra while-argumenten där den väntar.

Skrivaren borde vänta ifall bufferten är full, och annars skriva.

Läsaren borde vänta ifall bufferten är tom, och annars läsa.

Båda dom testerna använder lämpligen då på shmp->bufferLength och ev SIZE_OF_BUFFER.

Svara
Close