Memoria compartida en C++ 
El uso de la memoria compartida en sistemas operativos compatibles SystemV y BSD (como Linux, FreeBSD, OSX, etc.) siempre ha estado tradicionalmente asociado al uso del lenguaje C. Sin embargo, si estamos en C++, podemos utilizar la memoria compartida sin renunciar al paradigma de la orientación a objetos: Creando objetos en dicha memoria compartida. Estos “objetos compartidos” serán accesibles, al estar alojados en memoria compartida, desde todos los procesos que tengan acceso a ella.

El truco consiste simplemente en redefinir el operador “new” para la clase de los objetos que queremos compartir:
extern "C++" {
    using namespace std;
    namespace avelino {
        class TShared {
            private:
                int a;
            public:
                TShared();
                void setA(int v);
                int getA();
                static void *memArea;
                void *operator new (unsigned int size);
        };
    }
}
...
void *TShared::operator new (unsigned int size) {
    return TShared::memArea;
}

Como se puede observar, hacemos que new TShared() devuelva un puntero a un área de memoria controlada por nosotros (no estoy implementando el delete ni estoy realizando una gestión de memoria como tal: obsérvese que dos new TShared() seguidos devolverían la misma posición de memoria, estoy haciéndolo así para facilitar la comprensión).

Bueno, ya tenemos una clase que, al hacerle new nos va a devolver un puntero a una dirección de memoria controlada por nosotros. Ahora sólo nos queda inicializar dicho puntero adecuadamente.

Debe haber un proceso que cree el objeto en memoria compartida:
int shmid = shmget(SHM_KEY, sizeof(TShared), IPC_CREAT | IPC_EXCL | 0700);
TShared::memArea = shmat(shmid, NULL, 0);
TShared *p = new TShared();
p->setA(12345);

Como se puede ver, antes de hacer el new TShared() inicializo TShared::memArea con la zona de memoria compartida que acabo de crear (he omitido, por claridad, los if que controlan los posibles errores que puedan devolver la funciones shmget, shmat, etc.). Ahora nuestro objeto de tipo TShared está en la memoria compartida identificada por SHM_KEY (una constante cualquiera definida por nosotros y mayor que cero).

Si otro proceso quiere acceder a dicho “objeto compartido” sólo tendrá que acceder a dicha memoria compartida y hacer el cast correspondiente:
int shmid = shmget(SHM_KEY, sizeof(TShared), 0700);
TShared::memArea = shmat(shmid, NULL, 0);
TShared *p = (TShared *) TShared::memArea;
cout << "a = " << p->getA() << endl;

El código fuente completo lo he puesto en la sección soft de la web.


Administrator (Avelino Herrera Morales) 
Si, claro, se podría (y se debería) encapsular. Con respecto a los posibles errores que devuelva shmget y shmat, para eso están las excepciones como bien dices. Gracias por comentar :-).

Carlos Moisés 
Muy didáctico.
Supongo que se podría encapusular la reserva de memoria compartida dentro del constructor, que incluso podría el tener SHM_KEY como argumento. ¿O hay alguna limitación que obligue a hacerlo desde fuera y previamente? Eso sí, se perderían los códigos de error devueltos por shget, shmat, etc (habría que usar excepciones).

Comentarios 
Lo sentimos. No se permiten nuevos comentarios después de 90 días.