C/Visual C - Memoria dinámica en memoria compartida en C

   
Vista:

Memoria dinámica en memoria compartida en C

Publicado por alex3193 (1 intervención) el 19/04/2014 16:18:09
Hola,

Necesito crear un bloque de memoria compartida con la siguiente estructura:

1
2
3
4
5
6
typedef struct {
	int semid;
	int *plazas;
	int coches;
	int pidDesapar;
}parking;

Pero necesito reservar memoria para el array de int (plazas), el cual no lo puedo hacer estático. Para crear la zona de memoria realizo lo siguiente:

1
2
id_zone = shmget(key, sizeof(parking) + (sizeof(int) * numPlazas), IPC_CREAT | IPC_EXCL | SHM_R | SHM_W);
buffer = shmat(id_zone, (char *)0, 0);

Pero no se como especificar que sizeof(int) * numPlazas es para el campo plazas.
He probado a hacer

1
buffer->plazas = (int *)malloc(sizeof(int) * numPlazas);

Pero no se crea en memoria compartida.

Gracias de antemano.
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder

Memoria dinámica en memoria compartida en C

Publicado por Pico (37 intervenciones) el 19/04/2014 16:36:40
La memoria compartida dinámica se consigue a través de un fichero, en memoria, no disco, pero fichero.

http://www.chuidiang.com/clinux/ipcs/mem_comp.php
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Memoria dinámica en memoria compartida en C

Publicado por Chema (187 intervenciones) el 19/04/2014 18:21:46
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <sys/ipc.h>
 #include <sys/shm.h>
 
 
typedef struct Parking{
	int semid;
	int coches;
	int pidDesapar;
	int size;
	int nplazas;
	int plazas[1];
}Parking;
 
 #include <sys/ipc.h>
 #include <sys/shm.h>
 
int main(void){
	char *buffer;
	int i;
	int id_zone;
	int key = 1234599;
	id_zone = shmget(key, 8192, IPC_CREAT | IPC_EXCL | SHM_R | SHM_W);
	buffer = shmat(id_zone, (char *)0, 0);
 
	Parking *parking;
	parking = (Parking*)buffer;
 
	parking->size = 8192;
	parking->nplazas =0;
 
	for(i =0; i < 100; i++){
		parking->semid = i;
		parking->coches = i +1;
		parking->pidDesapar = 0;
 
		if( parking->size + sizeof(int) <= 0)
			break;
		parking->size -= sizeof(int);
		parking->plazas[parking->nplazas] = i+1;
		parking->nplazas++;
	}
 
	for(i =0; i < parking->nplazas; i++){
		printf("\n%d",parking->plazas[i]);
	}
 
 
 
	/*Recomendable crear bloques múltiplos de 4, 1024... 8192*/
 
	printf("\n%d",parking->size);
	return 0;
 
}
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Memoria dinámica en memoria compartida en C

Publicado por Chema (187 intervenciones) el 19/04/2014 18:40:53
Pico comentó: La memoria compartida dinámica se consigue a través de un fichero, en memoria, no disco, pero fichero.

¿Seguro? Yo creo que no.

No me malinterpretes, Si te gusta programar en Ansi C debes intentar ser exacto en tus afirmaciones, Recuerda que UNIX/LINUX y Ansi C no son tengologías de Microsoft , donde todo es incierto y cada cual piensa a su manera al ser código cerrado.

La documentación mejor leerla de sitios oficiales, ya lo se, está todo en Ingles, lo siento es necesario conocer subiente ingles si quieres enterarte de verdad y no liarte con webs bienintencionadas pero que lían al lector con ideas raras.

http://linux.die.net/man/2/shmget
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Memoria dinámica en memoria compartida en C

