• Publicidad

Compartir memoria entre procesos

¿Ya sabes lo que es una referencia? Has progresado, el nível básico es cosa del pasado y ahora estás listo para el siguiente nivel.

Compartir memoria entre procesos

Notapor Moraita » 2008-12-05 09:10 @423

Hola .

Pretendo compartir una pila (variable que todavía no he definido) entre dos o varios procesos. De momento estoy en la parte de análisis, sólo quiero asegurarme de que no me complico la vida a la hora de desarrollar. La pila o variable hash será manipulada por un proceso y leída por otro/s procesos.

He leído en el foro que podría usar shared-memory del CPAN. Al buscarlo en el CPAN, entiendo que sería el Cache::SharedMemoryBackend que a su vez utiliza el Cache::Backend.

En caso de que esté bien encaminada, me gustaría aprender sobre esto. Ver ejemplos, saber dónde tengo que definir la variable compartida, cómo manejarla..., etc...

También conocer (antes de desarrollar) cualquier requerimiento tipo (para usar shared memory hay que tener un procesador tal...) o cualquier inconveniente de esta solución que me haga cambiar de estrategia (como por ejemplo implementar la pila con una tabla de base de datos), claro que si lo pregunto es porque "me exigen" de alguna manera utilizar una variable compartida aunque ya os digo, argumentos para desechar esta solución me vendrían de perlas.

He buscado en este foro y en Internet pero no veo dónde podría yo centrarme para conseguir ponerlo en práctica...

¿Alguno puede indicarme dónde encontrar información sobre ésto?...

¡Espero haberme explicado bien!


Muchas gracias,
Mercedes
Moraita
Perlero nuevo
Perlero nuevo
 
Mensajes: 36
Registrado: 2008-10-29 10:25 @475

Publicidad

Notapor creating021 » 2008-12-06 09:55 @455

Si estás en Unix, IPC::SysV puede ser una respuestas, pero creo que es un método un tanto complicado, y en muchos de los casos no es necesario.

Yo nunca lo he usado, así que no puedo decir nada, pero aquí puedes ver un ejemplo.

Te recomiendo leer perlipc en especial Unix-Domain TCP Clients and Servers que te puede servir.
Moraita escribiste:argumentos para desechar esta solución me vendrían de perlas.

De perldoc perlipc:
perlipc escribiste:BUGS
All these routines create system-specific portability problems. As noted elsewhere, Perl is at the mercy of your C libraries for much of its system behaviour. It's probably safest to assume broken SysV semantics for signals and to stick with simple TCP and UDP socket operations; e.g., don't try to pass open file descriptors over a local UDP datagram socket if you want your code to stand a chance of being portable.
Expect the worst, is it the least you can do?
Avatar de Usuario
creating021
Perlero frecuente
Perlero frecuente
 
Mensajes: 595
Registrado: 2006-02-23 16:17 @720
Ubicación: Frente al monitor

Notapor Moraita » 2009-02-02 04:17 @220

¡Hola!

Ya estoy implementando la memoria compartida, he leído y probado los trozos de código de la página que me indicaste.

Solo hay un pequeño lapsus que quizá sea una tontería pero no lo veo...

Tenemos un trozo de código que dicen que comparte memoria, por ejemplo:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
    use IPC::SysV qw(IPC_PRIVATE IPC_RMID S_IRUSR S_IWUSR);
    $size = 2000;
    $id = shmget(IPC_PRIVATE, $size, S_IRUSR|S_IWUSR) || die "$!";
    print "shm key $id\n";    $message = "Message #1";
    shmwrite($id, $message, 0, 60) || die "$!";
    print "wrote: '$message'\n";
    shmread($id, $buff, 0, 60) || die "$!";
    print "read : '$buff'\n";    # the buffer of shmread is zero-character end-padded.
    substr($buff, index($buff, "\0")) = '';
    print "un" unless $buff eq $message;
    print "swell\n";    print "deleting shm $id\n";
    shmctl($id, IPC_RMID, 0) || die "$!";
Coloreado en 0.006 segundos, usando GeSHi 1.0.8.4


