Usted puede utilizar un protocolo de cooperación elaborado como en la siguiente. Ambos extremos, reader
y writer
, usan un código común en el módulo TakeTurns
que maneja detalles molestos como el bloqueo y dónde vive el archivo de bloqueo. Los clientes solo necesitan especificar lo que quieren hacer cuando tienen acceso exclusivo al archivo.
lector
#! /usr/bin/perl
use warnings;
use strict;
use TakeTurns;
my $runs = 0;
reader "file.txt" =>
sub {
my($fh) = @_;
my @lines = <$fh>;
print map "got: $_", @lines;
++$runs <= 10;
};
escritor
#! /usr/bin/perl
use warnings;
use strict;
use TakeTurns;
my $n = 10;
my @chars = ('a'..'z','A'..'Z','0'..'9','_');
writer "file.txt" =>
sub { my($fh) = @_;
print $fh join("" => map $chars[rand @chars], 1..$n), "\n"
or warn "$0: print: $!";
};
El módulo TakeTurns
es execute-around en el trabajo:
package TakeTurns;
use warnings;
use strict;
use Exporter 'import';
use Fcntl qw/ :DEFAULT :flock /;
our @EXPORT = qw/ reader writer /;
my $LOCKFILE = "/tmp/taketurns.lock";
sub _loop ($&) {
my($path,$action) = @_;
while (1) {
sysopen my $lock, $LOCKFILE, O_RDWR|O_CREAT
or die "sysopen: $!";
flock $lock, LOCK_EX or die "flock: $!";
my $continue = $action->();
close $lock or die "close: $!";
return unless $continue;
sleep 0;
}
}
sub writer {
my($path,$w) = @_;
_loop $path =>
sub {
open my $fh, ">", $path or die "open $path: $!";
my $continue = $w->($fh);
close $fh or die "close $path: $!";
$continue;
};
}
sub reader {
my($path,$r) = @_;
_loop $path =>
sub {
open my $fh, "<", $path or die "open $path: $!";
my $continue = $r->($fh);
close $fh or die "close $path: $!";
$continue;
};
}
1;
de salida de la muestra:
got: 1Upem0iSfY
got: qAALqegWS5
got: 88RayL3XZw
got: NRB7POLdu6
got: IfqC8XeWN6
got: mgeA6sNEpY
got: 2TeiF5sDqy
got: S2ksYEkXsJ
got: zToPYkGPJ5
got: 6VXu6ut1Tq
got: ex0wYvp9Y8
Aunque se haya tomado tantas molestias, todavía hay problemas. El protocolo no es confiable, por lo que reader
no tiene garantía de ver todos los mensajes que envía writer
. Sin writer
activo, reader
se contenta con leer el mismo mensaje una y otra vez.
Puede agregar todo esto, pero un enfoque más sensato sería utilizar las abstracciones que ya proporciona el sistema operativo.
Por ejemplo, Unix named pipes parece ser un bonito partido cercano a lo que quiere, y tenga en cuenta lo sencillo que el código es:
pread
#! /usr/bin/perl
use warnings;
use strict;
my $pipe = "/tmp/mypipe";
system "mknod $pipe p 2>/dev/null";
open my $fh, "<", $pipe or die "$0: open $pipe: $!";
while (<$fh>) {
print "got: $_";
sleep 0;
}
pwrite
#! /usr/bin/perl
use warnings;
use strict;
my $pipe = "/tmp/mypipe";
system "mknod $pipe p 2>/dev/null";
open my $fh, ">", $pipe or die "$0: open $pipe: $!";
my $n = 10;
my @chars = ('a'..'z','A'..'Z','0'..'9','_');
while (1) {
print $fh join("" => map $chars[rand @chars], 1..$n), "\n"
or warn "$0: print: $!";
}
Ambos extremos intentan crear la tubería usando mknod
porque no tienen otro método de sincronización. Al menos uno fallará, pero no nos importa mientras exista la tubería.
Como puede ver, el sistema maneja toda la maquinaria en espera, por lo que hace lo que le importa: leer y escribir mensajes.
Lo que has intentado todavía. ¿Puedes compartir el código que has probado? – Space
Intente leer el archivo Modo NO BLOQUEAR – sganesh
Es posible que desee cerrar el archivo en el programa de escritura antes de abrirlo en el programa de lectura. ¿Y cómo se asegura de que la lectura solo suceda después de una escritura? – AngryWhenHungry