Schrift
[thread]12109[/thread]

Entkoppelung zweier Prozesse mittels FIFO



<< >> 7 Einträge, 1 Seite
fibbs
 2008-07-01 11:55
#111714 #111714
User since
2008-06-30
1 Artikel
BenutzerIn
[Homepage] [default_avatar]
Hallo Community!

Ich verzweifle gerade an einem Problem, zu dem ich zunächst erklären möchte, was ich eigentlich bezwecke:

Ich habe ein System welches Daten sammelt und ein scheduling durchführt. Gewisse Events müssen an ein anderes System übermittelt werden, was eine zeitlang dauert. Das System ist so konzipiert, dass es auf Verzögerungen im Scheduling empfindlich reagiert, so dass hier eine Art Entkoppelung stattfinden muss.

Ich möchte nun also einen Daemon haben, der auf eine named pipe lauscht und Daten, die dort hineintröpfeln verarbeitet. Auf sendender Seite wird pro Event ein Script ausgeführt, welches die Zeile mit den Daten in den Fifo kippt. Der Sender soll immer sofort weiterlaufen ohne sich weiter um die Daten zu kümmern, der Empfänger (Daemon) hat nun ausreichend Zeit, die Queue abzuarbeiten.

Soweit die Theorie, nur leider habe ich das Problem, dass mein Daemon zwar arbeitet, aber nach dem Empfang der ersten Zeile an Daten auf 100% CPU-Last geht und von dort nicht mehr herunterkommt. Den Fifo nach dem Erhalt jeder Zeile zu schließen und erneut zu öffnen würde zwar helfen, ist aber nicht Sinn der Sache, da ich dann keine Entkoppelung mehr hätte.


Ich würde mich sehr freuen, wenn mir von Euch jemand einen Tritt in die richtige Richtung geben könnte.



################# Daemon-Script #####################
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#!/usr/bin/perl -w

use constant FIFOPATH => "/tmp/fifo-demo";
use POSIX qw(mkfifo);
use Fcntl qw(O_RDONLY);
use Sys::Syslog qw( :DEFAULT setlogsock);

# catch signals to die gracefully
$SIG{'TERM'} = 'handler';
$SIG{'INT'} = 'handler';

# syslog
sub do_syslog {
        my $msg = shift;
        setlogsock('unix');
        openlog($0,'','user');
        syslog('info',"$msg");
        closelog;
}


sub handler {
    my $signal = shift;    # signal-nummer besorgen
    $SIG{'TERM'} = 'handler';   # reinstall sig-handler
    $SIG{'INT'} = 'handler';   # reinstall sig-handler

    &do_syslog ("Signal: SIG$signal caught!");
    unlink(FIFOPATH);
    exit 0;
}

sub do_notification {
        my $string = shift;
        &do_syslog($string);
        # instead of this 'sleep' here should be some intelligent code to
        # do magic stuff with the data we got from uncle fifo.
        sleep 5;
}

########################### MAIN ################################


unlink(FIFOPATH);
mkfifo(FIFOPATH, 0666) or die "can't create FIFO: $!\n";

sysopen(FIFOFD, FIFOPATH, O_RDONLY) or die "can't read: $!\n";

#my $fifostring = "";
#while (1) {
#    if (sysread(FIFOFD, $fromfifo, 1) == 1) {
#       if ($fromfifo eq "\n") {
#               &do_notification($fifostring);
#               $fifostring = "";
#       } else {
#               $fifostring .= $fromfifo;
#       }
#    }
#}

# easyer reading line-by-line
while (1) {
        while (<FIFOFD>) {
                &do_notification($_);
        }
}



################# Client-Script ####################
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/bin/perl -w
# fifo-client.pl -- Sendet Auftraege in eine FIFO hinein.

use strict;
use Data::Dumper;

my $fifo = "/tmp/fifo-demo";
my $string = shift;


#sysopen(FIFOFD, FIFOPATH, O_WRONLY) or die "can't write: $!\n";
open (FIFOFD, ">$fifo") or die "could not open fifo: $!\n";
print FIFOFD "$string\n";
close (FIFOFD);
RalphFFM
 2008-07-01 15:09