¡Vale!, me lo creo pero ¿y ahora qué hago?, ¿cómo implemento que dos o varios procesos compartan?, ¿tienen que llamar a este trozo de código?... ¿es la variable message la que pueden leer todos los procesos que yo quiera?

En fin...

Cualquier apunte será bien venido, y lo siento si es que es tan obvio que no lo indican en la página de perl...

Gracias.
moraita
Moraita
Perlero nuevo
Perlero nuevo
 
Mensajes: 36
Registrado: 2008-10-29 10:25 @475

Notapor explorer » 2009-02-02 06:29 @312

Aquí te pongo un ejemplo.

Supongamos que tenemos un programa A como este:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl
use strict;
use warnings;

use IPC::SysV qw(ftok S_IRUSR S_IWUSR IPC_CREAT IPC_RMID);

## Creación del token único.
## Un token para gobernarlos a todos, un token para encontrarlos,
## un token para atraerlos a todos y atarlos en las Tinieblas
my $TOKEN = ftok('/tmp/',1);
print "Token: $TOKEN\n";

## Creación del buffer de memoria
our $id = shmget($TOKEN, 200, IPC_CREAT|S_IRUSR|S_IWUSR) or die $!;
print "shm key $id\n";

## En caso de parar el programa
## eliminamos la memoria compartida
$SIG{INT} = sub{
    shmctl($id, IPC_RMID, 0);
    exit;
};

## Bucle para el usuario
while (<STDIN>) {
    chomp;

    shmwrite($id, $_, 0, 160) or die $!;        # Escribimos el mensaje

    print "escrito: '$_' : ", length($_), "\n";
}
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4

El programa, en base al $TOKEN creado, solicita 200 bytes de espacio compartido. Luego, entra en un bucle en el que espera la entrada del usuario, que, primero le quita el carácter de final de línea y lo escribe en la memoria compartida.

En caso de que el usuario corte el programa, se activa la subrutina asociada a $SIG{INT}, que se ocupará de liberar el espacio de memoria.

Y luego tenemos el programa B:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl
use strict;
use warnings;

use IPC::SysV qw(ftok S_IRUSR S_IWUSR);

## Creación del token
my $TOKEN = ftok('/tmp/',1);
print "Token: $TOKEN\n";

our $id = shmget($TOKEN, 200, S_IRUSR|S_IWUSR) or die $!;
print "shm key $id\n";

## Bucle para el usuario
my $buffer;
while ('para siempre') {
    sleep 1;                                    # Pausa

    shmread($id, $buffer, 0, 160) or die $!;    # Leemos el mensaje

    substr($buffer, index($buffer, "\0")) = ''; # El buffer está relleno de \0, así que lo recortamos hasta el primer \0

    next if !$buffer;                           # Si no hay nada nuevo, seguiremos esperando

    print "leido: '$buffer' : ", length($buffer),"\n";

    shmwrite($id, '', 0, 160) or die $!;        # Lo ponemos a cero
}
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4

El proceso de unirnos a la memoria compartida es igual que antes. Luego entramos en el bucle sin fin, donde, después de esperar 1 segundo, leemos la memoria compartida. Lo leído, lo recortamos a partir del primer 0 que encontramos, y luego lo pintamos. Como paso final, "borramos" la memoria compartida, para que no esté pintando el mismo mensaje continuamente.

Para probarlo, abre una terminal y ejecuta allí el programa A. En otro terminal, el programa B. Luego, prueba a escribir un mensaje en la terminal del programa A, y observa cómo aparece en la terminal del programa B.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor Moraita » 2009-02-02 09:59 @457

¡jelou!

Entiendo que el token es el espacio de memoria reservado.

Yo pretendo hacer un espacio para cada proceso de los que ejecuto en paralelo, así que he intentado crear varios tokens pero no me deja cambiar el "id" del token, por ejemplo:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
my $TOKEN = ftok('/tmp/',8);
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


en lugar de "1" he puesto "8"

y no funciona... ¿qué es entonces ese 1?
Moraita
Perlero nuevo
Perlero nuevo
 
Mensajes: 36
Registrado: 2008-10-29 10:25 @475

Notapor Moraita » 2009-02-02 10:27 @477

Hola, explorer.

