ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/docs/pws2004/goofed.pod
Revision: 1.4
Committed: Mon May 17 20:23:12 2004 UTC (22 years, 4 months ago) by root
Branch: MAIN
Changes since 1.3: +9 -3 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 =head1 GOOFED - Generic Object Oriented Flexible Extensible Daemon
2    
3     =head2 Abstract
4    
5 root 1.2 Perl ist eine tolle Sprache. Leider hat sie auch viele
6     Abhängigkeiten. Besonders bei Embedding muss man im Allgemeinen eine
7     ganze Perl-Installation "mitschleppen". Bei einem bestimmten Projekt
8     musste ich ohne externe Dateien oder andere Abhängigkeiten auskommen. Um
9     trotzdem Perl einsetzen zu können, musste alles in das Binary
10     wandern. Die Probleme und Lösungen, die ich fand, sind im Folgenden
11     beschrieben.
12 root 1.1
13 root 1.2 =head1 Wozu, weshalb und warum?
14    
15     Das Projekt, für das Goofed entstand, bestand darin, den Radius-Server
16     eines großen Internet-Providers in einigen Funktionen zu ersetzen. Da die
17     Anforderungen durch viele Jahre hinweg sehr speziell wurden (ein typisches
18     "I<Wir> setzen den Standard"-Phänomen) und die alte Codebasis neuen
19     Anforderungen nicht mehr gut gewachsen war, musste ein neuer Daemon her.
20    
21     Recht früh kam die Idee, im Kern für die komplizierten Regeln eine
22     High-Level-Skriptsprache zu verwenden und nur für das eigentliche
23     Radius-Paket-Management C zu verwenden.
24    
25     Perl schien zuerst an vielen Gründen zu scheitern: kompliziertes
26     Build-System, viele Abhängigkeiten und Dateien, keine gute Kontrolle
27     über den Speicherbedarf (Leaks wären tödlich für einen Daemon, der
28     meherre Monate durchhalten muss) und Last-not-Least stand zu befürchten,
29     daß die Server-Abteilung die Lösung sofort ablehnen würde, sobald
30 root 1.3 bekannt würde, daß sie Perl benutzt (typisches "Real-World - macht
31     keinen Sinn"-Phänomen).
32 root 1.2
33 root 1.3 =head2 Eckpunkte der Implementierung
34 root 1.1
35 root 1.3 Trotz dieser Gegenanzeigen versprach Perl auch wichtige Vorteile, der
36     wichtigste war das Vorhandensein einer grossen Codebasis und viele
37     Module. Das und Perl selbst führen meist sehr schnell zu verwertbaren
38     Ergebnissen.
39    
40     Um die Anforderungen zu Erfüllen, habe ich folgende Entscheidungen
41     gefällt:
42    
43     =over 4
44    
45     =item einzelnes Binary
46    
47     Bis auf die Konfigurationsdateien sollte alles - Perl-Interpreter, Module,
48     Bibliotheksdateien - in einer einzigen Datei sein und keine externen
49     Dateien benötigen oder anlegen.
50    
51     Dies schließt leider das (ansonsten hervorragende) PAR-Modul aus, da
52     dieses alle Bibliotheksdateien zwar in eine Datei packt, zur Laufzeit
53     diese aber lediglich entpackt und entsprechend viele Dateien schreibt.
54    
55     =item festgelegte Perl-Version
56    
57     Die Perl-Version sollte hartverdrahtet werden. Der Grund liegt in vielen,
58     kleinen Änderungen auch innerhalb stabiler Release-Zyklen, die zu
59     Build-Problemen oder Fehler zur Laufzeit führen können. I<Never change a
60     running system> war hier ausschlaggebend.
61    
62     Ausserdem kann man, sobald man die Kontrolle über dei Perl-Quellen
63     hat, bedenkenlos Anpassungen vornehmen (ich nenne das die "Lizenz zum
64     Rumsauen"-Regel).
65    
66     Es sollte möglich sein, den Perl-Kern upzugraden, wobei aber klar sein
67     sollte, das dies Veränderungen am Quellcode nach sich zieht.
68    
69     =item festgelegte Module und festgelegte Versionen
70    
71     Ähnliches gilt für Module: es sollte möglich sein, fast beliebige
72     Module einzubauen, aber auch diese sollten in einer festen Version kommen.
73    
74     Perl-Module auf CPAN haben - seien wir ehrlich - fast immer kleine und
75     große Bugs. Meistens kann man mit ihnen leben oder Workarounds finden
76     - häufig muss man dazu auf Interna zugreifen, die sich von Version zu
77     Version ändern.
78    
79     =item "normales" Build-System, kein Configure
80    
81     Configure nichtinteraktiv auszuführen ist kompliziert, und sehr viel kann
82     schiefgehen. Ein einfaches Makefile fühlt sich wesentlich stabiler und
83     einfacher wartbar an.
84    
85     =back
86    
87     Da der Daemon sehr viele Anfragen erhält und in anderer Form
88     weiterleitet, wäre es schön, wenn man die Bearbeitung der Anfragen
89     verzahnen könnte. Dazu braucht man ein vernünftiges Event-System (der
90     Name sagts schon - das Event-Modul) und etwas, mit dem man effizient
91     und vor allem einfach Pseudoparallelität erreichen kann - Coroutinen,
92     implementiert mit dem Coro-Modul.
93    
94     Coro greift auf viele Perl-Interna zu und ist eigentlich recht
95     experimentell, ich hatte aber Erfahrungen mit langlaufenden Servern und
96     Coro und wußte daher, das es sehr stabil läuft, sobald es läuft.
97    
98     Daß das Umfeld stabil ist, gab den Ausschlag.
99    
100     =head1 Implementierung
101    
102     Nachdem ein paar grundlegende Gedanken gedacht waren, konnte ich an die
103     Implementierung gehen. Flexibilität ist alles, wenn etwas schiefgeht.
104 root 1.1
105     =head2 Perl? .... Microperl!
106 root 1.3
107     Wenig bekannt ist, daß es auch eine Microperl-"Distribution" gibt,
108     die ein sehr kleines und portables Perl verspricht - ohne Module, ohne
109     Systemabhängigkeiten und ohne interaktives Configure.
110    
111     Die "Distribution" ist sehr klein: sie besteht nur aus den drei Dateien
112     C<README.micro>, C<Makefile.micro> und C<uconfig.sh>. Daher ist bei Perl
113     gleich mit dabei.
114    
115     Ich habe das Makefile und die nötigen Perl-Sourcen in ein
116     Unterverzeichnis kopiert und dann die Konfiguration, die standardmäßig
117     nur ISO-C89 + einige wenige Erweiterungen wie C<rename()> benötigt,
118     solange getuned, bis ich Zugriff auf die meisten POSIX-Funktionen hatte.
119    
120     Dazu habe ich die C<CFLAGS> von:
121    
122     -DPERL_CORE -DPERL_MICRO -DSTANDARD_C -DPERL_USE_SAFE_PUTENV
123    
124     auf
125    
126     -DPERL_CORE=1 -DPERL_MICRO=1
127    
128     geändert und die Konfiguration in C<uconfig.sh> getuned, compiliert und
129     solange iteriert, bis ich zum Link-Stadium kam.
130    
131     Danach hatte ich folgende Dateien in meinem C<uperl>-Verzeichnis:
132    
133     embed.h mg.h perlio.c proto.h thrdvar.h
134     EXTERN.h embedvar.h miniperlmain.c perlio.h reentr.c thread.h
135     INTERN.h ext.libs nostdio.h perliol.h reentr.h toke.c
136     Makefile form.h numeric.c perlsdio.h reentr.inc uconfig.sh
137     XSUB.h globals.c op.c perlvars.h regcomp.c universal.c
138     av.c gv.c op.h perly.c regcomp.h unixish.h
139     av.h gv.h opcode.h perly.h regexec.c utf8.c
140     config_h.SH handy.h opnames.h pp.c regexp.h utf8.h
141     configpm hv.c pad.c pp.h regnodes.h util.c
142     cop.h hv.h pad.h pp_ctl.c run.c util.h
143     cv.h intrpvar.h patchlevel.h pp_hot.c scope.c warnings.h
144     deb.c iperlsys.h perl.c pp_pack.c scope.h xsutils.c
145     doio.c keywords.h perl.h pp_proto.h sv.c
146     doop.c locale.c perlapi.c pp_sort.c sv.h
147     dump.c mg.c perlapi.h pp_sys.c taint.c
148    
149     Beim Bauen bekommt man die C<libuperl.a>, das Microperl-Äquivalent zur
150     C<libperl> und C<microperl>, das zum Bauen benötigt wird und auch beim
151     weiteren Build-Prozess hilfreich sein kann.
152    
153 root 1.4 Mit C<micrperl>, C<libuperl.a> und den Header-Dateien hat man alles, was
154     man zum Embedden benötigt.
155 root 1.3
156     Dieser Schritt war relativ leicht. Er wäre noch leichter gewesen, wenn
157     ich auf die meisten esoterischen Funktionen wie C<getpwnam>, C<mkdir> oder
158     Signal-Handling verzichtet hätte, da ich fast alles über die C<POSIX>-
159     und C<Event>-Module erreichen kann, und notfalls auch auf C zurückgreifen
160     könnte. Im absoluten Notfall.
161 root 1.1
162 root 1.4 =head2 Bibliothek
163    
164     Im nächsten Schritt
165    
166 root 1.1 =head2 Module Embedden
167    
168 root 1.4 Header und Library sind zwar genug, aber Perl-Module wollen ein
169     lauffähiges Perl und Zugriff auf Kleinkram wie C<ExtUtils::MakeMaker>,
170     damit man sie übersetzen kann.
171 root 1.1
172     =head2 Bootstrapping
173