![]() ![]() ![]() |
|
![]() |
Funktionen f�r Betriebssystemaufrufe |
![]() |
|
![]() |
Unter "Betriebssystemaufrufe" sind hier Funktionen versammelt, die sich vor allem eng am Konzept der Unix-Betriebssysteme orientieren. Nur wenige der Funktionen sind auf andere Systeme portierbar.
Unix-Systeme verwalten laufende "Programme" in so genannten Prozessen. Jeder Prozess hat eine Prozessnummer (PID). Au�erdem gibt es Prozessgruppen. Jeder Prozess geh�rt zu einer Prozessgruppe. Prozessgruppen haben ebenfalls Nummern. Auch Ihr Perl-Script stellt, wenn es ausgef�hrt wird, einen solchen Prozess dar, der einer Prozessgruppe angeh�rt. Bei vielen der hier beschriebenen Funktionen k�nnen Sie den aktuellen Prozess, also den Ihres Perl-Scripts, durch die "virtuelle" Prozessnummer 0
ansprechen. �ber vordefinierte Variablen k�nnen Sie jedoch auch die tats�chliche Prozessnummer herausfinden und benutzen. Das folgende Beispielscript zeigt die entsprechenden Variablen im Einsatz:
#!/usr/bin/perl -w use strict; use CGI::Carp qw(fatalsToBrowser); print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Testausgabe</title>\n"; print "</head><body>\n"; print "Prozessnummer (PID): <strong>$$</strong><br>\n"; print "Reale Benutzergruppe (GID) des Prozesses: <strong>$(</strong><br>\n"; print "Effektive Benutzergruppe (GID) des Prozesses: <strong>$)</strong>\n"; print "</body></html>\n";
Mit $$
sprechen Sie die Nummer des aktuellen Prozesses an. Der Prozess l�uft unter einer bestimmten User-ID, die wiederum einer oder mehreren Gruppen angeh�rt. Wenn das Script beispielsweise mit setgid
gestartet wurde, enth�lt die reale Gruppen-ID die Gruppe(n), von der aus gestartet wurde, die effektive Gruppen-ID enth�lt die Gruppe(n), in die gewechselt wurde (die aktuelle also). Das Beispiel-CGI-Script gibt die entsprechenden Daten aus.
Weitere wichtige Konzepte der Unix-Betriebssysteme, auf die Sie mit Perl-Funktionen Zugriff haben, sind Alarme, Kindprozesse und die so genannten Pipes. N�here Informationen dazu finden Sie in der Unix-Fachliteratur.
Hierbei handelt es sich eigentlich nicht um eine Perl-Funktion, sondern um eine besondere Form des Notierens von Zeichenketten. Das
qx
steht f�r quoted executable. Die darin eingeschlossene Zeichenkette wird von Perl einfach in einen Kommandozeilenaufruf umgesetzt. Die Standardausgabe des aufgerufenen Kommandos, Fremdprogramms oder Scripts wird aufgefangen und kann in einer Variablen gespeichert werden. Eine andere M�glichkeit, diese Art von ausf�hrbaren Zeichenketten zu notieren, sind die so genannten Backticks. Dabei arbeiten Sie anstelle von qx(irgendein Kommando)
mit dem r�ckw�rts gerichteten Accent-Zeichen `
und notieren `irgendein Kommando`
.
Die Funktionalit�t der ausf�hrbaren Zeichenketten ist f�r CGI-Scripts extrem n�tzlich, um die Ausgaben anderer Prozesse auffangen und an den Browser senden lassen zu k�nnen. So lassen sich beispielsweise XML-Daten mit
XSLT und einem XSLT-Prozessor in HTML �bersetzen. Wenn dieser Prozessor seine Ergebnisse auf den
Standardausgabekanal
STDOUT
schreibt, kann das CGI-Script die Ausgabe auffangen und an den Webserver zur Weiterleitung �bergeben. Das folgende Beispiel zeigt dies.
#!/usr/bin/perl -w use strict; use CGI::Carp qw(fatalsToBrowser); print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; my $Output = qx(/usr/bin/saxon /daten/xml/kunden.xml /daten/xml/kunden.xsl); print "$Output";
Mehr als dieses winzige Script ist nicht n�tig, um XML-Daten in HTML-Form an den Webserver zur �bergabe an einen aufrufenden Browser zu senden - sofern ein XSLT-Prozessor die �bersetzungsarbeit leistet. Das Beispiel f�hrt folgendes Kommando aus:
/usr/bin/saxon /daten/xml/kunden.xml /daten/xml/kunden.xsl
Dabei ist saxon
der Name eines XSLT-Prozessors, also eines ausf�hrbaren Programms. Dieses Programm erwartet im Normalfall zwei Aufrufparameter: erstens die Angabe einer XML-Datei, und zweitens die Angabe einer dazu passenden XSL-Datei mit XSLT-Anweisungen. Saxon �bersetzt die XML-Auszeichnungen aufgrund der XSLT-Angaben in HTML-Konstrukte und gibt das Ergebnis, eine vollst�ndige HTML-Datei, auf die Standardausgabe aus. Das Script f�ngt diese Standardausgabe auf, indem es sie in der Variablen $Output
speichert. In dieser Variablen steht also nach dem Saxon-Aufruf der gesamte Inhalt der HTML-Daten. Ein einfacher print-Befehl gen�gt anschlie�end, um die gesamten HTML-Daten auszugeben.
Die Art der Klammerung bei Verwendung von qx
ist egal. Sie k�nnen auch eckige oder geschweifte Klammern oder Schr�gstriche verwenden - von letzteren ist allerdings abzuraten, weil viele Kommandos Pfadangaben ben�tigen und Sie in diesem Fall alle Schr�gstriche bei Pfadangaben maskieren m�ssten.
Bei Pfadangaben sollten Sie auch bei qx(...)
stets die einfachen Schr�gstriche verwenden - auch wenn das Perl-Script unter Windows ausgef�hrt wird.
Mit Backticks w�rde der Aufruf des obigen Beispiels lauten:
my $Output = `/usr/bin/saxon /daten/xml/kunden.xml /daten/xml/kunden.xsl`;
Um die Backticks zu erzeugen, halten Sie auf den meisten Systemen die Shift-Taste gedr�ckt, tippen einmal auf die Taste mit den franz�sischen Accent-Zeichen und anschlie�end die Leertaste.
Im Link-Verzeichnis des Online-Angebots von SELFHTML aktuell finden Sie Links zu XML-Software. Dort finden Sie ebenso Verweise zu Produkten wie Saxon.
Die hier beschriebene M�glichkeit ist auf alle Kommandos anwendbar, die etwas auf die Standardausgabe STDOUT
schreiben, also z.B. auch auf Betriebssystem-Kommandos wie ls
(bzw. dir
), oder auch auf andere Perl-Scripts. Einige solcher Programme oder Kommandos schreiben ihren Output bei fehlerhaften Aufrufen jedoch nicht auf STDOUT
, sondern auf STDERR
. Solche Ausgaben werden von den hier beschriebenen ausf�hrbaren Zeichenketten nicht aufgefangen.
Unix-spezifischer Befehl. Bewirkt, dass der Prozess einen SIGALARM nach einer bestimmten Anzahl Sekunden erh�lt, wenn z.B. ein kritischer Befehl nicht funktioniert.
Erwartet als Parameter:
1. die Anzahl Sekunden, bis der Alarm aktiv wird.
Gibt die Anzahl Sekunden zur�ck, die verstrichen sind.
#!/usr/bin/perl -w use CGI::Carp qw(fatalsToBrowser); print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Testausgabe</title>\n"; print "</head><body><pre>\n"; eval { local $SIG{ALRM} = sub { die "Alarm" }; alarm(2); system("/usr/bin/perl -c /usr/web/myhome/cgi-bin/freelink.pl"); alarm(0); }; if ($@ and $@ !~ /Alarm/) { print "Problem! 2 Sekunden vergangen!\n"; } else { print "Alles klar!\n"; } print "</pre></body></html>\n";
Das Beispiel zeigt, wie Sie einen "kritischen Systemaufruf" mit Hilfe eines Timeout-Alarms behandeln k�nnen. Dazu wird in dem Script zun�chst ein f�r solche Behandlung typischer eval-Block notiert. Darin wird mit der typischen Anweisung:
local $SIG{ALRM} = sub { die "Alarm" };
eine Behandlungsroutine f�r SIGALARM definiert. Anschlie�end wird mit alarm(2)
ein Timeout von 2 Sekunden definiert, bevor der Alarm aktiv wird. Mit alarm(0)
wird der Alarm wieder zur�ckgesetzt.
Danach wird versucht, mit system den Perl-Interpreter aufzurufen, und zwar so, dass er ein bestimmtes Script auf die G�ltigkeit seiner Syntax �berpr�ft. Sollte dieser Vorgang mehr als 2 Sekunden dauern, wird der Alarm aktiv.
Mit der Abfrage if ($@ and $@ !~ /Alarm/)
wird �berpr�ft, ob der Alarm aktiv wurde. Wenn ja, wird eine entsprechende Meldung ausgegeben. Im else
-Zweig kann der Code stehen, der ausgef�hrt wird, wenn alles in Ordnung war. Im Beispiel wird einfach ebenfalls eine entsprechende Meldung ausgegeben.
Aufrufe mit system oder
qx(...) in Verbindung mit
alarm
k�nnen zu sogenannten Zombies f�hren. M�glicherweise m�ssen Sie sie f�r solche Zwecke mit Hilfe von fork und
exec selbst implementieren.
Startet einen anderen Prozess und beendet das aktuelle Script. Der aktuelle Prozess wird dabei durch den neuen Prozess vollst�ndig ersetzt. Wenn Sie das aktuelle Script nicht beenden wollen, benutzen Sie system,
qx(...) oder
open mit dem Pipe-Zeichen
|
.
Erwartet als Parameter:
1. Kommandozeilenaufruf des gew�nschten Programms,
2. bis n. (optional) Liste mit Aufrufparametern.
#!/usr/bin/perl -w exec("/usr/bin/perl","mystats.pl") if -e "mystats.pl";
Das Beispiel fragt mit Hilfe des Dateitestoperators
-e
ab, ob eine Datei namens mystats.pl
im aktuellen Verzeichnis existiert. Wenn ja, wird der Perl-Interpreter (in einem eigenen neuen Prozess) gestartet und f�hrt mystats.pl
aus.
Unix-spezifischer Befehl. Erzeugt eine Kopie des aktuellen Prozesses, die dem aktuellen erzeugenden Prozess untergeordnet ist. Ein Perl-Script kann sich auf diese Weise gabeln (engl. fork) und Daten in zwei getrennten Prozessen verarbeiten. Auf ge�ffnete Dateien k�nnen dabei beide Prozesse zugreifen. Alles �brige, wie Variablen usw., wird vom Elternprozess in den Kindprozess kopiert. Die Variable, die den R�ckgabewert von fork
speichert, hat jedoch im Elternprozess einen Wert, n�mlich die Prozessnummer des Kindprozesses, w�hrend sie im Kindprozess den Wert 0
hat.
Obwohl fork
eigentlich aus der Unix-Welt stammt, l�sst sich diese Funktion mittlerweile auch unter ActivePerl f�r Windows nutzen.
Erwartet keine Parameter.
Gibt die vom Betriebssystem zugewiesene Prozessnummer des Kindprozesses zur�ck.
#!/usr/bin/perl -w use strict; use CGI::Carp qw(fatalsToBrowser); $| = 1; print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Testausgabe</title>\n"; print "</head><body>\n"; my $Eltern_pid = $$; my $Kind_pid = fork(); if($Kind_pid) { print "<p>Hier ist der Elternprozess. Der Kindprozess hat die PID <strong>$Kind_pid</strong></p>\n"; wait; } else { my $Eltern_pid = getppid(); print "<p>Hier ist der Kindprozess. Der Elternprozess hat die PID <strong>$Eltern_pid</strong></p>\n"; exit(0); } print "</body></html>\n";
Das Beispiel erzeugt mit fork
einen Kindprozess. Der R�ckgabewert der Funktion, die Prozessnummer des Kindprozesses, wird in dem Skalar $Kind_pid
gespeichert. Im Beispiel ist daraufhin eine if
-Abfrage notiert. Mit if($Kind_pid)
wird abgefragt, ob der Skalar $Kind_pid
einen Wert ungleich 0
hat. Ist das der Fall, werden Anweisungen ausgef�hrt, die zum Elternprozess geh�ren. Im Beispiel wird eine Meldung ausgegeben, dass sich das Script im Elternprozess befindet. Au�erdem wird die Prozessnummer des Kindprozesses ausgegeben. Danach wird mit der Anweisung wait gewartet, bis der Kindprozess beendet ist. Im
else
-Zweig, in den das Script gelangt, wenn Kind_pid
den Wert 0
hat, wird dagegen ausgegeben, dass der Kindprozess aktiv ist. Au�erdem wird die Prozessnummer des Elternprozesses ausgegeben. Danach wird der Kindprozess mit der Anweisung exit(0);
beendet. Der Elternprozess, der darauf nur gewartet hat, gibt dann noch die letzte Zeile HTML-Code aus.
Das besondere Verhalten des Scripts, das in zwei Prozessen l�uft, zeigt sich im Beispiel darin, dass sowohl der if
-Zweig als auch der else
-Zweig ausgef�hrt werden. Das erkl�rt sich daraus, dass die if
-Bedingung f�r den Elternprozess wahr ist, die else
-Alternative dagegen f�r den Kindprozess.
Unix-spezifischer Befehl.
Erwartet als Parameter:
1. eine Prozessnummer, zu der die zugeh�rige Prozessgruppe ermittelt werden soll. Um die Prozessgruppe des aktuellen Prozesses zu ermitteln, m�ssen Sie 0
�bergeben.
Gibt die Gruppennummer zur�ck.
#!/usr/bin/perl -w use strict; use CGI::Carp qw(fatalsToBrowser); print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Testausgabe</title>\n"; print "</head><body>\n"; my $Gruppennummer = getpgrp(0); print "Die Prozessgruppe des aktuellen Prozesses ist <strong>$Gruppennummer</strong>\n"; print "</body></html>\n";
Das Beispiel ermittelt die Gruppennummer des aktuellen Prozesses mit getpgrp
und gibt HTML-Code mit der ermittelten Nummer aus.
Unix-spezifischer Befehl.
Erwartet keine Parameter.
Gibt die Prozessnummer (PID) des Elternprozesses des aktuellen Scripts zur�ck.
#!/usr/bin/perl -w use strict; use CGI::Carp qw(fatalsToBrowser); print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Testausgabe</title>\n"; print "</head><body>\n"; my $Eltern_pid = getppid(); print "Die PID des Elternprozesses lautet <strong>$Eltern_pid</strong>\n"; print "</body></html>\n";
Das Beispiel ermittelt die PID des Elternprozesses mit getppid
und gibt HTML-Code mit der ermittelten Nummer aus.
Unix-spezifischer Befehl. Ermittelt die aktuelle Priorit�t eines Prozesses, einer Prozessgruppe oder eines Benutzers. Prozesse mit h�herer Priorit�t erhalten unter den aktuell laufenden Prozessen mehr Systemressourcen zur Ausf�hrung.
Erwartet als Parameter:
1. eine Angabe dazu, ob Sie die Priorit�t f�r einen bestimmten Prozess, eine Prozessgruppe oder einen Benutzer ermitteln wollen. Dazu �bergeben Sie am besten eine der Konstanten, die in resource.ph
definiert sind (siehe unten).
2. die Nummer des Prozesses, der Prozessgruppe oder des Benutzers.
Gibt die Priorit�t des Prozesses, der Prozessgruppe oder des Benutzers als Zahl zur�ck. Der m�gliche Wertebereich ist abh�ngig vom System.
#!/usr/bin/perl -w use strict; use CGI::Carp qw(fatalsToBrowser); print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Testausgabe</title>\n"; print "</head><body>\n"; require "resource.ph"; my $Prio = getpriority(&PRIO_PROCESS,0); print "Prioritaet des aktuellen Prozesses: $Prio\n"; print "</body></html>\n";
Das Beispiel ermittelt mit getpriority
die Priorit�t des aktuellen Prozesses und gibt diese aus. Dazu wird mit require "resource.ph"
die Kopfdatei eingebunden, die die Definition der folgenden Konstanten enth�lt:
Konstante: | Bedeutung: |
---|---|
PRIO_PROCESS |
Die Priorit�t eines bestimmten Prozesses ermitteln, dessen Prozessnummer (oder 0 f�r den aktuellen Prozess) im zweiten Parameter von getpriority angegeben wird. |
PRIO_PGRP |
Die Priorit�t einer Prozessgruppe ermitteln, deren Nummer (oder 0 f�r die aktuelle Prozessgruppe) im zweiten Parameter angegeben wird. |
PRIO_USER |
Die Priorit�t eines Benutzers ermitteln, dessen Benutzernummer (UID - oder 0 f�r den aktuelle Benutzer) im zweiten Parameter angegeben wird. |
Durch Voranstellen eines &
-Zeichens k�nnen Sie eine der Konstanten wie im Beispiel gezeigt als ersten Parameter �bergeben.
Diese Funktion f�hrt zu einem schweren Fehler, wenn das System keine Prozess- bzw. Benutzerverwaltung im Sinne von Unix kennt.
Unix-spezifischer Befehl. Damit k�nnen Sie aus einem Perl-Script heraus Signale an andere laufende Prozesse auf dem Rechner senden und diese dadurch beeinflussen. Interessant ist dies vor allem, wenn Sie in Ihrem Perl-Script eigene Kindprozesse erzeugen (siehe fork). Eltern- und Kindprozess k�nnen dann durch Signale kommunizieren.
Erwartet als Parameter:
1. Nummer oder Name einer Konstante (siehe Tabelle weiter unten) des gew�nschten Signals (oder Sie �bergeben 0
, um herauszufinden, ob der Prozess mit der nachfolgend �bergebenen Prozessnummer noch "am Leben" ist),
2. bis n. einer oder mehrere Prozesse, an die das Signal gesendet werden soll.
#!/usr/bin/perl -w use strict; use CGI::Carp qw(fatalsToBrowser); $| = 1; print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Testausgabe</title>\n"; print "</head><body>\n"; my $Kind_pid = fork(); if(kill(0,$Kind_pid)) { print "<p>Hier meldet sich ein Prozess</p>\n"; kill("KILL",$Kind_pid); } print "</body></html>\n";
Das Beispiel erzeugt mit fork einen Kindprozess. Mit
if(kill(0,$Kind_pid))
wird abgefragt, ob dieser Prozess am Leben ist. Wenn ja, wird ausgegeben, dass sich ein Prozess meldet. Da im Beispiel f�r den Kindprozess kein eigener Perl-Code notiert ist und Kindprozesse einfach erst mal alles vom Elternprozess kopieren, w�rden beide Prozesse sich melden und Hier meldet sich ein Prozess
ausgeben. Doch im Beispiel wird das verhindert, indem der Elternprozess den Kindprozess mit kill("KILL",$Kind_pid)
t�tet, bevor dieser die Anweisung mit der Ausgabe der Meldung ausf�hren kann. Die Meldung wird also insgesamt nur einmal ausgegeben.
Die folgende Tabelle enth�lt typische Signale mit Namen, wie Sie sie als ersten Parameter an kill
�bergeben k�nnen. Eine Garantie, dass alle hier aufgelisteten Signale auf jedem Rechner in Perl funktionieren, besteht nicht. Auch die entsprechenden Nummern wurden hier weggelassen, da sie von System zu System schwanken k�nnen. Ma�geblich ist letztendlich immer, was auf dem jeweiligen Rechner in der Datei /usr/include/signal.h
definiert ist.
Name: | Bedeutung: |
---|---|
"HUP" |
Ereignis: Verbindung beendet |
"INT" |
Ereignis: allgemeine Unterbrechung |
"QUIT" |
Ereignis: Endekennzeichen |
"ILL" |
Anweisung ist illegal |
"TRAP" |
Anweisung ist eine "Falle" |
"ABRT" |
Abbruch |
"FPE" |
Fehler bei Flie�kommaberechnung |
"KILL" |
Prozess "abschie�en" (Unix: kill -9) |
"BUS" |
Bus-�bertragungsfehler |
"SEGV" |
Segment-Schutzverletzung im Speicher |
"PIPE" |
Fehler bei Pipe-Kommunikation |
"ALARM" |
Allgemeiner Alarm |
"TERM" |
Beendigung |
"USR1" |
Benutzerdefiniert 1 |
"USR2" |
Benutzerdefiniert 2 |
"CHLD" |
Signal vom Kindprozess |
"PWR" |
Stromausfall |
"WINCH" |
Fenstergr��e wurde von einem Hintergrundprozess ge�ndert |
"URG" |
Dringende Bedingung |
"IO" |
Asynchrone Ein-/Ausgabe |
"STOP" |
Prozess anhalten |
"TSTP" |
Prozess vom Terminal aus anhalten |
"CONT" |
Angehaltenen Prozess fortf�hren |
"TTIN" |
Prozess anhalten durch Lesen vom kontrollierenden Terminal |
"TTOU" |
Prozess anhalten durch Schreiben auf kontrollierendes Terminal |
"VTALARM" |
Virtueller Zeittaktgeber abgelaufen |
"PROF" |
Profil-Zeittaktgeber abgelaufen |
"XCPU" |
CPU-Belastungsgrenze erreicht |
"XSFZ" |
Dateigr��engrenze erreicht |
Mit dem folgenden Script k�nnen Sie abfragen, welche Signale unter welchen Signalnummern auf Ihrem Server-Rechner konfiguriert sind:
#!/usr/bin/perl use Config; defined $Config{sig_name} || die "Kein Konfigmodul?"; foreach $name (split(' ', $Config{sig_name})) { $i++; printf "%3d) %s \t", $i, $name; if (($i % 5) == 0) { print "\n"; } } print "\n";
Unix-spezifischer Befehl. Erm�glicht zwei Prozessen, miteinander zu kommunizieren. Eine "Pipe" (Pfeife, R�hre) ist dabei der Kommunikationskanal f�r die beiden Prozesse. Es gibt einen Kanal zum Schreiben von Daten und einen zum Lesen von Daten. F�r beide Kan�le gibt es jeweils ein "Handle". Diese Lese- und Schreib-Handles sind ganz �hnlich den Datei-Handles. Typischerweise wird eine Pipe er�ffnet, bevor mit
fork ein Kindprozess erzeugt wird. Eltern- und Kindprozess k�nnen dann �ber die ge�ffnete Pipe Daten austauschen.
Erwartet als Parameter:
1. den Namen eines Lese-Handles (frei vergebbar),
2. den Namen eines Schreib-Handles (frei vergebbar)
#!/usr/bin/perl -w use strict; use CGI::Carp qw(fatalsToBrowser); $| = 1; print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Testausgabe</title>\n"; print "</head><body><pre>\n"; pipe(LESE_HANDLE, SCHREIB_HANDLE); my $Kind_pid = fork(); if ($Kind_pid) { close(LESE_HANDLE); my $old_handle = select(SCHREIB_HANDLE); $| = 1; for (my $i=1;$i<=5;$i++) { sleep(1); print SCHREIB_HANDLE "$i (gesendet vom Elternprozess)\n"; } close(SCHREIB_HANDLE); wait; select($old_handle); } else { close(SCHREIB_HANDLE); my $Speicher; while(defined($Speicher = <LESE_HANDLE>)) { print "Empfangen: $Speicher \n"; } exit(0); } print "</pre></body></html>\n";
Das Beispiel erzeugt mit pipe
eine Pipe. �ber die beiden �bergebenen Handle-Namen LESE_HANDLE
und SCHREIB_HANDLE
ist anschlie�end der Nachrichtenaustausch zwischen zwei Prozessen m�glich. Mit Hilfe von fork erzeugt das Script einen Kindprozess. Der Elternprozess l�uft im
if
-Zweig des nachfolgenden Codes, der Kindprozess im else
-Zweig. Beim Erzeugen des Kindprozesses wird alles kopiert - au�er den beiden Handles aus der Pipe. Diese werden nicht kopiert, bleiben allerdings f�r beide Prozesse verf�gbar. Deshalb muss jeder Prozess erst mal das nicht ben�tigte Handle mit close schlie�en. Um die Pufferung der Daten abschalten zu k�nnen, muss im
if
-Zweig au�erdem mit select das Schreib-Handle ausgew�hlt werden. Alle Anweisungen sowohl des
if
- als auch des else
-Zweiges werden insgesamt f�nf mal ausgef�hrt. Denn in einer for-Schleife, die von 1 bis 5 z�hlt, schreibt der Elternprozess, nachdem er zu Testzwecken eine Sekunde lang anh�lt (siehe
sleep), den aktuellen Z�hlerstand in das Schreib-Handle. Der Kindprozess im
else
-Zweig kann diese Daten lesen, indem er eine while-Schleife verwendet und darin das Lese-Handle ausliest. Zur Kontrolle gibt der Kindprozess aus, was er eingelesen hat.
![]() ![]() |
Unix-spezifischer Befehl. Ordnet einen Prozess einer Prozessgruppe zu.
Erwartet als Parameter:
1. die Prozessnummer (PID) des gew�nschten Prozesses (0
f�r aktuellen Prozess �bergeben),
2. die Nummer der Prozessgruppe, der dieser Prozess zugeordnet werden soll (0
f�r aktuelle Prozessgruppe �bergeben).
#!/usr/bin/perl -w use strict; use CGI::Carp qw(fatalsToBrowser); print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Testausgabe</title>\n"; print "</head><body>\n"; my $gruppe_alt = getpgrp(0); print "Prozessgruppe alt: <strong>$gruppe_alt</strong><br>\n"; setpgrp(0,0); my $gruppe_neu = getpgrp(0); print "Prozessgruppe neu: <strong>$gruppe_neu</strong>\n"; print "</body></html>\n";
Das Beispiel ordnet den aktuellen Prozess der aktuellen Prozessgruppe zu und erzeugt so seine eigene Prozessgruppe. Zum Vergleich wird die aktuelle Prozessgruppe vorher und hinterher ausgelesen und jeweils ausgegeben.
Unix-spezifischer Befehl. Setzt die aktuelle Priorit�t eines Prozesses, einer Prozessgruppe oder eines Benutzers. Prozesse mit h�herer Priorit�t erhalten unter den aktuell laufenden Prozessen mehr Systemressourcen zur Ausf�hrung.
Da diese Funktion "systemkritisch" ist, steht sie auf den meisten Unix-Systemen nur Benutzern mit root-Kennung zur Verf�gung.
Parameter wie bei getpriority
#!/usr/bin/perl -w use strict; use CGI::Carp qw(fatalsToBrowser); print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Testausgabe</title>\n"; print "</head><body>\n"; require "resource.ph"; my $Prio = getpriority(&PRIO_PROCESS,0); $Prio += 1; setpriority (&PRIO_PROCESS, 0, $Prio); print "Neue Prioritaet des aktuellen Prozesses: $Prio\n"; print "</body></html>\n";
Das Beispiel liest mit getpriority
die Priorit�t des aktuellen Prozesses ein, erh�ht sie anschlie�end um 1 und setzt dann mit setpriority
den neuen Wert. Zur Kontrolle gibt das Script den aktuellen Wert der Priorit�t aus.
Diese Funktion f�hrt zu einem schweren Fehler, wenn das System keine Prozess- bzw. Benutzerverwaltung im Sinne von Unix kennt.
H�lt die Ausf�hrung des Scripts f�r eine bestimmte Anzahl Sekunden an und f�hrt dann fort.
Erwartet als Parameter:
1. die Anzahl Sekunden, die angehalten werden soll. Wenn nichts �bergeben wird, wird "f�r ewig" angehalten.
#!/usr/bin/perl -w use strict; sleep(10); exec("/usr/bin/perl","aufwachen.pl");
Das Beispiel wartet nach Aufruf von sleep(10)
10 Sekunden und f�hrt dann mit exec ein anderes Script aus.
Ruft ein anderes Programm auf und ermittelt dessen R�ckgabewert. Wenn Sie daran interessiert sind, welche Ausgaben das andere Programm erzeugt, sollten Sie die Funktion open mit dem Zeichen
|
oder qx(...) bzw.
`...`
(Backticks) benutzen.
Erwartet als Parameter:
1. eine Zeichenkette oder eine Liste. Werden mehrere Parameter, also eine Liste, �bergeben, wird der erste Parameter als das auszuf�hrende Programm bzw. Kommando interpretiert, und die �brigen Parameter als �bergabeparameter f�r das Programm bzw. Kommando.
Gibt den R�ckgabewert des ausgef�hrten Programms oder Kommandos zur�ck.
#!/usr/bin/perl -w use strict; use CGI::Carp qw(fatalsToBrowser); (my $Datei_1, my $Datei_2) = split(/&/,$ENV{'QUERY_STRING'}); my $Pfaddatei_1 = "/usr/web/daten/alt/".$Datei_1; my $Pfaddatei_2 = "/usr/web/daten/neu/".$Datei_2; my $Vergleich = system("cmp $Pfaddatei_1 $Pfaddatei_2 >/dev/null"); print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Test-Ausgabe</title></head><body>\n"; if($Vergleich == 0) { print "<tt>$Pfaddatei_1</tt><br>und<br><tt>$Pfaddatei_2</tt><br><strong>sind gleich!</strong>!\n"; } else { print "<tt>$Pfaddatei_1</tt><br>und<br><tt>$Pfaddatei_2</tt><br><strong>sind verschieden!</strong>!\n"; } print "</body></html>\n";
Das Beispielscript ermittelt den Inhalt der CGI-Umgebungsvariablen
QUERY_STRING
, erwartet in dem �bergebenen Parameter ein kaufm�nnisches Und (&
) und trennt den Teil davor und den dahinter in die Skalare $Datei_1
und $Datei_2
. Die beiden Daten werden als Dateien interpretiert. Ein Beispielaufruf des Scripts k�nnte lauten:
/cgi-bin/script.pl?news.htm&news.htm
Das Script h�ngt die beiden gleichnamigen Dateien an unterschiedliche Pfadnamen auf dem Server und erzeugt damit zwei unterschiedliche Dateipfadangaben in den Skalaren $Pfaddatei_1
und $Pfaddatei_2
. Mit system
wird nun der Shell-Befehl cmp
(unter Unix) gestartet, der zwei Dateien daraufhin �berpr�ft, ob sie gleich sind. Dem Befehl werden die beiden Skalare mit den Pfadangaben �bergeben. Eine Ausgabe soll der Befehl in diesem Fall nicht erzeugen. Deshalb wird seine Ausgabe nach /dev/null
umgeleitet. Der R�ckgabewert des system
-Aufrufs und damit des cmp
-Befehls wird jedoch gespeichert, n�mlich im Skalar $Vergleich
. Wenn der Wert 0
ist, sind die verglichenen Dateien gleich, andernfalls unterschiedlich. Diese Information wird zur�ckgegeben.
Ermittelt die Laufzeit eines Prozesses (und, wenn vorhanden, seiner Kindprozesse) von der Erzeugung bis zum Ausf�hren dieses times
-Aufrufs. Ermittelt werden f�r jeden Prozess jeweils zwei Werte: "user time" und "system time". W�hrend "user time" bezeichnet, wie lange der Prozess selber gelaufen ist, gibt "system time" die Zeit an, wie lange der Prozess das Betriebssystem besch�ftigt hat. Die Summe beider Zeiten ist die gesamte verbrauchte CPU-Zeit.
Die gemessenen Zeiten basieren auf so genannten Uhrenticks. Die Anzahl der Uhrenticks pro Sekunde ist auf Unix-Systemen einstellbar (TICKSPERSEC
in der Datei conf.h
).
Erwartet keine Parameter.
Gibt eine Liste mit Laufzeiten in Sekunden (Flie�kommazahlen mit Angaben zu Sekundenbruchteilen) zur�ck. Schema:
($user_time,$system_time[,$user_time_Kind,$system_time_Kind,...])
#!/usr/bin/perl -w use strict; use CGI::Carp qw(fatalsToBrowser); my $x; for(my $i = 0; $i < 1000; $i++) { for(my $k = 0; $k < 100; $k++) { $x = $i * $k / time(); } } my ($Systemzeit, $Userzeit) = times(); my $CPU_Zeit = $Systemzeit + $Userzeit; print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Testausgabe</title>\n"; print "</head><body>\n"; print "verbrauchte Systemzeit: <strong>$Systemzeit</strong> Sekunden<br>\n"; print "verbrauchte Userzeit: <strong>$Userzeit</strong> Sekunden<br>\n"; print "verbrauchte CPU-Zeit: <strong>$CPU_Zeit</strong> Sekunden\n"; print "</body></html>\n";
Das Beispiel enth�lt zwei verschachtelte for-Schleifen, in denen sehr viel zu rechnen ist (es werden insgesamt 100.000 Funktionsaufrufe von
time und Bruchzahlrechnungen durchgef�hrt). Anschlie�end ermittelt das Beispiel die ben�tigten Zeiten. Vom Aufruf der Funktion
times
werden die ersten beiden Listenelemente, also die f�r den aktuellen Prozess, in den Skalaren $Systemzeit
und $Userzeit
festgehalten. Aus der Summe dieser beiden wird noch die CPU-Zeit ermittelt und in $CPU_Zeit
gespeichert. Zur Kontrolle gibt das Script die ermittelten Zeiten aus.
Unix-spezifischer Befehl.
Erwartet keine Parameter.
#!/usr/bin/perl -w #use strict; use CGI::Carp qw(fatalsToBrowser); $| = 1; print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Testausgabe</title>\n"; print "</head><body>\n"; my $Kind_pid = fork(); if($Kind_pid) { print "<p>Hier ist der Elternprozess.</p>\n"; wait(); print "<p>Der Kindprozess ist zuende.</p>\n"; } else { print "<p>Hier ist der Kindprozess.</p>\n"; exit(0); } print "</body></html>\n";
Das Beispiel erzeugt mit fork einen Kindprozess. Mit
if($Kind_pid)
wird abgefragt, ob der Skalar $Kind_pid
einen Wert ungleich 0
hat. Ist das der Fall, werden Anweisungen ausgef�hrt, die zum Elternprozess geh�ren. Im Beispiel wird eine Meldung ausgegeben, dass sich das Script im Elternprozess befindet. Im else
-Zweig, in den das Script gelangt, wenn Kind_pid
den Wert 0
hat, wird dagegen ausgegeben, dass der Kindprozess aktiv ist.
Normalerweise w�rde erst der if
-Zweig abgearbeitet, dann der else
-Zweig. Durch die Anweisung wait()
im if
-Zweig wartet jedoch der Elternprozess auf das Ende des Kindprozesses, bevor er fortf�hrt. So wird vorher der else
-Zweig abgearbeitet, und anschlie�end die letzte Meldung im if
-Zweig ausgegeben.
Unix-spezifischer Befehl. Ruft im Gegensatz zu wait direkt das Betriebssystem auf.
Erwartet als Parameter:
1. Die Prozessnummer (PID) des gew�nschten Kindprozesses.
2. Schalter (Flags - siehe Tabelle weiter unten)
Gibt die Prozessnummer (PID) des beendeten Prozesses zur�ck, oder -1
, wenn der gew�nschte Kindprozess nicht oder nicht mehr existiert. Auf manchen Systemen ist auch der R�ckgabewert 0
m�glich - er bedeutet, dass der Kindprozess noch immer l�uft (d.h. ein Timeout beim Warten �berschritten wurde).
#!/usr/bin/perl -w #use strict; use CGI::Carp qw(fatalsToBrowser); use POSIX; $| = 1; print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Testausgabe</title>\n"; print "</head><body>\n"; my $Kind_pid = fork(); if($Kind_pid) { print "<p>Hier ist der Elternprozess.</p>\n"; use POSIX ":sys_wait_h"; do { my $Kind_pid = waitpid(-1,&WNOHANG); } until $Kind_pid == -1; print "<p>Der Kindprozess ist zuende.</p>\n"; } else { print "<p>Hier ist der Kindprozess.</p>\n"; exit(0); } print "</body></html>\n";
Das Beispiel tut das gleiche wie jenes bei wait. In diesem Fall wird jedoch mit einer
do-until-Schleife gewartet, bis der Kindprozess zuende ist. Das ist der Fall, wenn die Funktion
waitpid
den R�ckgabewert -1
liefert, der Kindprozess also nicht mehr existiert.
Der Funktion waitpid
wird im Beispiel das Flag &WNOHANG
�bergeben. Die Konstanten dazu werden im Standardmodul
POSIX
definiert. Daher ist es erforderlich, dieses Modul so wie im Beispiel mit use POSIX ":sys_wait_h"
einzubinden.
Die folgende Tabelle listet die Flags auf, die Sie an der Stelle �bergeben k�nnen.
Flag: | Bedeutung: |
---|---|
&WEXITSTATUS |
Enth�lt den R�ckgabewert des Kindprozesses (genauer: die untersten 8 Bit, also einen Wert bis maximal 255). |
&WIFEXITED |
Hat den Wert true oder 1 , wenn der Kindprozess normal beendet wurde. |
&WIFSIGNALED |
Hat den Wert true oder 1 , wenn der Kindprozess durch ein unbeantwortetes Signal beendet wurde. |
&WIFSTOPPED |
Hat den Wert true oder 1 , wenn der Kindprozess angehalten wurde. |
&WNOHANG |
Der aufrufende Prozess wird nicht blockiert, falls der Kindprozess nicht sofort reagiert. In einem solchen Fall wird waitpid() sofort beendet und liefert 0 zur�ck. |
&WSTOPSIG |
Die Nummer des Signals, das zum Anhalten des Kindprozesses f�hrte (das Anhalten des Kindprozesses) kann mit &WIFSTOPPED ermittelt werden. |
&WTERMSIG |
Die Nummer des Signals, das vom Kindprozess nicht beantwortet wurde und deshalb zu dessen Beenden f�hrte (ob dies der Fall ist, kann mit &WIFSIGNALED ermittelt werden. |
&WUNTRACED |
waitpid() kehrt mit dem Status eines bereits gestoppten Kindprozesses zur�ck, dessen exit-R�ckgabewert aber noch nicht abgefragt wurde. |
![]() | |
![]() |
![]() |
![]() |
![]() |
![]() ![]() ![]() |
© 2007 Impressum