Página 1 de 1

Mismo manejador de archivo con distintos hilos

NotaPublicado: 2015-04-10 09:16 @427
por estudiante
Hola, ¿hay alguna manera de que desde distintos hilos puedan escribir en el mismo fichero sin sobrescribir información ya escrita?

Un saludo y gracias.

Re: Mismo manejador de archivo con distintos hilos

NotaPublicado: 2015-04-10 12:08 @547
por explorer
Hay módulos, como Sys::Mmap, que permite compartir los contenidos de un archivo entre varios hilos.

Otra cosa es escribir un archivo de registro, un log. ¿Es ese el caso?

Re: Mismo manejador de archivo con distintos hilos

NotaPublicado: 2015-04-10 14:30 @646
por estudiante
Hola, explorer, efectivamente estoy intentando que varios hilos escriban en un fichero que es un log.

¿No hay alguna manera de compartir el descriptor de fichero entre los distintos hilos al igual que se hace con las variables?

Otra duda que tengo, es si da problemas abrir el mismo fichero siempre en lectura con distintos descriptores de ficheros y pasar a cada hilo un descriptor diferente (como yo lo entiendo cada vez que creo un descriptor apunta a la primera línea del fichero y mientras solo abra el fichero del mismo modo, no debería de dar problema).

Un saludo.

Re: Mismo manejador de archivo con distintos hilos

NotaPublicado: 2015-04-10 16:52 @744
por explorer
Bueno, la forma moderna de abrir un archivo es así:

open my $HANDLE, '>>', 'archivo.log';

Así que ya ves que el gestor de archivo es una variable. Y por lo tanto, la puedes compartir entre los distintos hilos.

Ahora bien... es muy posible que varios hilos intenten escribir a la vez. Mientras un hilo está escribiendo algo, en ese momento puede entrar en la CPU el contexto de otro hilo, que escribirá su correspondiente salida. Luego regresa al primero hilo, que escribirá el resto. Así que la salida queda mezclada.

Habría que usar un sistema de bloqueo en el acceso, o un sistema parecido a lo que usan programas como Apache, que permiten que varios hilos accedan a los mismos registros (la verdad, no sé cómo lo hacen, creo que tiene que ver con tuberías -pipes-, pero no lo he mirado).

Si abres el mismo archivo pero con descriptores diferentes, cada descriptor guardará un puntero de posicionamiento de escritura diferente, por lo que la salida de un hilo quedará sobrescrito por la salida de los demás.

El asunto es complejo, sin duda. La clave está en lo siguiente: en los sistemas UNIX es casi imposible realizar una operación de escritura en un archivo, de forma simultánea, sin corromper el propio archivo.

Hay varias opciones. Por ejemplo: cuando un hilo quiere escribir en el registro, primero lo bloquea (lock()), luego hace un seek() para posicionarse al final del registro, escribe la salida, y termina desbloqueando el acceso. Ejemplo:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. sub proceso {  
  2.    lock(\*LOG);                 # bloquear
  3.    print LOG "lo-que-sea...";   # pintar
  4.    unlock(\*LOG);               # desbloquear
  5. }
  6.  
  7. use Fcntl qw(:flock SEEK_END);
  8.  
  9. sub lock {
  10.   my ($fh) = @_;                        # recibimos el descriptor de archivo
  11.   flock($fh, LOCK_EX) or die $!;        # solicitamos el bloqueo, y de forma esclusiva
  12.   seek($fh, 0, SEEK_END) or die $!;     # nos colocamos al final del archivo
  13. }
  14.  
  15. sub unlock {
  16.   my ($fh) = @_;
  17.   flock($fh, LOCK_UN) or die $!;        # desbloqueamos el acceso
  18. }
Coloreado en 0.004 segundos, usando GeSHi 1.0.8.4


Hay soluciones más elaboradas, como la de que ir creando espacio (un relleno de ceros) justo antes de escribir la propia línea, en el registro.

En este hilo de blogs.perl.org se comenta el mismo problema: Suprisingly hard task of writing logs. Y también se comentan diversas soluciones.

Re: Mismo manejador de archivo con distintos hilos

NotaPublicado: 2015-04-11 14:44 @655
por estudiante
Gracias de nuevo, explorer, probaré con tu código. Otra idea podría ser escribir en distintos ficheros y luego juntarlos en uno solo.

Otra pregunta, si hiciera lo siguiente:

open(MANEJADOR1,"<$fichero");
open(MANEJADOR2,"<$fichero");
open(MANEJADOR3,"<$fichero");
open(MANEJADOR4,"<$fichero");
open(MANEJADOR5,"<$fichero");

y que después, cada manejador fuera en un hilo para ir leyendo cada uno por su lado el fichero. ¿Puede dar problemas?

Un saludo.

Re: Mismo manejador de archivo con distintos hilos

NotaPublicado: 2015-04-13 10:03 @460
por explorer
Si el tema es leer de un archivo, ni siquiera te haría falta crear tantos manejadores de archivo. Con uno sería suficiente(*).

El problema está a la hora de escribir.


(*) excepto en Windows, naturalmente.

Re: Mismo manejador de archivo con distintos hilos

NotaPublicado: 2015-04-16 04:32 @231
por estudiante
Gracias, explorer. Como siempre un 10 :)