2011-02-14 27 views
17

Estoy en Linux 2.6. Tengo un entorno en el que 2 procesos simulan (utilizando memoria compartida) el intercambio de datos a través de una implementación simple del modo de paso de mensajes.Compartir memoria entre procesos mediante el uso de mmap()

Tengo un proceso de cliente (en forma de horquilla del padre, que es el servidor) que escribe una estructura (mensaje) a una región de memoria asignada creada (después de que el tenedor) con:

message *m = mmap(NULL, sizeof(message), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0)

Este el puntero se escribe en una cola (en forma de lista vinculada) en otra área de memoria compartida que es común para el proceso del servidor y del cliente (porque se creó antes de la horquilla con el mismo código anterior). Luego, el servidor lee esta área y obtiene el puntero del mensaje y lo procesa.

El problema es que * m se crea después de la horquilla() y cuando el proceso del servidor intenta acceder a la ubicación de la memoria apuntada, aparece un error de segmentación. ¿Es posible adjuntar esa región de memoria al servidor POST bifurcación, después de que el cliente lo cree?

NOTA: No quiero asignar el puntero al mensaje antes de bifurcar (y luego compartirlo antes con el servidor) porque normalmente no sé cuántos mensajes el cliente desea enviar al servidor, y también puede haber más de un proceso de cliente, por lo que me gustaría crear un nuevo bloque de memoria compartida solo cuando un cliente necesita enviar un mensaje, y desasignarlo después de que el servidor haya recibido ese mensaje.

NOTA: Esto es para fines académicos: sé que esta no es la mejor manera de resolver este problema, pero solo tengo que seguir este camino.

¡Gracias de antemano!

Respuesta

25

¿Es posible adjuntar esa región de memoria al servidor POST bifurcación, después de que el cliente lo cree?

MAP_ANONYMOUS|MAP_SHARED memoria asignada sólo se puede acceder por el proceso que hace que mmap() llamada o los procesos hijos. No hay forma de que otro proceso asigne la misma memoria porque no se puede hacer referencia a esa memoria desde ningún otro lugar, ya que es anónimo.

Usando shm_open() llamada es posible crear llamada memoria compartida que puede ser referida y mapeada por procesos no relacionados.

+0

Gracias! Usé 'shm_open()' y luego 'mmap()' con el fd dado, resolvió el problema parcialmente. ¿Es posible cambiar el nombre (usando 'rename()') de la cadena de "etiqueta" que proporciono a 'shm_open()' después de que fd se mmapped? Intenté hacer esto pero luego, cuando trato de usar 'shm_open()' de otro proceso usando la etiqueta renombrada, obtengo un "Error de bus" en tiempo de ejecución. NOTA: Noté que en/sys/shm/existe el archivo renombrado, por lo que el cambio de nombre parece tener éxito. –

+0

'shm_open (" nombre ")' en Linux normalmente se traduce en 'open ("/dev/shm/name ")'. Deberías poder cambiarle el nombre como un archivo normal. Tenga en cuenta que "/ dev/shm /" es el punto de montaje predeterminado de tmpfs en Linux. Se puede mapear en otro lugar. Ver http://www.google.com/codesearch/p?hl=en#xy1xtVWIKOQ/pub/glibc/releases/glibc-2.3.1.tar.bz2%7CQzvfrd4m2kQ/glibc-2.3.1/sysdeps/unix/sysv /linux/shm_open.c&q=where_is_shmfs –

+0

Gracias por la nota. ¿Tienes alguna pista de por qué el cambio de nombre podría causar un error de bus si intento, entonces, acceder a la zona de memoria compartida? –

6

Eso no va a funcionar.

Si crea una asignación después de la horquilla(), no será la misma en el (los) otro (s) proceso (s) relacionado (s).

No puede asumir el intercambio de punteros de esta manera.

Si realmente quieres hacerlo de esta manera (¡no lo recomendaría!), Debes mapear un área grande antes de la horquilla(), luego asignar de alguna manera tampones de un tamaño adecuado (sin condiciones de carrera con otros procesos) , por supuesto!) y pasa esos indicadores.

Dos procesos relacionados que llaman a mmap() después de una bifurcación, pueden obtener el mismo puntero hacia atrás, apuntando a una memoria diferente. De hecho, esto es muy probable.

1

Solo para cualquiera que lea esta pregunta en 2018 y posterior. La solución ahora es usar memfd_create para crear un archivo anónimo y usar un socket unix para pasar este manejador de archivo al otro proceso.

memfd_create es solo un syscall de linux

Cuestiones relacionadas