Publicado por Chema (187 intervenciones) el 19/04/2014 19:31:29
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/*La prisas........... Esta versión es ocrrecta me olvide de ciertos detalles
  Si te fijas verás que se puede realizar cualquier tipo de prueba sin necesidad
 de shmget  sobre buffer, una vez sea satisfactorio, buffer = shmat(id_zone, (char *)0, 0);
 se ahorra el tener que cambiar int key  en cada prueba*/
 
typedef struct Parking{
	int semid;
	int coches;
	int pidDesapar;
	int size;
	int nplazas;
	int plazas[1];
}Parking;
 
#define BUFER 200
 
int main(void){
	char *buffer;
	int i;
 
	buffer = malloc(BUFER);
 
	Parking *parking;
	parking = (Parking*)buffer;
 
	parking->size = BUFER - sizeof(Parking);
 
	parking->nplazas =0;
 
	for(i =0; i < 100; i++){
		parking->semid = i;
		parking->coches = i +1;
		parking->pidDesapar = 0;
 
		if( (parking->size - sizeof(int)) <= 0){
			printf("\n----Bloque de memoria sin espacio  %lu", (parking->size - sizeof(int)));
			break;
		}
 
		parking->size -= sizeof(int);
		parking->plazas[parking->nplazas] = i+1;
		parking->nplazas++;
	}
 
	for(i =0; i < parking->nplazas; i++){
		printf("\n%d",parking->plazas[i]);
	}
 
	free(buffer);
	return 0;
 
}
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Memoria dinámica en memoria compartida en C

Publicado por Pico (37 intervenciones) el 19/04/2014 20:09:20
Creo que más bien me has malinterpretado tú a mí, aunque seguramente no sin razón.

Lo que he querido decir es que con un malloc no vas a reservar memoria compartida, que la memoria compartida se reserva de otra manera. Sí, he pensado en el CreateFileMapping del windows, y será por el nombre de esa función por la que muchos asocian memoria compartida con fichero, aunque no tenga nada que ver, pero la idea era simplemente la de dejar claro que una cosa son las funciones de memoria "normal" y otra la de memoria compartida. Aunque al final su uso es exactamente igual, como le has dicho en tu ejemplo: reservas la cantidad de memoria que necesites (con sus funciones) y le pegas la estructura de datos que quieras para acceder a ella.

Yo también recomiendo sitios oficiales aunque sean en inglés (incluso la msdn). Y si tiendo a pegar páginas en español no es porque yo tenga problema con el inglés (por cada libro que tengo en español tengo 10 en inglés), es porque no me vengan al día siguiente diciendo que de esa página que he pegado no entienden nada de nada.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Memoria dinámica en memoria compartida en C

Publicado por Chema (187 intervenciones) el 19/04/2014 23:23:16
Si se usa memoria compartida entre procesos (fork) no se usa igual que malloc, se debe crear un gestor de memoria
que trabaje con posiciones, basta una simple lista enlazada que use posiciones en el bloque en lugar de punteros, cosa nada complicada de realizar.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Memoria dinámica en memoria compartida en C

Publicado por Chema (187 intervenciones) el 20/04/2014 14:40:54
alex3193 lo desea dinámico (¿puntero?), por algún motivo no sabe usar el operador &,


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
typedef struct Parking {
	int semid;
	int *plazas;
	int coches;
	int pidDesapar;
}Parking;
 
 
 int main(void){
	 char *buf = malloc(8192);
	 int i;
	 int *p;
	 Parking *parking;
 
	 parking=( Parking*)buf;
 
	 parking->plazas = (int*)buf+ sizeof (Parking);
 
	 p = parking->plazas;
	 for(i =0; i < 100; i++){
		*p = i;
		p++;
	}
 
	 p = parking->plazas;
	for(i =0; i < 100; i++){
		printf("-%d",*p);
		p++;
	}
	 free(buf);
	 return 0;
 }
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Memoria dinámica en memoria compartida en C