Acabo de encontrar el por qué, el flag IPC_CREAT es para crear la cola en caso de que no exista.

Si yo ejecuto, como estaba haciendo, el programa B antes que el A y llamando a una nueva cola (o buffer o trozo de memoria), no la encontrará porque el programa B no tiene ese flag activado.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
use IPC::SysV qw(ftok S_IRUSR S_IWUSR);
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Thanks!
Moraita
Perlero nuevo
Perlero nuevo
 
Mensajes: 36
Registrado: 2008-10-29 10:25 @475

Notapor explorer » 2009-02-02 11:02 @501

Pues no... ftok() no devuelve ni crea la memoria compartida. Solo crea un identificador único, basado en el path y en el identificador que le sigue. Entre los dos se crea un identificador único (el token).

Esto sirve para que distintos programas puedan acceder a la misma información, sin tener que transmitirse por otros medios el identificador de la memoria compartida, semáforos o colas de mensajes. Otra opción hubiera sido poner my $TOKEN = 12345; en los dos programas. El caso es partir del mismo valor.

Y en cuanto al IPC_CREAT, es natural que solo esté en el programa A, porque se SUPONE que es así como te he pedido que lo ejecutaras, como te escribí en el último párrafo: el programa A crea la memoria compartida con shmget(), la envía con shmwrite() y la destruye con shmctl(). Mientras que el programa B se "conecta" a esa memoria con shmget() y lee lo que hay con shmread().
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor Moraita » 2009-02-03 02:59 @166

Gracias, explorer, he leído un montón de información sobre la memoria compartida (bueno, lo que he encontrado en Internet que tampoco es tanta) y no me enteraba de nada... desde luego que con los ejemplos que me has enviado tú es más que suficiente para entenderlo... y ahora ya con esta explicación, ni te cuento...

¡Muchas gracias!
Moraita
Perlero nuevo
Perlero nuevo
 
Mensajes: 36
Registrado: 2008-10-29 10:25 @475

Notapor creating021 » 2009-02-03 20:11 @882

Hola.

Mirando en CPAN, ví un módulo que puede hacer todo eso más fácil, aunque es sólo para Unix (nada de Windows ni VMS... )

Hablo de IPC::ShareLite.

En teoría el ejemplo de explorer se podría modificar así (no lo he probado).

Programa A:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl
use strict;
use warnings;

use IPC::ShareLite;

my $share = IPC::ShareLite->new(
        -key     => 2009, # ID
        -create  => 'yes',
        -destroy => 'no'
    ) or die "Error: $!";

while (<STDIN>) {
    chomp;

    $share->store( $_ );

    print "escrito: '$_' : ", length($_), "\n";
}
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


Programa B:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl
use strict;
use warnings;

use IPC::ShareLite;

my $share = IPC::ShareLite->new(
        -key     => 2009, # ID
        -create  => 'no', # No hay que crear nada
        -destroy => 'no'
    ) or die "Error: $!";
while ('para siempre') {
    sleep 1; # pausa

    my $buffer = $share->fetch();

    next if !$buffer;

    print "leido: '$buffer' : ", lenght($buffer);
}
 
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4
Expect the worst, is it the least you can do?
Avatar de Usuario
creating021
Perlero frecuente
Perlero frecuente
 
Mensajes: 595
Registrado: 2006-02-23 16:17 @720
Ubicación: Frente al monitor

Notapor salva » 2009-02-04 05:54 @287

Las soluciones de memoria compartida son una fuente inagotable de problemas y a no ser que tengas unos requerimientos de velocidad extremos en general no merecen la pena.

Mi consejo es que utilices una base de datos que admita accesos concurrentes. Por ejemplo, SQLite o BerkeleyDB son bases de datos que se ejecutan dentro del mismo proceso y que no requieren un servidor independiente. Para obtener una buena velocidad de acceso colócalas en un disco RAM.
Avatar de Usuario
salva
Perlero nuevo
Perlero nuevo
 
Mensajes: 200
Registrado: 2008-01-03 15:19 @680

Siguiente

Volver a Intermedio

¿Quién está conectado?

Usuarios navegando por este Foro: Bing [Bot] y 4 invitados

cron