#111719 #111719
User since
2006-11-16
258 Artikel
BenutzerIn
[Homepage] [default_avatar]
Ich hab jetzt nur wenig Erfahrung mit Named Pipes, da es aber sonst so leer hier aussieht antworte ich trotzdem mal.

Um eine Entkopplung zu erreichen würd ich wahrscheinlich eine Datenbank anstelle der Pipe nehmen. Und diese entweder regelmäßig abfragen, oder schauen ob sich sowas vielleicht auch mit einem Trigger machen läßt.(?, d.h. Frage / Das wissen vielleicht die Experten hier.)
esskar
 2008-07-01 15:45
#111721 #111721
User since
2003-08-04
7321 Artikel
ModeratorIn

user image
cpu auf 100 liegt an

Code: (dl )
while(1) { ... }


schau dir mal das 4 parametriege select an
oder auch CPAN:IO::Select
FIFO
 2008-07-01 20:59
#111726 #111726
User since
2005-06-01
469 Artikel
BenutzerIn

user image
... endlich mal ein Thread über mich ;-)
Everyone knows that debugging is twice as hard as writing a program in the first place. So if you're as clever as you can be when you write it, how will you ever debug it? -- Brian Kernighan: "The Elements of Programming Style"
betterworld
 2008-07-02 20:48
#111745 #111745
User since
2003-08-21
2614 Artikel
ModeratorIn

user image
Wie esskar schon sagt, es liegt an dem while(1). Die innere while-Schleife wird beendet, sobald ein EOF vom FIFO kommt. Nach einem EOF kann man nicht mehr lesen, daher wird darauf die innere Schleifenbedingung immer sofort EOF zurueckgeben.

Wenn Du ein EOF kriegst und wieder lesen moechtest, solltest Du wohl den FIFO neu oeffnen.

Das EOF kommt uebrigens, sobald der Client das Socket schliesst:
Code: (dl )
close (FIFOFD);


Übrigens kann man auch nach print und <> Fehler aus $! auslesen. Das ist zur Fehlersuche ganz hilfreich, auch wenn es hier wohl nicht hilft, da EOF kein wirklicher Fehler ist.

Und den Signal-Handler verstehe ich auch nicht so ganz. Warum setzt Du darin die Signal-Handler noch einmal neu? Das ist erstens nicht notwendig, da sie so lange gesetzt bleiben, bis sie explizit deaktiviert werden. Und zweitens bringt es ja eh nichts mehr, so kurz vor dem exit...

Ich mag nicht mit FIFOs programmieren. Da blockt und EOFt es an allen Enden, und nie macht es das, was man will. Warum nicht einfach ein Socket nehmen? @FIFO: Nichts gegen Dich ;)
esskar
 2008-07-03 10:10
#111756 #111756
User since
2003-08-04
7321 Artikel
ModeratorIn

user image
was du auch bedenken solltest; der "daemon" liesst erst wieder, wenn er mit dem bearbeiten eines "auftrages" fertig ist; heisst, der client wartet wieder, weil er die pipe nicht zumachen darf, bis der daemon alles abgearbeitet hat.

du musst also entweder mit fork (empfehle ich nur unter linux) oder mit threads arbeiten. oder auch mal POE anschauen.
Gast Gast
 2008-07-05 09:58
#111875 #111875
Seit zwei Tagen keine Anmerkung mehr - ich schreib trotzdem.

Das ist eine perfekte Anwendung für eine Dateischnittstelle.

Der Datenlieferant öffnet eine Zwischendatei (z.B zw1.txt) zum Anhängen von Daten, schreibt was zu schreiben ist und schließt diese Datei wieder (schließen ist wichtig).

Der Empfänger prüft ob zw1.txt existiert - gibt der Datei einen anderen Namen (z.B. zw2.txt) - öffnet zw2.txt zum Lesen - liest die Daten soweit vorhanden - tut damit was er tun muß - und schläft für eine angemessene Zeit, x Minuten/Stunden - Ende der Schleife.

Die Entkopplung ist perfekt und keiner der beteiligten Prozesse ist in seiner Arbeit behindert.
<< >> 7 Einträge, 1 Seite



View all threads created 2008-07-01 11:55.