Publicado por Tom (481 intervenciones) el 21/04/2014 11:04:00
Con shmget() obtienes una zona de memoria compartida. Esa memoria, lógicamente, ya está "allocada".
Tú ya has obtenido el espacio en memoria que necesitas, para eso lo has calculado con sizeof(parking) + (sizeof(int) * numPlazas).

No tiene ningún sentido intentar hacer malloc() para un puntero que _ya_ tiene espacio reservado.
Por otra parte, tienes un problema en la definición de tu struct, al meter esa pretendida lista de int en medio de los otros datos: si el tamaño de la lista es variable ¿ como demonios sabe "el programa" dónde están -en memoria- los campos que vienen detrás ?

En tu caso, lo normal es intentar hacer algo como esto:

1
2
3
4
5
6
7
8
9
10
11
struct PARKING {
  int semid;
  int coches;
  int pidDesapar;
  int plazas[];  /* o bien int plazas[0] */
};
 
...
 
struct PARKING *parking = shmat(id_zone, (char *)0, 0);
...

Si has calculado el tamaño correctamente, accederás a los elementos de plazas como a los de un array normal y corriente.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Memoria dinámica en memoria compartida en C

Publicado por Chema (187 intervenciones) el 21/04/2014 21:28:25
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
/* Si int *plazas es un puntero puede situarse en cualquier sitio, si es una
matriz tipo int plazas[] debe estar en el último lugar de la estrucctura
 y al menos tener un elemento , GCC se queja "plazas[1]" */
 
 
typedef struct Parking {
	int semid;
	int *plazas;
	int coches;
	int pidDesapar;
}Parking;
 
#include <sys/ipc.h>     
#include <sys/shm.h>	 
 
int main(void){
 
	char *buf;
	int size;
	Parking parking;
	int i;
	int id_zone;
	int key = 123456;
 
	size = 100 * sizeof(int);/* 100 plazas de parking*/
	buf = malloc(size);
 
	parking.plazas = (int*)buf;
 
	for(i = 0; i < 100; i++){
		parking.plazas[i] = i;
	}
 
	for(i = 0; i < 100; i++){
		printf("-%d",parking.plazas[i]);
 
	}
 
 
	/*Buf es eliminado ,no mantiene ninguna realción con malloc*/
	free(buf);
 
	printf("\n**Memoria compartida****\n");
 
	id_zone = shmget(key,size, IPC_CREAT | IPC_EXCL | SHM_R | SHM_W);
	buf = shmat(id_zone, (char *)0, 0);
 
	parking.plazas = (int*)buf;
 
	for(i = 0; i < 100; i++){
		parking.plazas[i] = i;
	}
 
	for(i = 0; i < 100; i++){
		printf("-%d",parking.plazas[i]);
	}
 
	if (shmdt(buf) == -1) {
        printf("1___Error");
    }
 
    if (shmctl(id_zone, IPC_RMID, NULL) == -1) {
        printf("2___Error");
    }
	return 0;
 
}
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Memoria dinámica en memoria compartida en C

Publicado por Tom (481 intervenciones) el 22/04/2014 11:40:53
Chema, te has liado un poco, seguramente por las prisas ...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/shm.h>
 
struct PARK {
	int	capacidad;
	long	plazas[];
};
 
int	parkId = 1;
 
/* */
int main(int argc, char *argv[]) {
	int	nplazas = atoi(argv[1]);
	size_t	size = sizeof(struct PARK) + (nplazas * sizeof(long));
	key_t parks = ftok("/tmp/parkings.shm", parkId); // File must exist
	int	sid = shmget(parks, size, IPC_CREAT | SHM_R | SHM_W);
	struct PARK	*parking = shmat(sid, NULL, 0);
 
	if(parking == (void*)-1) {
		perror("shmat");
		exit(1);
	}
	parking->capacidad = nplazas;
 
	for(nplazas = 0; nplazas < parking->capacidad; nplazas++) {
		parking->plazas[nplazas] = 0L; // plaza libre.
	}
}
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Memoria dinámica en memoria compartida en C

