Problema con memoria compartida(C)

BRaDoLH

Bueno dado que mi profesor es un incompetente y por mucho que busco en google no encuentro nada os pongo a continuación un sencillo codigo que en cuanto saque el error lo podré implantar en un programa mayor.

#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<time.h>
 



typedef struct 

{

int numero;

char tipo[2];

char jugada[4];

}baraja;

void main()
{
	int i=0,id=0,segsize=0,pid=1,estado=0,direccion=0;
	key_t KEY;
	char *archivo;
	int idkey;
	baraja jugadas[5][10];
	segsize=sizeof(jugadas)/sizeof(baraja);
	baraja *juego;
	struct shmid_ds shmbuf;
	
archivo="/home/jJuego/hijos/memoriacompartida/llave.cle";
idkey=1234;

KEY=ftok(archivo,idkey);

id=shmget(KEY,segsize,IPC_CREAT | 0666);
printf("%i \n",id);
	if(id<0)
	{
	printf("ERROR EN CREADOR: FALLO EL SHMGET\n");
	}
juego=(struct baraja*) shmat(id,0,0);
direccion=&jugadas[1][3].numero;
juego=direccion;
pid=fork();

	if(pid==0) //hijo
		{
		KEY=ftok(archivo,idkey);
		id=shmget(KEY,segsize,0);
		juego=(struct baraja*) shmat(id,0,0);
		juego=direccion;
		juego->numero=9;
		printf("%i\n",juego->numero);
		
		}
	else // padre
		{
		wait(&estado);
		printf("%i\n",jugadas[1][3].numero);			
		}

}

Resultado:
9
24 --> OMFG?¿?

quiero que el padre imprima el numero que le he indicado en el hijo

JuAn4k4

El hijo no cambia la variable estado, no ? EDIT: Que por cierto no la veo en ningun sitio.

Lo que deberia pasar en teoria es:

Hijo entra en seccion critica.
Hijo cambia el valor de la variable
Hijo sale de la seccion critica.
Padre entra en seccion critica
Padre mira el resultado
Padre sale de seccion critica.

no ?

Dale a estado el valor 0 y que el hijo la ponga a 1 una vez ponga el resultado. Por google tendras que buscar "semaforos" me imagino que querras.

BRaDoLH

Si, eso es lo que quiero hacer, pero sin semaforos ya que aún no hemos llegado a darlo

Ahora me he dado cuenta que jugadas no es la zona compartida sino que es juego,, al igualar la dirección de memoria de jugadas a juego.. entonces en el hijo cambiar el valor pero en el padre como no es la zona compartida pues no la lee bien.

Entonces creo que me tocaría pasar todo a punteros, que no me gustan nada(los utilizamos lo justo y necesario).

como sería en punteros jugadas[1][2].numero?

sé que sería algo así ((juego+1)+2) pero como le indico que tiene que ponerlo en numero?

B

EDITADO xD

No puede ser un problema de entrar en la seccion critica.

No puede ser un problema de lectura despues de escritura, ya que lee primero el hijo (despues de escribir), y luego seguidamente el padre. Ya que si te sale 9 y 24 esa es la secuencia xD

Solo se me ocurre que no estan apuntando al mismo sitio.

El jugadas[1][3].numero del padre no es el mismo del hijo.

pd: yo no es que sea un experto xD, asi que seguramente estare equivocado, pero leyendo el codigo no se me ocurre otra cosa, prueba a poner el mismo printf con el mismo puntero a los dos.

LOc0

juego=(struct baraja*) shmat(id,0,0);

direccion=&jugadas[1][3].numero;

juego=direccion;

pid=fork();

#

Eso no tiene mucho sentido. Primero asignas a juego la dirección del principio de la memoria compartida y luego la cambias con la dirección de jugadas[1][3].numero.

Después viene el fork() que como sabrás hace una copia casi exacta del proceso padre, asi que tp tiene sentido que en el proceso hijo vuelvas a hacer lo mismo.

if(pid==0) //hijo

{

KEY=ftok(archivo,idkey);

id=shmget(KEY,segsize,0);

juego=(struct baraja*) shmat(id,0,0);

juego=direccion;

juego->numero=9;

printf("%i\n",juego->numero);

#

}

else // padre

{

wait(&estado);

printf("%i\n",jugadas[1][3].numero);

}

Resumiendo, lo que quieres hacer debería de funcionar con:

En el padre:

id=shmget(KEY, sizeof(struct baraja), IPC_CREAT | 0666);
printf("%i \n",id);
if(id<0)
{
printf("ERROR EN CREADOR: FALLO EL SHMGET\n");
}
juego=(struct baraja*) shmat(id,0,0);
pid=fork();

En el hijo:


if(pid==0) //hijo
{
juego->numero=9;
printf("%i\n",juego->numero);
}

Salu2 ;)

PD: Si en vez de un elemento de tipo baraja, usas una matriz de [5][10], la forma de asignar en el proceso hijo el elemento [2][3] por ejemplo, sería (*(juego+2)+3)

BRaDoLH

Bueno primero gracias por las respuestas.

y bueno, no sabia que el proceso hijo podía aprovechar las funciones de memoria compartida del proceso padre, solo por lo de IPC_CREAT supuse que se tendría que poner en el hijo, pero bueno parece que no.

Loco tal como tú dices si funciona, es más me funcionó hace unos dias pero con dos procesos diferentes, y bueno ahora con tu ayuda también con hijos, el problema estaba en que estaba apuntando a esta estructura:
baraja jugadas[5][10]
cuando tenía que apuntar a la zona compartida.
Asi es como lo tenía antes

juego=&jugadas[jugador][jugada_turno];

asignar_carta(juego,carta,jugador,jugada_turno);

Pero el problema que tengo ahora es que si lo hize asi es porque no tengo mucha idea de punteros y no quise hacerlo con ellos.

necesitaría saber cual sería el equivalente a esto en punteros

jugadas[2][3].numero

sabiendo esto ya me funcionaría!

#5 thx!! entonces tendira que cambiar esto no?

id=shmget(KEY, sizeof(struct baraja), IPC_CREAT | 0666);

cuando pongo el (*(juego+2)+3)->numero=9 me da el siguiente error
operadores inválidos para el binario +

me falta alguna libreria?

#include <stdio.h>

#include <string.h>

#include <stdlib.h>
#include <stdio_ext.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<time.h>

LOc0

Ese error no es de cabeceras. Es porque supuestamente no te deja sumarle a juego.

Pega EL código que tengas en www.pastebin.es

Salu2 ;)

BRaDoLH

Tiene 1500 lineas xd

http://pastebin.es/2207

te digo las lineas que creo que pueden tener error

11
814 a 844
1232 a 1256

Es el juego del 21, quien llegue a 21 o más se aproxime gana y bueno , hay muchas funciones quizás la mas significativa es la de asignar cartas donde guardo los valores que salen dentro de la estructura,luego los leo, quiero que estos valores se guardan en la zona compartida para que el hijo puede tirar una carta y el padre pueda consultar que carta ha tirado para comprobar resultados. Antes de crear el hijo se reparten 2 cartas a cada jugador por lo que el turno es 2.
Jugadas[5][10] dónde 5 eran los jugadores y 10 sus posibles tiradas.

LOc0

Bueno, ahora mismo no tengo tiempo para mirarlo a fondo, pero te repito lo de antes. Cuando tú reservas memoria compartida, si todo va bien obtienes UN PUNTERO al principio de un segmento que es "lineal". Por lo tanto, si lo que quieres es "convertir" esa ristra de memoria en una matriz tendrás que ingeniártelas (googlea porque hay varias formas).

La forma cutre es una función que le pases la fila, la columna y el total de columnas y te devuelva el elemento. Por ejemplo, reservas memoria para un segmento de 50 elementos.
[0][1]...[48][49]

pero quieres tratarlo como una matriz de [5][10]

Para acceder al elemento [2][4], por ejemplo, tendrías que recorrer la fila [0] entera, luego la [1] entera y en la fila [2] recorrer hasta el elemento [4] Es decir, tendrías que coger el elemento 10+10+4

[0][1]...[8][9]#[10][11]...[18][19]#[20][21][22][23][24]

Si quieres asignar al elemento [2][4] un 9, por ejemplo:


id=shmget(KEY, (50)*sizeof(struct baraja), IPC_CREAT | 0666);

juego=(struct baraja*) shmat(id,0,0);

juego[dame_pos(2, 4, 10)].numero=9;

dame_pos(fila, col, tot_col) es la función que te digo que tendrías que hacerte.

Salu2 ;)

BRaDoLH

Gracias tio, entiendo lo que dices, aver como me las arreglo :D

EDIT: Ya me funciona, gracias!!

Usuarios habituales