Publicado por Chema (187 intervenciones) el 22/04/2014 17:43:44
No me he liado, es deformación profesional.

Antes de C99 se usaba long plazas[1], la técnica se le conoce como Struct Hack.

C99 introdujo el concepto de "flexible array member" , se permite long plazas[].

1
2
3
4
typedef struct PARK {
	int	capacidad;
	int	plazas[];
}PARK;

C99 ,GCC no cuenta el tamaño de int plazas[], vale 0 al considerarlo un array de tipo incompleto.
Tamaño de PARK = 4;


1
2
3
4
5
6
typedef struct Parking {
	int	capacidad;
	int	plazas[1];
}Parking;
 
Tamaño de Parking = 8;

Cuando trabajo con memoria compartida todos los datos son alineados en múltiplos de 4, sin punteros y se localizan los datos por su posición y tamaño.
me molesta spbremanera ver 2 int en una estructura y que su tamaño sea 4 , por
ese motivo siempre uso y recomiendo [1];
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Memoria dinámica en memoria compartida en C

Publicado por Tom (481 intervenciones) el 22/04/2014 18:12:26
No, si lo decía porque solamente mapeas a shared memory el array de plazas, aunque mirando mejor ...está claro que es a efectos de demostración.

No me refería a la sintaxis del struct hack (creo recordar que alguna versión anterior de gcc no soportaba plazas[] y crearon su extensión propia plazas[0], pero me puede estar fallando la memoria).

Por otra parte, es un buen punto lo de tener en cuenta el alineamiento en memoria. Lo que yo suelo hacer es usar siempre algún tipo de pragma para forzarlo a 1 (para los struct). Sé que se pierde rendimiento pero ningún desarrollador tiene que preocuparse de si hay "huecos" entre los campos de los struct o no ...

Por ejemplo, en mi código, el array es de tipos long, no int. Compilando con gcc el tamaño del struct es 8, no 4 (aunque no cuente el tamaño de plazas[], sí cuenta su alineamiento, que es a 8 por ser long).

Sin embargo añadiendo __attribute__ ((__packed__)); el asunto es más controlable, el tamaño es 4, no influye el alineamiento.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Memoria dinámica en memoria compartida en C

Publicado por Chema (187 intervenciones) el 22/04/2014 19:29:48
Si te fijas verás que no suelo repetir un ejemplo, la idea es que se vean las posibilidades.

Yo soy partidario de controlar el padding manualmente, añadiendo campos char en cada estructura,
me gusta tener el control en la medida que me dejan.


Estamos hablando de memoria compartida, como ejercicio es simpático aunque en plan profesional te puedo
asegurar que es otro nivel.

Yo trabajo SIEMPRE con sistemas 24*365, con múltiples procesos (fork() ) que usan memoria compartida de forma
intensiva.

Un ejemplo de la organización de un bloque de memoria compartida típico en mis proyectos

Bloque de 10/30 megas.
Bloque: estructuras tamaño fijo de configuración general e individual.
......................................
......................................
......................................
Bloque :listas, matrices ,de tamaño conocido y uso frecuente.
......................................
......................................
......................................
bloque: matriz bufer ficheros. cada fichero abierto mantiene un bufer asociado de lectura y se guarda
..................................... por si se repite la petición de apertura.
.....................................
.....................................
Bloque: datos texto, log, avisos, error.
......................................
......................................
Bloque: Ocasionalmente uso un bloque dedicado al ordenamiento sort() y amigos
......................................
......................................
......................................

Todos los bloques como gestor de memoria usan la típica lista enlazada y la consabida freelist menos el
primer bloque,que es igual a la suma de todas las estructuras de configuración que usan todos los procesos , si un proceso cae y se levanta debe recuperar los datos originales, no puede crear una zona nueva, a todo esto se añade en zona compartida , semáforos, y señales.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar