LinuxUnixSystemprogrammierungAddison Wesley,HelmutHerold

1191

description

Legendary UNIX system programming book. Tell you all about realy close to OS libc calls and it´s internal functionalities

Transcript of LinuxUnixSystemprogrammierungAddison Wesley,HelmutHerold

LINUX/UNIX und seine Werkzeugebisher erschienen: Helmut Herold: LINUX-UNIX-Grundlagen Helmut Herold: LINUX-UNIX-Profitools Helmut Herold: LINUX-UNIX-Shells Helmut Herold: LINUX-UNIX-Systemprogrammierung Helmut Herold: LINUX-UNIX-Kurzreferenz

Helmut Herold

LINUX-UNIX-Systemprogrammierung2., berarbeitete Auflage

An imprint of Addison Wesley Longman, Inc.Bonn Reading, Massachusetts Menlo Park, California New York Harlow, England Don Mills, Ontario Sydney Mexico City Madrid Amsterdam

Die Deutsche Bibliothek CIP-Einheitsaufnahme Herold, Helmut: Linux-Unix-Systemprogrammierung : Helmut Herold. 2., berarb. Aufl. Bonn ; Rending, Mass. [u. a.] : Addison-Wesley-Longman, 1999. (Linux/Unix und seine Werkzeuge) ISBN 3-8273-1512-3 Buch: GB

1999 Addison-Wesley (Deutschland) GmbH, A Pearson Education Company 2., berarbeitete Auflage 1999

Lektorat: Susanne Spitzer und Andrea Stumpf, Mnchen Satz: Reemers EDV-Satz, Krefeld. Gesetzt aus der Palatino 9,5 Punkt Belichtung, Druck und Bindung: Ksel GmbH, Kempten Produktion: TYPisch Mller, Mnchen Umschlaggestaltung: Hommer Grafik-Design, Haar bei Mnchen Das verwendete Papier ist aus chlorfrei gebleichten Rohstoffen hergestellt und alterungsbestndig. Die Produktion erfolgt mit Hilfe umweltschonender Technologien und unter strengsten Auflagen in einem geschlossenen Wasserkreislauf unter Wiederverwertung unbedruckter, zurckgefhrter Papiere. Text, Abbildungen und Programme wurden mit grter Sorgfalt erarbeitet. Verlag, bersetzer und Autoren knnen jedoch fr eventuell verbliebene fehlerhafte Angaben und deren Folgen weder eine juristische Verantwortung noch irgendeine Haftung bernehmen. Die vorliegende Publikation ist urheberrechtlich geschtzt. Alle Rechte vorbehalten. Kein Teil dieses Buches darf ohne schriftliche Genehmigung des Verlages in irgendeiner Form durch Fotokopie, Mikrofilm oder andere Verfahren reproduziert oder in eine fr Maschinen, insbesondere Datenverarbeitungsanlagen, verwendbare Sprache bertragen werden. Auch die Rechte der Wiedergabe durch Vortrag, Funk und Fernsehen sind vorbehalten. Die in diesem Buch erwhnten Software- und Hardwarebezeichnungen sind in den meisten Fllen auch eingetragene Warenzeichen und unterliegen als solche den gesetzlichen Bestimmungen.

InhaltsverzeichnisEinleitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Gliederung dieses Buches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Unix-Standards und -Implementierungen . . . . . . . . . . . . . . . . . . . . . . Beispiele und bungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Hinweis zur Buchreihe: Unix und seine Werkzeuge . . . . . . . . . . . . . . 1 berblick ber die Unix-Systemprogrammierung . . . . . . . . . . . . . . . . . . . . . 1.1 Anmelden am Unix-System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2 Dateien und Directories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.3 Ein- und Ausgabe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.4 1.5 1.6 1.7 1.8 1.9 1.10 1.11 1.12 1.13 Prozesse unter Unix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ausgabe von System-Fehlermeldungen . . . . . . . . . . . . . . . . . . . . . . . . Benutzerkennungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Signale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Zeiten in Unix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Unterschiede zwischen Systemaufrufen und Bibliotheksfunktionen Unix-Standardisierungen und -Implementierungen . . . . . . . . . . . . . . Limits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Erste Einblicke in den Linux-Systemkern . . . . . . . . . . . . . . . . . . . . . . . bung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1 7 7 7 9 9 11 17 21 26 28 29 32 33 35 39 52 99

2 berblick ber ANSI C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 2.1 2.2 2.3 2.4 2.5 Allgemeines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Der Prprozessor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Sprache ANSI C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die ANSI-C-Bibliothek . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 106 114 124

bung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160

3 Standard-E/A-Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167 3.1 3.2 Der Datentyp FILE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167 stdin, stdout und stderr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168

vi

Inhaltsverzeichnis

3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10

ffnen und Schlieen von Dateien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168 Lesen und Schreiben in Dateien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172 Pufferung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200 Positionieren in Dateien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204 Temporre Dateien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207 Lschen und Umbenennen von Dateien . . . . . . . . . . . . . . . . . . . . . . . . 212 Ausgabe von Systemfehlermeldungen . . . . . . . . . . . . . . . . . . . . . . . . . . 214 bung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 216

4 Elementare E/A-Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 4.10 4.11 4.12 Filedeskriptoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221 ffnen und Schlieen von Dateien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222 Lesen und Schreiben in Dateien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229 Positionieren in Dateien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233 Effizienz von E/A-Operationen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237 Kerntabellen fr offene Dateien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240 File Sharing und atomare Operationen . . . . . . . . . . . . . . . . . . . . . . . . . 241 Duplizieren von Filedeskriptoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245 ndern oder Abfragen der Eigenschaften einer offenen Datei . . . . . 247 Filedeskriptoren und der Datentyp FILE . . . . . . . . . . . . . . . . . . . . . . . . 253 Das Directory /dev/fd . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259 bung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260

5 Dateien, Directories und ihre Attribute . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9 5.10 5.11 5.12 5.13 Dateiattribute . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dateiarten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Zugriffsrechte einer Datei . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Eigentmer und Gruppe einer Datei . . . . . . . . . . . . . . . . . . . . . . . . . . . 263 265 267 281

Partitionen, Filesysteme und i-nodes . . . . . . . . . . . . . . . . . . . . . . . . . . . 282 Symbolische Links . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297 Gre einer Datei . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303 Zeiten einer Datei . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 307 Directories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 311 Gertedateien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325 Der Puffercache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327 Realisierung von Filesystemen unter Linux . . . . . . . . . . . . . . . . . . . . . 329 bung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364

Inhaltsverzeichnis

vii

6 Informationen zum System und seinen Benutzern . . . . . . . . . . . . . . . . . . . . . 369 6.1 6.2 6.3 6.4 6.5 6.6 Informationen aus der Pawortdatei . . . . . . . . . . . . . . . . . . . . . . . . . . . 369 Informationen aus der Gruppendatei . . . . . . . . . . . . . . . . . . . . . . . . . . . 374 Informationen aus Netzwerkdateien . . . . . . . . . . . . . . . . . . . . . . . . . . . 377 Informationen zum lokalen System . . . . . . . . . . . . . . . . . . . . . . . . . . . . 378 Informationen zu Systemanmeldungen . . . . . . . . . . . . . . . . . . . . . . . . . 380 bung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 381

7 Datums- und Zeitfunktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 385 7.1 7.2 7.3 Datentypen und Konstanten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 385 Datums- und Zeitfunktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386 bung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401

8 Nicht-lokale Sprnge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403 8.1 8.2 Die Headerdatei . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403 bung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 416

9 Der Unix-Proze . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 419 9.1 9.2 9.3 9.4 9.5 9.6 9.7 9.8 Start eines Unix-Prozesses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 419 Beendigung eines Unix-Prozesses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 421 Environment eines Unix-Prozesses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 427 Speicherbelegung eines Unix-Prozesses . . . . . . . . . . . . . . . . . . . . . . . . 431 Ressourcenlimits eines Unix-Prozesses . . . . . . . . . . . . . . . . . . . . . . . . . 439 Ressourcenbenutzung eines Unix-Prozesses . . . . . . . . . . . . . . . . . . . . . 443 Die Speicherverwaltung unter Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . 445 bung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 477

10 Die Prozesteuerung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 483 10.1 10.2 10.3 10.4 10.5 10.6 10.7 10.8 10.9 Prozekennungen und die Unix-Prozehierarchie . . . . . . . . . . . . . . . 483 Kreieren von neuen Prozessen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 486 Warten auf Beendigung von Prozessen . . . . . . . . . . . . . . . . . . . . . . . . . Synchronisationsprobleme zwischen Eltern- und Kindprozessen . . . Die exec-Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Funktion system . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 502 515 520 527

ndern der User-ID und Group-ID eines Prozesses . . . . . . . . . . . . . . 532 Informationen zu Prozessen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 537 bung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 545

viii

Inhaltsverzeichnis

11 Attribute eines Prozesses (Kontrollterminal, Prozegruppe und Session) 11.1 11.2 11.3 11.4 11.5 11.6 11.7

549

Loginprozesse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 549 Prozegruppen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 554 Session . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 556 Kontrollterminals, Sessions und Prozegruppen . . . . . . . . . . . . . . . . . 557 Jobkontrolle und Programmausfhrung durch die Shell . . . . . . . . . . 559 Verwaiste Prozegruppen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 565 bung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 566

12 Blockierungen und Sperren von Dateien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 567 12.1 12.2 12.3 Blockierende und nichtblockierende E/A-Operationen . . . . . . . . . . . 567 Sperren von Dateien (record locking) . . . . . . . . . . . . . . . . . . . . . . . . . . . 568 bung (Multiuser-Datenbankbibliothek) . . . . . . . . . . . . . . . . . . . . . . . 583

13 Signale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 599 13.1 13.2 13.3 13.4 13.5 13.6 13.7 13.8 13.9 Das Signalkonzept und die Funktion signal . . . . . . . . . . . . . . . . . . . . . 599 Signalnamen und Signalnummern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 607 Probleme mit der signal-Funktion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 616 Das neue Signalkonzept . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 618 Senden von Signalen mit den Funktionen kill und raise . . . . . . . . . . . 628 Einrichten einer Zeitschaltuhr und Suspendieren eines Prozesses . . 630 Anormale Beendigung mit Funktion abort . . . . . . . . . . . . . . . . . . . . . . 648 Zustzliche Argumente fr Signalhandler . . . . . . . . . . . . . . . . . . . . . . 650 bung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 651

14 STREAMS in System V . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 655 14.1 14.2 14.3 Allgemeines zu STREAMS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 655 STREAM-Messages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 657 bung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 669

15 Fortgeschrittene Ein- und Ausgabe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 671 15.1 15.2 15.3 15.4 15.5 E/A-Multiplexing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 671 Asynchrone E/A . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 681 Memory Mapped I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 683 Weitere read- und write-Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . 695 bung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 699

Inhaltsverzeichnis

ix

16 Dmonprozesse 16.1 16.2 16.3 16.4 16.5

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 703

Typische Unix-Dmonen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 703 Besonderheiten von Dmonen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 704 Schreiben von eigenen Dmonen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 705 Fehlermeldungen von Dmonen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 707 bung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 714

17 Pipes und FIFOs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 717 17.1 17.2 17.3 17.4 berblick ber die unterschiedlichen Arten der Interprozekommunikation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 717 Pipes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 718 Benannte Pipes (FIFOs) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 744 bung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 749

18 Message-Queues, Semaphore und Shared Memory . . . . . . . . . . . . . . . . . . . . 753 18.1 18.2 18.3 18.4 18.5 Allgemeine Strukturen und Eigenschaften . . . . . . . . . . . . . . . . . . . . . . 753 Message-Queues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 756 Semaphore . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 770 Shared Memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 780 bung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 800

19 Stream Pipes, Client-Server-Realisierungen und Netzwerkprogrammierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 805 19.1 19.2 19.3 19.4 19.5 19.6 19.7 19.8 Client-Server-Eigenschaften der klassischen IPC-Methoden . . . . . . . 805 Stream Pipes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 807 Austausch von Filedeskriptoren zwischen Prozessen . . . . . . . . . . . . . 811 Client-Server-Realisierung mit verwandten Prozessen . . . . . . . . . . . . 823 Benannte Stream Pipes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 828 Client-Server-Realisierung mit nicht verwandten Prozessen . . . . . . . 845 Netzwerkprogrammierung mit TCP/IP . . . . . . . . . . . . . . . . . . . . . . . . 856 bung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 877

20 Terminal-E/A . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 879 20.1 20.2 20.3 20.4 20.5 20.6 Charakteristika eines Terminals im berblick . . . . . . . . . . . . . . . . . . . Terminalattribute und Terminalidentifizierung . . . . . . . . . . . . . . . . . . Spezielle Eingabezeichen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Terminalflags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 879 887 896 900

Baudraten von Terminals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 908 Zeilensteuerung bei Terminals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 910

x

Inhaltsverzeichnis

20.7 20.8 20.9 20.10 20.11 20.12 20.13

Kanonischer und nicht-kanonischer Modus . . . . . . . . . . . . . . . . . . . . . 912 Terminalfenstergren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 919 termcap, terminfo und curses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 921 S-Lang Eine Alternative zu curses unter Linux . . . . . . . . . . . . . . . . . 936 Die Linux-Konsole . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 953 Die Programmierung von virtuellen Konsolen unter Linux . . . . . . . . 985 bung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 994

21 Weitere ntzliche Funktionen und Techniken . . . . . . . . . . . . . . . . . . . . . . . . 1007 21.1 21.2 21.3 Expandierung von Dateinamen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1007 String-Vergleiche mit regulren Ausdrcken . . . . . . . . . . . . . . . . . . . . 1013 Abarbeiten von Optionen auf der Kommandozeile . . . . . . . . . . . . . . . 1023

22 Wichtige Entwicklungswerkzeuge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1055 22.1 22.2 22.3 22.4 22.5 22.6 22.7 22.8 gcc Der GNU-C-Compiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1055 ld Der Linux/Unix-Linker . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1060 gdb Der GNU-Debugger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1061 strace Mitprotokollieren aller Systemaufrufe . . . . . . . . . . . . . . . . . . . 1067 Tools zum Auffinden von Speicherberschreibungen und -lcken . 1073 ar Erstellen und Verwalten von statischen Bibliotheken . . . . . . . . . 1082 Dynamische Bibliotheken . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1087 make Ein Werkzeug zur automatischen Programmgenerierung . . 1100 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1123

A Headerdatei eighdr.h und Modul fehler.c A.1 A.2

Headerdatei eighdr.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1123 Zentrales Fehlermeldungsmodul fehler.c . . . . . . . . . . . . . . . . . . . . . . . 1124

B Ausgewhlte Lsungen zu den bungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1129 B.1 B.2 B.3 B.4 B.5 B.6 B.7 B.8 B.9 Ausgewhlte Lsungen zu Kapitel 4 (Elementare E/A-Funktionen) 1129 Ausgewhlte Lsungen zu Kapitel 5 (Dateien, Directories und ihre Attribute) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1130 Ausgewhlte Lsungen zu Kapitel 7 (Datums- und Zeitfunktionen) 1133 Ausgewhlte Lsungen zu Kapitel 8 (Nicht-lokale Sprnge) . . . . . . 1133 Ausgewhlte Lsungen zu Kapitel 9 (Der Unix-Proze) . . . . . . . . . . 1134 Ausgewhlte Lsungen zu Kapitel 10 (Die Prozesteuerung) . . . . . . 1135 Ausgewhlte Lsungen zu Kapitel 11 (Attribute eines Prozesses) . . 1137 Ausgewhlte Lsungen zu Kapitel 13 (Signale) . . . . . . . . . . . . . . . . . . 1139 Ausgewhlte Lsungen zu Kapitel 14 (STREAMS in System V) . . . . 1141

Inhaltsverzeichnis

xi

B.10 B.11 B.12 B.13

Ausgewhlte Lsungen zu Kapitel 15 (Fortgeschrittene Ein- und Ausgabe) . . . . . . . . . . . . . . . . . . . . . . . . . . . 1141 Ausgewhlte Lsungen zu Kapitel 16 (Dmonprozesse) . . . . . . . . . . 1142 Ausgewhlte Lsungen zu Kapitel 17 (Pipes und FIFOs) . . . . . . . . . . 1142 Ausgewhlte Lsungen zu Kapitel 18 (Message-Queues, Semaphore und Shared Memory) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1144

Literaturverzeichnis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1145 Stichwortverzeichnis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1149

EinleitungIn die Tiefe mut du steigen, soll sich dir das Wesen zeigen. Schiller

Dieses Buch beschreibt die Systemprogrammierung unter Linux/Unix. Unix bietet wie jedes Betriebssystem sogenannte Systemaufrufe an, die von den Benutzerprogrammen aus aufgerufen werden knnen, wenn diese bestimmte Dienste vom System bentigen. Typische von einem Betriebssystem angebotene Dienste sind z.B. ffnen einer Datei, Schreiben auf eine Datei, Bereitstellen von freiem Speicherplatz oder Kommunizieren mit anderen Programmen. Diese Systemaufrufe werden ebenso wie andere wichtige Funktionen aus der C-Standardbibliothek in diesem Buch anhand von zahlreichen anschaulichen Beispielen ausfhrlich beschrieben. Praxisnahe bungen am Ende jedes Kapitels ermglichen dem Leser das Anwenden und Vertiefen der jeweils erworbenen Kenntnisse. An entsprechenden Stellen wird in diesem Buch die Umsetzung von wichtigen Betriebssystemkonzepten und -algorithmen am System Linux gezeigt. Dieses System wurde nicht nur aufgrund seiner groen Beliebtheit ausgewhlt, sondern auch, weil Linux alle seine Quellprogramme der ffentlichkeit zur Verfgung stellt.

Gliederung dieses BuchesDer Inhalt dieses Buch untergliedert sich in zehn Themengebiete sowie in einen Anhang.

Einfhrung in die Unix-Systemprogrammierung (Kapitel 1 - 2)berblick ber die Unix-Systemprogrammierung (Kapitel 1)In diesem Kapitel wird zunchst ein kurzer Einblick in die Unix-Konzepte und -Begriffe gegeben, bevor ein kleiner Ausflug in die wichtigsten Gebiete der Systemprogrammierung erfolgt, um in den spteren Kapiteln auf diese Grundbegriffe Bezug nehmen zu knnen, ohne da stndig eine Erklrung eines erst spter behandelten Begriffes eingeschoben werden mu. In diesem Kapitel wird darber hinaus ein kurzer berblick ber wichtige Unix-Standards und -Systeme gegeben. Zum Abschlu bekommen Sie erste Einblicke in den LinuxSystemkern. Dieser Linux-spezifische Abschnitt ist nur fr Leser gedacht, die an der Umsetzung von Betriebssystemkonzepten und -algorithmen interessiert sind oder die

2

Einleitung

selbst Kernroutinen oder systemnahe Funktionen programmieren mchten. Dieser umfangreiche Abschnitt zeigt den grundlegenden Aufbau des Linux-Systemkerns, klrt wichtige Begriffe und stellt wesentliche Kernalgorithmen und -konzepte vor, die fr das Verstndnis der spteren Linux-spezifischen Kapitel vorausgesetzt werden.

berblick ber ANSI C (Kapitel 2)Da zur Linux/Unix-Systemprogrammierung die Programmiersprache C verwendet wird, wird hier ein kurzer berblick ber das heute gltige Standard-C (auch ANSI C genannt) gegeben. Dazu werden in diesem Kapitel zunchst allgemein geltende ANSI-CBegriffe und -Konstrukte behandelt, bevor nher auf den Prprozessor und die Sprache ANSI C eingegangen wird. Am Ende dieses Kapitels wird ein berblick ber die nun standardisierten Headerdateien gegeben. Dabei werden alle von ANSI C vorgeschriebenen Konstanten, Datentypen, Makros, globale Variablen und Funktionen kurz vorgestellt, soweit diese nicht in spteren Kapiteln ausfhrlich behandelt werden.

Ein- und Ausgabe (Kapitel 3 - 5)Standard-E/A-Funktionen (Kapitel 3)Hier werden die Funktionen beschrieben, die sich in der C-Standardbibliothek befinden und in der Headerdatei definiert sind. Die in dieser Headerdatei definierten Datentypen und Funktionen dienen der Ein- und Ausgabe auf das Terminal oder auf Dateien. Die hier vorgestellten Funktionen arbeiten mit optimal eingestellten Puffern, so da sich der Benutzer vollstndig auf seine Ein- und Ausgabe konzentrieren kann, ohne sich um solche Details kmmern zu mssen.

Elementare E/A-Funktionen (Kapitel 4)Die hier beschriebenen elementaren E/A-Funktionen leisten hnliches wie die StandardE/A-Funktionen, nur da sie als systemnahe Funktionen nicht Bestandteil von ANSI C sind und nicht den Komfort der Standard-E/A-Funktionen bieten, dafr aber schneller ablaufen und dem Benutzer mehr Einflumglichkeiten auf seine Ein- und Ausgabe geben.

Dateien, Directories und ihre Attribute (Kapitel 5)Dieses Kapitel beschreibt die Attribute, die zu jeder Datei und jedem Directory im sogenannten i-node gespeichert sind, und stellt die Funktionen vor, mit denen diese Attribute erfragt oder modifiziert werden knnen. Auerdem wird die grundlegende Struktur eines Unix-Dateisystems vorgestellt, und es werden Begriffe wie i-nodes und symbolische Links geklrt, bevor auf die konkrete Realisierung von Dateisystemen unter Linux eingegangen wird, wobei hier insbesondere das meist unter Linux verwendete ext2Dateisystem detaillierter beschrieben wird. Auch stellt dieses Kapitel Funktionen vor, mit denen man Directories anlegen, deren Inhalt lesen oder aber in andere Directories wechseln kann.

Gliederung dieses Buches

3

Systeminformationen (Kapitel 6 - 7)Informationen zum System und seinen Benutzern (Kapitel 6)Dieses Kapitel stellt Funktionen vor, mit denen Informationen aus der Pawortdatei, aus der Gruppendatei, aus Netzwerkdateien und Informationen zum lokalen System und seinen Benutzern erfragt werden knnen.

Datums- und Zeitfunktionen (Kapitel 7)Hier werden Konstanten, Datentypen und Funktionen beschrieben, mit denen das Setzen und Erfragen von Datums- und Zeitwerten mglich ist.

Nicht-lokale Sprnge (Kapitel 8)Dieses Kapitel beschreibt die beiden ANSI-C-Funktionen setjmp und longjmp, mit denen ein Springen ber Funktionsgrenzen hinweg mglich ist.

Prozesse (Kapitel 9 - 13)Der Unix-Proze (Kapitel 9)Dieses Kapitel beschftigt sich mit Unix-Prozessen im allgemeinen. Dazu beschreibt es zunchst die Aktivitten seitens des Systems, die beim Start und der Beendigung eines Unix-Prozesses ablaufen, bevor es auf die Umgebung (Environment) und die Speicherbelegung eines Unix-Prozesses genauer eingeht. Es wird auch auf die Ressourcenlimits eingegangen, die einem Unix-Proze auferlegt sind. Zum Abschlu dieses Kapitels wird ein Einblick in die Speicherverwaltung und das Abbilden von Dateien in den Speicher (Memory Mapping) unter Linux gegeben. Dieses Kapitel ist nur fr Leser von Interesse, die mehr ber die interne Speicherverwaltung eines realen Systems wissen mchten.

Die Prozesteuerung (Kapitel 10)Dieses Kapitel stellt die Kennungen eines Prozesses und die Unix-Prozehierarchie vor, bevor es auf das Kreieren von neuen Prozessen und dabei insbesondere auf die Beziehungen von Eltern- und Kind-Prozessen nher eingeht. Ebenso beschftigt sich dieses Kapitel mit dem Warten von Prozessen auf die Beendigung von anderen Prozessen, bevor es mgliche Probleme der Synchronisation von Eltern- und Kindprozessen beschreibt. Des weiteren stellt dieses Kapitel die exec-Funktionen vor, mit denen sich ein Proze durch ein anderes Programm berlagern kann. Der Rest dieses Kapitels beschftigt sich mit dem ndern von Prozekennungen und dem Erfragen von Informationen zu einem Proze.

4

Einleitung

Attribute eines Prozesses (Kapitel 11)Hier werden zunchst die bei einem Login ablaufenden Prozesse beschrieben, wobei zwischen Terminal- und Netzwerk-Logins unterschieden wird. Des weiteren werden in diesem Kapitel die Begriffe Prozegruppe, Kontrollterminal und Session (Sitzung) nher erlutert. Auch wird hier ein detaillierter Einblick in die von vielen Shells angebotene Jobkontrolle und die dabei ablaufenden Mechanismen gegeben.

Sperren von Dateien (Kapitel 12)Dieses Kapitel stellt zunchst blockierende und nicht blockierende E/A-Operationen vor, bevor es sich ausfhrlich mit dem Sperren von Dateien und den dabei mglichen Problemen beschftigt. In der bung wird ein umfangreicheres Projekt vorgestellt, in dem eine einfache Mehrbenutzer-Datenbank entwickelt werden soll.

Signale (Kapitel 13)Signale sind asynchrone Ereignisse, die von der Hard- oder Software erzeugt werden, wenn whrend einer Programmausfhrung besondere Ausnahmesituationen auftreten. In diesem Kapitel wird zunchst das Unix-Signalkonzept und die wichtige Funktion signal vorgestellt, bevor ein berblick ber die verschiedenen Arten von Signalen gegeben wird. Nachfolgend werden weitere Funktionen vorgestellt, mit denen z.B. das explizite Senden von Signalen, das Einrichten einer Zeitschaltuhr, das Suspendieren oder das anormale Beendigen eines Prozesses mglich ist.

Besondere Arten von E/A (Kapitel 14 - 16)STREAMS in SVR4 (Kapitel 14)Die in diesem Kapitel beschriebenen STREAMS werden von System V Release 4 (SVR4) vollstndig untersttzt und sind dort die allgemeine Schnittstelle zu Kommunikationstreibern.

Fortgeschrittene E/A (Kapitel 15)Dieses Kapitel beschftigt sich mit den folgenden Formen der Ein- und Ausgabe: E/AMultiplexing, asynchrone E/A, gleichzeitiges Lesen und Schreiben aus mehreren nicht zusammenhngenden Puffern und das sogenannte Memory Mapped I/O. Die Kenntnis dieser Formen der Ein- und Ausgabe ist Voraussetzung fr das Verstndnis der Kapitel 17, 18 und 19, die sich mit der Interprozekommunikation beschftigen.

Dmonprozesse (Kapitel 16)Dmonprozesse sind Prozesse, die stndig im Hintergrund ablaufen. Sie werden blicherweise beim Booten des Systems gestartet und laufen dann so lange, bis das System ordnungsgem heruntergefahren wird oder aber zusammenbricht. Dmonprozesse sind fr stndig anfallende Aufgaben zustndig. Dieses Kapitel gibt zunchst einen berblick

Gliederung dieses Buches

5

ber typische Unix-Dmonen und deren Besonderheiten und zeigt dann, wie ein eigener Dmonproze zu erstellen ist. Da ein Dmonproze im Hintergrund luft und somit auch kein Kontrollterminal besitzt, wird zustzlich noch gezeigt, wie ein Dmonproze dennoch das Auftreten von Fehlern melden kann.

Interprozekommunikation (Kapitel 17 - 19)Pipes und FIFOS (Kapitel 17)In diesem Kapitel werden Techniken der Kommunikation zwischen unterschiedlichen Prozessen, der sogenannten Interprozekommunikation, vorgestellt. Als Kommunikationsmittel werden Pipes und FIFOs (benannte Pipes), die beide zunchst ausfhrlich beschrieben werden, verwendet. Auch wird in einem Beispiel eine erste Client-ServerKommunikation vorgestellt, die mittels FIFOs verwirklicht ist.

Message-Queues, Semaphore und Shared Memory (Kapitel 18)In diesem Kapitel werden drei Methoden der Interprozekommunikation vorgestellt: Austausch von Nachrichten (Message-Queues = Nachrichten-Warteschlangen) Synchronisation ber Semaphore Austausch von Daten ber gemeinsame Speicherbereiche (Shared Memory). Bevor in diesem Kapitel auf die Methoden und die zugehrigen Funktionen im einzelnen eingegangen wird, werden zunchst die allen drei Methoden zugrundeliegenden Strukturen und Eigenschaften vorgestellt.

Stream Pipes, Client-Server-Realisierungen und Netzwerkprogrammierung (Kapitel 19)In diesem Kapitel werden neuere Formen der Interprozekommunikation vorgestellt: Stream Pipes und benannte Stream Pipes. Diese beiden Methoden erlauben z.B. den Austausch von Filedeskriptoren zwischen verschiedenen Prozessen oder die Kommunikation von Clients mit einem Server, der als Dmonproze abluft. Hierzu werden jeweils Beispiele gegeben. Auch geht dieses Kapitel auf die Grundlagen der Socket- und Netzwerkprogrammierung mit TCP/IP ein, wozu es u.a. ein Beispielprogramm zur Kommunikation zwischen zwei Rechnern in einem Netzwerk vorstellt.

Terminal-E/A (Kapitel 20)Der Begriff Terminal-E/A umfat alle Funktionen zur Steuerung und Programmierung der seriellen Schnittstellen (seriellen Ports) eines Rechners. An den seriellen Ports knnen neben Terminals auch Modems, Drucker usw. angeschlossen werden. In diesem Kapitel werden alle von POSIX.1 vorgeschriebenen Terminalfunktionen und einige zustzliche Funktionen vorgestellt, die von System V Release 4 und BSD-Unix angeboten werden. Zudem stellt dieses Kapitel die Bibliotheken curses und S-Lang vor, mit denen Semigra-

6

Einleitung

phikprogrammierung unter Linux/Unix mglich ist. Des weiteren werden hier die Eigenschaften einer Linux-Konsole detaillierter vorgestellt, bevor am Ende dieses Kapitels noch auf die Programmierung von virtuellen Konsolen unter Linux eingegangen wird.

Ntzliche Funktionen und Techniken (Kapitel 21)Hier werden weitere Funktionen vorgestellt, die sehr wertvolle Dienste bei der Systemprogrammierung leisten knnen. Es werden dabei zunchst Funktionen zur Dateinamenexpandierung vorgestellt, bevor dann wichtige Funktionen beschrieben werden, die man zum Arbeiten mit regulren Ausdrcken innerhalb von Programmen bentigt. Am Ende des Kapitels werden dann Funktionen und Techniken vorgestellt, mit denen man Optionen auf der Kommandozeile abarbeiten kann.

Wichtige Entwicklungswerkzeuge (Kapitel 22)Dieses Kapitel stellt kurz wichtige Entwicklungswerkzeuge vor, die bei der Systemprogrammierung unter Linux/Unix bentigt werden: den GNU-C-Compiler gcc, den Linux/ Unix-Linker ld, den GNU-Debugger gdb, das Programm strace zum Mitprotokollieren von Systemaufrufen, Werkzeuge zum Auffinden von Speicherberschreibungen (Electric Fence, checkergcc und mpr), das Programm ar zum Erstellen und Verwalten von statischen Bibliotheken, das Erstellen von und Arbeiten mit dynamischen Bibliotheken und sogenannten shared objects und das Werkzeug make zur automatischen Programmgenerierung.

AnhangIm Anhang befinden sich neben der eigenen Headerdatei eighdr.h und dem Programm fehler.c, die beide in fast allen Beispielen dieses Buches benutzt werden, ausgewhlte Lsungen zu den bungen der einzelnen Kapitel.

LiteraturhinweiseAls Vorbild zu diesem Buch diente das Buch Advanced Programming in the UNIX Environment von W. Richard Stevens. Dieses Standardwerk von Stevens gab viele Hinweise, Anregungen und Tips. Zu dem vorliegenden Buch existiert ein begleitendes Buch Linux-Unix Kurzreferenz, das neben der Beschreibung anderer wichtiger Linux/Unix-Tools auch eine Kurzfassung zu allen typischen Aufrufformen der hier behandelten Funktionen, wichtige Konstanten, Datentypen, Strukturen oder Limitvorgaben enthlt. Die Kurzreferenz soll neben den Manpages dem Programmierer ntzliche und schnelle Informationen beim tglichen Programmieren seines Linux/Unix-Systems geben.

Unix-Standards und -Implementierungen

7

Unix-Standards und -ImplementierungenDie Vielzahl der verschiedenen Unix-Versionen fhrte in den achtziger Jahren dazu, da groe Anstrengungen unternommen wurden, Standards zu schaffen, an die sich die einzelnen Unix-Varianten halten sollten. So wurde mit ANSI C ein Standard fr die Programmiersprache C geschaffen, an den sich heute die meisten C-Compiler halten. Fr das Betriebssystem Unix selbst ist der IEEE-POSIX-Standard und der X/Open Portability Guide (XPG) von Bedeutung. Dieses Buch beschreibt diese Standards, wobei es allerdings immer wieder auf die heute weit verbreiteten Implementierungen System V Release 4 (SVR4), BSD-Unix (BSD) und Linux eingeht.

Beispiele und bungenIn diesem Buch befinden sich viele Programmbeispiele und bungen. Alle Programmlistings, die Lsungen zu den einzelnen bungen sind, knnen ebenso wie alle Beispielprogramme von der WWW-Adresse http://www.addison-wesley.de/service/herold/ sysprog.tgz heruntergeladen werden.

Test der Beispiele unter SOLARIS und LinuxDie meisten der in diesem Buch angegebenen Programmbeispiele wurden sowohl unter SOLARIS wie unter Linux getestet. Da teilweise auch implementierungsspezifische Eigenschaften in den Programmen verwendet werden, konnten jedoch einige wenige Programmbeispiele nicht auf beiden Systemen zum Laufen gebracht werden.

bungen am Ende jedes KapitelsAm Ende jedes der nachfolgenden Kapitel befinden sich bungen, die dem Leser die Mglichkeit geben, das Verstndnis der zuvor beschriebenen Funktionen und Konstrukte zu vertiefen. Ausgewhlte Lsungen zu diesen Aufgabenstellungen befinden sich in Anhang B.

Hinweis zur Buchreihe: Unix und seine WerkzeugeDiese Buchreihe soll den Unix-Anfnger systematisch vom Unix-Basiswissen ber die leistungstarken Unix- Werkzeuge bis hin zu den fortgeschrittenen Techniken der Systemprogrammierung fhren. dem bereits erfahrenen Unix-Anwender durch ihren modularen Aufbau eine Vertiefung bzw. Ergnzung seines Unix-Wissens ermglichen.

8

Einleitung

Linux-Unix Kurzreferenz

Nachschlagewerk zu Kommandos und Systemfunktionen

Teil 4 - Linux-Unix SystemprogrammierungDateien, Prozesse und Signale Fortgeschrittene E/A, Dmonen und Prozekommunikation

Teil 3 - Linux-Unix Profitoolsawk, sed, lex, yacc und make

Teil 2 - Linux-Unix ShellsBourne-Shell, Korn-Shell, C-Shell, bash, tcsh

Teil 1 - Linux-Unix Grundlagen

Kommandos und Konzepte

Die Buchreihe Unix und seine Werkzeuge

1

berblick ber die UnixSystemprogrammierungHat der Fuchs die Nase erst hinein, so wei er bald den Leib auch nachzubringen. Shakespeare

Jedes Betriebssystem bietet sogenannte Systemroutinen an, die von den Benutzerprogrammen aufgerufen werden knnen, wenn diese gewisse Dienste vom System bentigen. Typische von einem Betriebssystem angebotene Dienste sind z.B. ffnen einer Datei, Schreiben auf eine Datei, Bereitstellen von freiem Speicherplatz oder Kommunikation mit anderen Programmen. In diesem Kapitel wird anhand von kurzen Beschreibungen und Beispielen ein grober berblick ber grundlegende Unix-Eigenschaften und die wichtigsten Gebiete der Systemprogrammierung gegeben, um den Leser bereits zu Beginn mit den wichtigsten Grundbegriffen und Konzepten vertraut zu machen. Bei den detaillierteren Beschreibungen der einzelnen Systemfunktionen in den spteren Kapiteln verfgt der Leser dann ber das entsprechende Grundwissen, und es mu nicht stndig eine Erklrung eines erst spter genau behandelten Begriffes eingeschoben werden. Auch wird in diesem Kapitel noch ein kurzer berblick ber wichtige Unix-Standardisierungen und Unix-Systeme gegeben. Zum Abschlu werden erste Einblicke in den Linux-Systemkern gegeben. Dieser Linuxspezifische Abschnitt ist nur fr Leser gedacht, die an der Verwirklichung von Betriebssystemkonzepten und -algorithmen interessiert sind oder die selbst Kernroutinen oder systemnahe Funktionen programmieren mchten. Dieser umfangreichere Abschnitt zeigt den grundlegenden Aufbau des Linux-Systemkerns, klrt wichtige Begriffe und stellt wesentliche Kernalgorithmen und -konzepte vor, die fr das Verstndnis der spteren Linux-spezifischen Kapitel vorausgesetzt werden.

1.1

Anmelden am Unix-System

Um sich am Unix-System anzumelden, mu der Benutzer zunchst seinen Loginnamen und sein Pawort eingeben. Das System sucht den Loginnamen zunchst in der Datei /etc/passwd.

10

1

berblick ber die Unix-Systemprogrammierung

1.1.1

/etc/passwd

In der Datei /etc/passwd befindet sich zu jedem autorisierten Benutzer eine Zeile, die z.B. folgende Information enthlt:heh:huj67hXdfg8ah:118:109:Helmut Herold:/user1/heh:/bin/sh (Bourne-Shell) ali:hzuS2kIluO53f:143:111:Albert Igel:/user1/ali: (keine Angabe=Bourne-Shell) fme:hksdq.Rx8pcJa:121:110:Fritz Meyer:/user2/fme:/bin/ksh (Korn-Shell) mik:6idEFG73ha7uj:138:110:Michael Kode:/user2/mik:/bin/csh (C-Shell) | | | | | | | | | | | | | Loginshell | | | | | Home-Directory | | | | Weitere Info.zum Benutzer (meist:richtigerName) | | | Gruppenummer (GID) | | Benutzernummer (UID) | Verschlsseltes Pawort Login-Kennung

Innerhalb jeder Zeile sind die einzelnen Felder durch Doppelpunkte getrennt. Die neueren Unix-Systeme wie SVR4 hinterlegen das Pawort aus Sicherheitsgrnden nicht mehr in /etc/passwd, sondern in der nicht fr jedermann lesbaren Datei /etc/shadow. In diesem Fall steht in /etc/passwd anstelle des Paworts nur ein Stern (*). Nachdem das System den entsprechenden Eintrag gefunden hat, verschlsselt es das eingegebene Pawort und vergleicht es mit dem in /etc/passwd bzw. /etc/shadow angegebenen Pawort. Sind beide Pawrter identisch, so wird dem betreffenden Benutzer der Zugang zum System gestattet.

1.1.2

Shells

Nach einem erfolgreichem Anmeldevorgang wird die in /etc/passwd fr den betreffenden Benutzer angegebene Shell gestartet. Eine Shell ist ein Programm, das die Kommandos des Benutzers entgegennimmt, interpretiert und in Systemaufrufe umsetzt, so da die vom Benutzer geforderten Aktivitten vom System durchgefhrt werden. Die Shell ist demnach ein Kommandointerpreter. Im Unterschied zu anderen Systemen ist die Unix-Shell nicht Bestandteil des Betriebssystemkerns, sondern ein eigenes Programm, das sich zwar bezglich der Leistungsfhigkeit von anderen Unix-Kommandos erheblich unterscheidet, aber doch wie jedes andere Unix-Kommando oder -Anwenderprogramm aufgerufen oder sogar ausgetauscht werden kann. Da die Shell einfach austauschbar ist, wurden auf den unterschiedlichen Unix-Derivaten und -Versionen eigene Shell-Varianten entwickelt. Drei Shell-Varianten1 haben sich dabei durchgesetzt und werden heute auf SVR4 angeboten: Bourne-Shell (/bin/sh) Korn-Shell (/bin/ksh) C-Shell (/bin/csh)1. Alle drei Shell-Varianten sind ausfhrlich im Band Linux-Unix-Shells dieser Reihe beschrieben.

1.2

Dateien und Directories

11

Weitere sehr beliebte Shells, die z.B. bei Linux schon standardgem mitgeliefert werden, sind die Bourne-Again-Shell (/bin/bash) und die TC-Shell (/bin/tcsh). Diese beiden letzten Shells sind als Freeware erhltlich und sind verbesserte Versionen der Bourne- (bash) bzw. der C-Shell (tcsh). Welche Shell das System nach dem Anmelden fr den betreffenden Benutzer starten soll, erfhrt es aus dem 7. Feld der entsprechenden Benutzerzeile in /etc/passwd.

1.21.2.1

Dateien und DirectoriesDateistruktur

Unter Unix gibt es eigentlich keine Struktur fr Dateien2. Eine Datei ist fr das System nur eine Folge von Bytes (featureless byte stream), und ihrem Inhalt wird vom System keine Bedeutung beigemessen. Unix kennt nur sequentielle Dateien und keine sonstigen DateiOrganisationen, welche in anderen Betriebssystemen blich sind, wie z.B. indexsequentielle Dateien. Die einzigen Ausnahmen sind die Dateiarten, die fr die Dateihierarchie und die Identifizierung der Gerte bentigt werden.

1.2.2

Lnge von Dateien

Dateien sind stets in Blcken von Bytes gespeichert. Damit ergeben sich zwei mgliche Gren fr Dateien: Lnge in Byte Lnge in Blcken (bliche Blockgren sind z.B. 512 oder 1024 Byte) Unix legt keine Begrenzung bezglich einer maximalen Dateigre fest. Somit knnen zumindest theoretisch Dateien beliebig lang sein.

1.2.3

Dateiarten

Es werden mehrere Arten von Dateien unterschieden: Regular Files (regulre Dateien, einfache Dateien, gewhnliche Dateien) Eine solche Datei ist eine Sammlung von Zeichen, die unter den entsprechenden Dateinamen gespeichert sind. Diese Dateien knnen beliebigen Text, Programme oder aber den Binrcode eines Programms enthalten.

2. Das Unix-Dateisystem, die Dateien und Directories sind ausfhrlich im Band Linux-Unix-Grundlagen dieser Reihe beschrieben.

12

1

berblick ber die Unix-Systemprogrammierung

Special Files (spezielle Dateien, Gertedateien) Gertedateien reprsentieren die logische Beschreibung von physikalischen Gerten wie z.B. Bildschirmen, Druckern oder Festplatten. Das Besondere am Unix-System ist, da es von solchen Gertedateien in der gleichen Weise liest oder auf sie schreibt, wie es dies bei gewhnlichen Dateien tut. Jedoch wird hierbei nicht der normale Dateizugriff aktiviert, sondern der entsprechende Gertetreiber (device driver). Es werden zwei Klassen von Gerten unterschieden: zeichenorientierte Gerte (Datentransfer erfolgt zeichenweise, wie z.B. Terminal) blockorientierte Gerte (Datentransfer erfolgt nicht byteweise, sondern in Blcken, wie z.B. bei Festplatten) Directory (Dateiverzeichnis) Ein Directory enthlt wieder Dateien. Es kann neben einfachen Dateien auch andere Dateiarten (wie z.B. Gertedateien) oder aber auch wiederum Directories (sogenannte Subdirectories bzw. Unterverzeichnisse) enthalten. Zu jedem in einem Directory enthaltenen Dateinamen existiert Information ber dessen Attribute. Diese Dateiattribute informieren z.B. ber die Art, Gre, Eigentmer, Zugriffsrechte einer Datei. Die in einem spteren Kapitel vorgestellten Systemfunktionen stat und fstat liefern dem Aufrufer eine Struktur, in der er alle Attribute zu der entsprechenden Datei findet. Beim Anlegen eines neuen Directorys werden immer die folgenden beiden Dateinamen automatisch dort angelegt:. .. Name fr dieses Directory Name fr das sogenannte Parent-Directory (siehe unten).

FIFO (first in first out, Named Pipes) FIFOS auch Named Pipes genannt dienen der Kommunikation und Synchronisation verschiedener Prozesse. Prinzipiell knnen sie wie einfache Dateien benutzt werden, mit dem wesentlichen Unterschied, da Daten nur einmal gelesen werden knnen. Zudem knnen sie nur in der Reihenfolge gelesen werden, wie sie geschrieben wurden. Sockets Sockets dienen zur Kommunikation von Prozessen in einem Netzwerk, knnen aber auch zur Kommunikation von Prozessen auf einem lokalen Rechner benutzt werden. Symbolic Links (symbolische Verweise) Symbolische Links sind Dateien, die lediglich auf andere Dateien zeigen.

1.2.4

Zugriffsrechte

Jeder Datei (regulre Datei, Directory ...) ist unter Unix ein aus 9 Bits bestehendes Zugriffsrechte-Muster zugeordnet. Jeweils 3 Bit geben dabei die Zugriffsrechte (read, write, execute) der entsprechenden Benutzerklasse (owner, group, others) an. Diese Zugriffsrechte von Dateien kann man sich mit der Angabe der Option -l beim ls-Kommando anzeigen lassen, wie z.B.:

1.2

Dateien und Directories

13

$ ls -l kopier -rwxr-x--x 1 hh $

grafik

867 May

17

1995 kopier

An dieser Ausgabe lt sich erkennen, da der Eigentmer der Datei (hier hh) die Datei kopier lesen, beschreiben oder ausfhren darf, whrend alle Mitglieder der grafik-Gruppe die Datei kopier nur lesen oder ausfhren drfen. Alle anderen Benutzer (others) drfen die kopier-Datei nur ausfhren, aber nicht lesen oder beschreiben.

1.2.5

Dateinamen

In einem Dateinamen sind auer dem Slash (/) und dem NUL-Zeichen alle Zeichen erlaubt. Trotzdem ist es empfehlenswert, folgende Zeichen nicht in Dateinamen zu verwenden, um Konflikte mit den Metazeichen der Shells zu vermeiden: ? @ # $ ^ & * ( ) ` [ ] \ | ' " < > Leerzeichen Tabulatorzeichen Auch sollte als erstes Zeichen eines Dateinamens nicht +, - oder . benutzt werden. Whrend auf lteren Unix-Systemen die Lnge von Dateinamen auf 14 Zeichen begrenzt war, wurde in neueren Unix-Systemen diese Grenze erheblich hochgesetzt (z.B. auf 255 Zeichen).

1.2.6

Dateisystem

Das Unix-Dateisystem (file system) ist hierarchisch in Form eines nach unten wachsenden Baumes aufgebaut. Die Wurzel dieses Baums ist das sogenannte Root-Directory, das einen Slash (/) als Namen hat. Bei jedem Arbeiten unter Unix befindet man sich an einem bestimmten Ort im Dateibaum. Jeder Benutzer wird nach dem Anmelden an einer ganz bestimmten Stelle innerhalb des Dateibaums positioniert. Von dieser Ausgangsposition kann er sich nun durch den Dateibaum hangeln", solange er nicht durch Zugriffsrechte vom Betreten bestimmter ste abgehalten wird. Nachfolgend sind die gebruchlichsten Begriffe aus dem Dateisystem-Vokabular aufgezhlt.

1.2.7

Root-Directory

Das Root-Directory (Root-Verzeichnis) ist die Wurzel des Dateisystems und enthlt kein bergeordnetes Directory mehr. Im Root-Directory entspricht der Name .. (Punkt, Punkt) dem Namen . (Punkt), so da das Parent-Directory zum Root-Directory wieder das Root-Directory selbst ist.

1.2.8

Working-Directory

Das Working-Directory (Arbeitsverzeichnis) ist der momentane Aufenthaltsort im Dateibaum. Mit dem Kommando pwd kann der aktuelle Aufenthaltsort (Working-Directory) am Bildschirm ausgegeben, und mit dem Kommando cd gewechselt werden in ein neues Working-Directory.

14

1

berblick ber die Unix-Systemprogrammierung

1.2.9

Home-Directory

Jeder eingetragene Systembenutzer hat einen eindeutigen und von ihm allein verwaltbaren Platz im Dateisystem: sein Home-Directory (Home-Verzeichnis). Der Pfadname des Home-Directorys steht in der betreffenden Benutzerzeile in der Datei /etc/passwd. Wird das Kommando cd ohne Angabe eines Directory-Namens abgegeben, so wird immer zum Home-Directory gewechselt.

1.2.10 Parent-DirectoryDas Parent-Directory (Elternverzeichnis) ist das Directory, das in der Dateihierarchie unmittelbar ber einem Directory angeordnet ist. Zum Beispiel ist /user1 das ParentDirectory zum Directory /user1/fritz. Eine Ausnahme gibt es dabei: Das Parent-Directory zum Root-Directory ist das Root-Directory selbst.

1.2.11 PfadnamenJede Datei und jedes Directory im Dateisystem ist durch einen eindeutigen Pfadnamen gekennzeichnet. Man unterscheidet zwei Arten von Pfadnamen: absoluter Pfadname Hierbei wird, beginnend mit dem Root-Directory, ein Pfad durch den Dateibaum zum entsprechenden Directory oder zur Datei angegeben. Ein absoluter Pfadname ist dadurch gekennzeichnet, da er mit einem Slash (/) beginnt. Der erste Slash ist die Wurzel des Dateibaums, alle weiteren stellen die Trennzeichen bei jeden Abstieg um eine Ebene im Dateibaum dar. relativer Pfadname Die Angabe eines solchen Pfadnamens beginnt nicht in der Wurzel des Dateibaums, sondern im Working-Directory. Anders als beim absoluten Pfadnamen ist das erste Zeichen hier kein Slash: Hier erfolgt also die Orientierung relativ zum momentanen Aufenthaltsort (Working-Directory). Ein relativer Pfadname beginnt immer mit einer der folgenden Angaben: einem Directory- oder Dateinamen . (Punkt): Kurzform fr das Working-directory .. (Punkt,Punkt): Kurzform fr das Parent-DirectoryBeispiel

Absolute und relative Pfadnamen Angenommen, das Working-Directory sei /user1/herbert, dann wrde der relative Pfadname briefe/finanzamt dem absoluten Pfadnamen /user1/herbert/briefe/ finanzamt entsprechen.

1.2

Dateien und Directories

15

Angenommen, das Working-Directory sei /user1/herbert, dann wrde der relative Pfadname ./briefe/finanzamt dem absoluten Pfadnamen /user1/herbert/briefe/ finanzamt entsprechen. Angenommen, das Working-Directory sei /user1/herbert, dann wrde der relative Pfadname ../../bin/sort dem absoluten Pfadnamen /bin/sort entsprechen.Beispiel

Ausgeben der Dateien eines Directorys#include #include #include #include "eighdr.h"

int main(int argc, char *argv[]) { char dir_name[MAX_ZEICHEN]; /* MAX_ZEICHEN ist in eighdr.h def. */ DIR *dir; struct dirent *dir_info; if (argc > 2) fehler_meld(FATAL, "Es ist nur ein Argument (Directory-Name) erlaubt"); else if (argc==2) strcpy(dir_name, argv[1]); else strcpy(dir_name, "."); /* working directory */ if ( (dir = opendir(dir_name)) == NULL) fehler_meld(FATAL_SYS, "kann %s nicht eroeffnen", dir_name); while ( (dir_info = readdir(dir)) != NULL) printf("%s\n", dir_info->d_name); closedir(dir); exit(0); }

Programm 1.1 (meinls.c): Alle Dateien eines Directorys ausgeben

Wenn wir dieses Programm 1.1 (meinls.c) wie folgt kompilieren und linken:cc -o meinls meinls.c fehler.c [unter Linux eventuell: gcc -o ...]

dann liefert es beim Aufruf z.B. folgende Ausgaben:$ meinls /usr/include . .. alloca.h ctype.h

16

1

berblick ber die Unix-Systemprogrammierung

curses.h dirent.h errno.h ............ ............ fcntl.h ftw.h getopt.h stdio.h signal.h stdlib.h string.h $ meinls /dev/console kann /dev/console nicht eroeffnen: Not a directory $ meinls /usr /tmp Es ist nur ein Argument (Directory-Name) erlaubt $ meinls /ect kann /ect nicht eroeffnen: No such file or directory $ meinls [Ausgeben der Dateien des Working-Directory] . .. copy1.c copy2.c meinls.c numer1.c procid.c zaehlen.c eighdr.h fehler.c meinls $

In diesem Programm 1.1 (meinls.c) wird mit#include "eighdr.h"

unsere eigene Headerdatei eighdr.h zum Bestandteil dieses Programms gemacht. Diese Headerdatei wird in nahezu jedes Programm der spteren Kapitel eingefgt, also included". Die Headerdatei eighdr.h included zum einen einige fr die Systemprogrammierung hufig bentigte Headerdateien, zum anderen definiert sie zahlreiche Konstanten und Prototypen von eigenen Funktionen (wie Fehlerroutinen), die in den Beispielen dieses und spterer Kapitel benutzt werden. Das Listing zu der Headerdatei eighdr.h befindet sich im Anhang. Falls beim Programm 1.1 (meinls.c) auf der Kommandozeile ein Directory-Name angegeben wurde, so befindet sich dieser in argv[1]. Wurde auf der Kommandozeile keinerlei Argument angegeben, so nimmt das Programm als Default (Voreinstellung) das Working-Directory (.) an. Fr den Fall, da dieses Programm mit mehr als einem Argument aufgerufen wird, ruft es die Fehlerroutine fehler_meld auf. Bei fehler_meld handelt es sich um eine eigene Fehlerroutine aus dem Modul fehler.c, dessen Listing sich ebenfalls im Anhang befindet. Das erste Argument legt dabei fest, wie

1.3

Ein- und Ausgabe

17

der entsprechende Fehler zu behandeln ist. Es sind die folgenden in eighdr.h definierten Konstanten als erstes Argument erlaubt:WARNUNG WARNUNG_SYS FATAL FATAL_SYS DUMP

Es wurde dabei die folgende Regelung bei der Vergabe der Konstantennamen gewhlt: Die Endung SYS bedeutet, da zustzlich zur eigenen Meldung noch die zum entsprechenden Fehler gehrige System-Fehlermeldung auszugeben ist. Nur bei den WARNUNG-Konstanten bewirkt die Fehlerroutine nicht die Beendigung des gesamten Programms. Bei Angabe der FATAL- und DUMP-Konstanten bewirkt die Fehlerroutine einen Programmabbruch. Nur bei der DUMP-Konstante wird mittels abort das Programm beendet und ein core dump (Speicherabzug) erzeugt. Bei FATAL und FATAL_SYS wird das Programm mit exit(1) beendet. Die weiteren Argumente zu fehler_meld entsprechen denen eines printf-Aufrufs. Der Aufruf von opendir bewirkt das ffnen des betreffenden Directorys und liefert einen DIR-Zeiger zurck. Unter Verwendung dieses DIR-Zeigers liest nun readdir in einer Schleife jeden Eintrag im entsprechenden Directory, wobei es entweder einen Zeiger auf die dirent-Struktur oder einen NULL-Zeiger (am Ende) liefert. Die dirent-Struktur enthlt fr jeden Directory-Eintrag in der Komponente d_name dessen Name. closedir schliet dann wieder das geffnete Directory. Um das Programm zu beenden, wird die Funktion exit aufgerufen. Der Wert 0 zeigt an, da das Programm fehlerfrei ausgefhrt wurde. Liefert dagegen ein Programm als exitStatus einen Wert zwischen 1 und 255, so deutet dies blicherweise auf das Auftreten eines Fehlers bei der Ausfhrung dieses Programms hin. Es ist anzumerken, da das Programm meinls die Namen in einem Directory nicht (wie ls) alphabetisch auflistet, sondern entsprechend der Reihenfolge, in der sie in der Directory-Datei eingetragen sind.

1.31.3.1

Ein- und AusgabeFiledeskriptoren

Wenn eine Datei geffnet wird, dann wird dieser Datei vom Betriebssystemkern eine nichtnegative ganze Zahl (0, 1, 2, 3 ...), der sogenannte Filedeskriptor zugewiesen. Unter Angabe dieses Filedeskriptors kann das Benutzerprogramm unter Verwendung der entsprechenden Systemroutinen in die geffnete Datei schreiben oder aus ihr lesen.

18

1

berblick ber die Unix-Systemprogrammierung

1.3.2

Standardeingabe, Standardausgabe, Standardfehlerausgabe

Wird ein Programm gestartet, so ffnet die Shell fr dieses Programm immer automatisch drei Filedeskriptoren:Standardeingabe (standard input) Standardausgabe (standard output) Standardfehlerausgabe (standard error)

Die Filedeskriptor-Nummern fr diese drei Dateien sind blicherweise 0, 1 und 2. Anstelle dieser Nummern sollte man allerdings in Systemen, die den POSIX-Standard erfllen, folgende Konstanten aus der Headerdatei benutzen:STDIN_FILENO (blicherweise 0) STDOUT_FILENO (blicherweise 1) STDERR_FILENO (blicherweise 2)

Normalerweise sind alle diese drei Filedeskriptoren auf das Terminal eingestellt. So erwartet z.B. der einfache Aufrufcat

Eingaben von der Tastatur (bis Strg-D fr EOF), welche er wieder am Bildschirm ausgibt. Lenkt man dagegen die Standardausgabe um, wie z.B.cat >x.txt

dann werden alle von der Tastatur eingegebenen Zeilen nicht auf den Bildschirm, sondern in die Datei x.txt geschrieben.

1.3.3

Standard-E/A-Funktionen (aus )

Die Standard-E/A-Funktionen sind in der Headerdatei definiert. Im Gegensatz zu den nachfolgend vorgestellten elementaren E/A-Funktionen arbeiten diese Funktionen mit eigenen Puffern, so da sich der Aufrufer darum (Definition eines eigenen Puffers mit selbstgewhlter Puffergre) nicht eigens kmmern mu. Auch bieten die Standard-E/A-Funktionen dem Benutzer mehr Komfort an, wie z.B. Formatierung der Ausgabe bei printf oder zeilenweises Einlesen bei fgets.Beispiel

Kopieren von Standardeingabe auf Standardausgabe#include "eighdr.h"

int main(void) { int zeich;

1.3

Ein- und Ausgabewhile ( (zeich=getc(stdin)) != EOF) if (putc(zeich, stdout) == EOF) fehler_meld(FATAL_SYS, "Fehler bei putc"); if (ferror(stdin)) fehler_meld(FATAL_SYS, "Fehler bei getc"); exit(0);

19

}

Programm 1.2 (copy1.c): Standardeingabe auf Standardausgabe kopieren

Die Funktion getc liest immer ein Zeichen von der Standardeingabe (stdin), das dann mit putc auf die Standardausgabe (stdout) geschrieben wird. Wenn das letzte Byte gelesen wird oder ein Fehler beim Lesen auftritt, liefert getc als Rckgabewert die Konstante EOF. Um festzustellen, ob ein Fehler beim Lesen aufgetreten ist, wird die Funktion ferror aufgerufen. Anders als die elementaren E/A-Funktionen wird beim ffnen einer Datei mit den Standard-E/A-Funktionen nicht ein Filedeskriptor, sondern ein FILE-Zeiger zurckgeliefert. Der Datentyp FILE ist eine Struktur, die alle Informationen enthlt, die von den entsprechenden Standard-E/A-Routinen beim Umgang mit der betreffenden Datei bentigt werden. Wird ein Programm gestartet, so werden fr dieses Programm immer automatisch drei FILE-Zeiger geffnet:stdin (Standardeingabe) stdout (Standardausgabe) stderr (Standardfehlerausgabe)

Wenn wir dieses Programm 1.2 (copy1.c) nun kompilieren und linkencc -o copy1 copy1.c fehler.c

und dann aufrufen, so liest es immer aus der Standardeingabe (bis EOF bzw. Strg-D) und schreibt die gelesenen Zeichen wieder auf die Standardausgabe. Es ist allerdings auch mglich, die Standardeingabe und/oder Standardausgabe umzulenken, wie z.B.:copy1 a.c copy1 datei2 [gibt Datei liste am Bildschirm aus] [schreibt alle ber Tastatur eingegeb. Daten in Datei a.c] [kopiert datei1 nach datei2]

Um weitere Dateien zu ffnen, steht die Funktion fopen zur Verfgung, der als erstes Argument der Name der zu ffnenden Datei zu bergeben ist. Als zweites Argument ist bei dieser Funktion anzugeben, was man nach dem ffnen mit dieser Datei zu tun wnscht, wie z.B. r fr Lesen oder w fr Schreiben.

20

1

berblick ber die Unix-Systemprogrammierung

Beispiel

Ausgeben einer Datei mit Zeilennumerierung#include "eighdr.h" 200

#define MAX_ZEILLAENG

int main(int argc, char *argv[]) { FILE *fz; char zeile[MAX_ZEILLAENG]; int zeilnr=0; if (argc != 2) fehler_meld(FATAL, "usage: %s dateiname", argv[0]); if ( (fz=fopen(argv[1], "r")) == NULL) fehler_meld(FATAL_SYS, "Kann %s nicht eroeffnen", argv[1]); while (fgets(zeile, MAX_ZEILLAENG, fz) != NULL) fprintf(stdout, "%5d %s", ++zeilnr, zeile); if (ferror(fz)) fehler_meld(FATAL_SYS, "Fehler beim Lesen aus %s", argv[1]); fclose(fz); exit(0); }

Programm 1.3 (numer1.c): Datei mit Zeilennumerierung auf Standardausgabe ausgeben

Dieses Programm 1.3 (numer1.c) liest mit fgets Zeile fr Zeile ein, wobei vorausgesetzt wird, da eine Zeile maximal 200 Zeichen lang ist. Jede gelesene Zeile wird mit Zeilennummer mittels fprintf auf die Standardausgabe (stdout) ausgegeben.

1.3.4

Elementare E/A-Funktionen (aus )

Elementare E/A-Funktionen sind in der Headerdatei deklariert. Wichtige elementare E/A-Funktionen sind z.B.:open read write lseek close (ffnen einer Datei; liefert entsprechenden Filedeskriptor) (Lesen aus einer geffneten Datei) (Schreiben in eine geffnete Datei) (Positionieren des Schreib-/Lesezeigers in geffneter Datei) (Schlieen einer geffneten Datei)

Alle diese elementaren E/A-Funktionen benutzen den von open gelieferten Filedeskriptor.

1.4

Prozesse unter Unix

21

Beispiel

Kopieren von Standardeingabe auf Standardausgabe#include "eighdr.h"

#define PUFF_GROESSE 1024 int main(void) { int n; char puffer[PUFF_GROESSE]; while ( (n=read(STDIN_FILENO, puffer, PUFF_GROESSE)) > 0) if (write(STDOUT_FILENO, puffer, n) != n) fehler_meld(FATAL_SYS, "Fehler bei write"); if (n0 (im Elternproze; pid ist dann die PID des Kindprozesses) pid=-1 (fork war nicht erfolgreich)

Da ein Kindproze in der Regel einen anderen Programmteil ausfhren soll als der Elternproze, kann ber diesen Rckgabewert gesteuert werden, welcher Programmteil vom Kind- und welcher vom Elternproze auszufhren ist. Im obigen Programm 1.6 (zaehlen.c) wird mit fork ein Kindproze gestartet, der eine Kopie des Code-, Daten- und Stacksegmentes des Elternprozesses enthlt; d.h., da er z.B. den momentanen Wert der Variablen z erbt. Auch bernimmt dieser Kindproze den Wert des Befehlszhlers vom Elternproze. Somit fhrt er zwar an der gleichen Programmstelle (nach fork-Aufruf) fort, an der er aufgerufen wurde, aber und das ist wichtig mit seinem eigenem Befehlszhler (instruction pointer) fr das Codesegment und mit seinem eigenen Daten- und Stacksegment (siehe Abbildung 1.1).

1.4

Prozesse unter Unix

25

Textsegment if (... fork() ....)

IP(Instruction Pointer)

Datensegment

e pi Ko es ne ss ei ze lt el ro st np er ter rk El fo e s d

Stacksegment z 1

E/A-Gerte

Beide Prozesse konkurrieren um die Betriebsmittel

Datensegment

IP

Hauptspeicher CPU

Stacksegment z 1

Abbildung 1.1: Kreieren eines Kindprozesses mit fork

Beide Prozesse konkurrieren nun um die Betriebsmittel (CPU, Hauptspeicher usw.). Um die Ausgabe des Kindprozesses von der des Elternprozesses unterscheiden zu knnen, erfolgen in zaehlen.c die Ausgaben des Elternprozesses am linken und die des Kindprozesses am rechten Bildschirmrand. Nachdem man das Programm 1.6 (zaehlen.c) kompiliert und gelinkt hatcc -o zaehlen zaehlen.c fehler.c

kann ein Aufruf von zaehlen z.B. die folgende Ausgabe liefern.$ zaehlen Eltern- und Kindprozess zaehlen um die Wette: Vater: Ich beginne zu zaehlen Kind: Ich beginne zu zaehlen Kind: Ich bin schon bei 100000 Vater: 200000 und rede nicht soviel! Kind: Ich bin schon bei 200000 Kind: Ich bin schon bei 300000 Vater: 400000 und rede nicht soviel! Kind: Ich bin schon bei 400000 Kind: Ich bin schon bei 500000 Vater: 600000 und rede nicht soviel! Kind: Ich bin schon bei 600000 Kind: Ich bin schon bei 700000

26Vater: 800000 und rede nicht soviel!

1

berblick ber die Unix-Systemprogrammierung

Kind: Ich bin schon bei 800000 Kind: Ich bin schon bei 900000 Vater: 1000000 und rede nicht soviel! Kind: Ich bin schon bei 1000000 z(Kind) = 1000001 ----> z = 1000001 Vater: 1200000 und rede nicht soviel! z(Vater) = 1200001 ----> z = 1200001 $

Bei dieser Ausgabe ist zu erkennen, da beiden Prozessen abwechselnd die Betriebsmittel (CPU, E/A-Gerte usw.), um die sie konkurrieren, zugeteilt werden. Auch ist an der Ausgabe zu erkennen, da der Kindproze bei seiner Erzeugung die Variable z (und ihren Wert) erbt. Da diese lokale Variable allerdings in sein eigenes Stacksegment kopiert wird, ist z ab diesem Zeitpunkt eine eigene Variable des Kindprozesses, d.h., da ein Verndern von z durch den Kindproze keinerlei Einflu auf das z des Elternprozesses hat. Ein weiterer interessanter Aspekt, der an dieser Ausgabe zu erkennen ist, ist die Tatsache, da beide Prozesse nach Beendigung ihres entsprechenden Programmteils (in der ifAnweisung) mit dem Programm nach der if-Anweisung fortfahren. In diesem Programmteil wird nur noch der jeweilige Wert von z ausgegeben:----> z = 1000001 ----> z = 1200001 (Kindproze) (Elternproze)

1.5

Ausgabe von System-Fehlermeldungen

Wenn bei der Ausfhrung einer Systemfunktion ein Fehler auftritt, so liefern viele Systemfunktionen -1 als Rckgabewert und setzen zustzlich die Variable errno auf einen von 0 verschiedenen Wert. Diese Variable errno ist in mitextern int errno;

definiert. Zustzlich zu dieser Definition der Variablen errno definiert Konstanten fr jeden Wert, der errno von den Systemfunktionen zugewiesen werden kann. Jede dieser Konstanten beginnt mit dem Buchstaben E (fr Error). In den Unix-Manpages sind unter intro(2) alle in definierten Konstanten zusammengefat. Bezglich der Verwendung der Variablen errno ist folgendes zu beachten. ANSI C garantiert nur fr den Programmstart, da die Variable errno auf 0 gesetzt wird. Die Systemfunktionen setzen niemals diese Variable zurck auf 0, und es gibt in keine Fehlerkonstante mit dem Wert 0.

1.5

Ausgabe von System-Fehlermeldungen

27

Deshalb ist es gngige Praxis, da man errno vor dem Aufruf einer Systemfunktion explizit auf 0 setzt und nach dem Aufruf dieser Funktion den Wert von errno berprft, um festzustellen, ob whrend der Ausfhrung dieser Funktion ein Fehler aufgetreten ist. Um die Fehlermeldung zu erhalten, die zu einem in errno stehenden Fehlercode gehrt, schreibt ANSI C die beiden Funktionen perror und strerror vor.

1.5.1

perror Ausgabe der zu errno gehrenden Fehlermeldung

Die Funktion perror gibt auf stderr die zum momentan in errno stehenden Fehlercode gehrende Fehlermeldung aus.:

#include void perror(const char *meldung);

Diese errno-Fehlermeldung entspricht genau dem Rckgabewert der nachfolgend beschriebenen Funktion strerror, falls diese mit dem gleichen errno-Wert als Argument aufgerufen wird.

1.5.2

strerror Erfragen der zu einer Fehlernummer gehrigen Meldung

Die Funktion strerror (in definiert) liefert die zu einer Fehlernummer (blicherweise der errno-Wert) gehrende Meldung als Rckgabewert.:

#include char *strerror(int fehler_nr);gibt zurck: Zeiger auf die entsprechende Fehlermeldung

Die beiden folgenden Anweisungen liefern das gleiche Ergebnis:perror("testausgabe") fprintf(stderr, "testausgabe: %s\n", strerror(errno));Beispiel

Demonstrationsbeispiel zu perror und strerror#include #include #include int main(void) { "eighdr.h" /* da globale Variable errno verwendet wird */

28int fehler_nr=0;

1

berblick ber die Unix-Systemprogrammierung

for (fehler_nr=0 ; fehler_nr strerror: perror : 1 -> strerror: perror : 2 -> strerror: perror : 3 -> strerror: perror : 4 -> strerror: perror : $ Unknown error Unknown error Operation not permitted Operation not permitted No such file or directory No such file or directory No such process No such process Interrupted system call Interrupted system call

In den spteren Beispielprogrammen dieses Buches wird jedoch weder perror noch strerror direkt aufgerufen. Statt dessen wird dort die eigene Fehlerroutine fehler_meld aus dem Programm fehler.c, dessen Listing sich im Anhang befindet, aufgerufen.

1.61.6.1

BenutzerkennungenUser-ID

Zu jedem Benutzer existiert in der Pawortdatei eine eindeutige Kennung in Form einer Nummer. Diese Nummer, die dem Benutzer vom Systemadministrator beim Einrichten seines Loginnamens zugeteilt wird, bezeichnet man als User-ID. 0 ist die User-ID des besonders privilegierten Superusers, dessen Loginname meist root ist. Ein Superuser hat alle Rechte im System, whrend die Rechte von normalen Benutzern meist sehr eingeschrnkt sind.

1.7

Signale

29

1.6.2

Group-ID

Jeder Benutzer ist einer Gruppe und jeder Gruppe ist eine eindeutige Kennung in Form einer Nummer zugeordnet. Diese Nummer, die dem Benutzer vom Systemadministrator ebenfalls beim Einrichten seines Loginnamens zugeteilt wird, bezeichnet man als GroupID. Die Group-ID eines Benutzers befindet sich auch im entsprechenden PawortdateiEintrag eines Benutzers. Da mehrere Benutzer zu einer Gruppe gehren knnen, was der Normalfall ist, knnen natrlich auch mehrere Benutzer die gleiche Group-ID besitzen. Die Zuordnung von Gruppennamen zu Group-IDs befindet sich in der Datei /etc/group.Beispiel

Ausgeben der User-ID und Group-ID eines Benutzers Das folgende Programm 1.8 (usergrup.c) gibt unter Verwendung der beiden Funktionen getuid und getgid die User- und Group-ID des aufrufenden Benutzers aus.#include "eighdr.h"

int main(void) { printf("uid = %d\n" "gid = %d\n", getuid(), getgid()); exit(0); }

Programm 1.8 (usergrup.c): Ausgeben der User-ID und Group-ID

Nachdem man das Programm 1.8 (usergrup.c) kompiliert und gelinkt hatcc -o usergrup usergrup.c

kann sich z.B. folgender Ablauf ergeben:$ usergrup uid = 2021 gid = 5 $

1.7

Signale

Signale sind asynchrone Ereignisse, die erzeugt werden, wenn whrend einer Programmausfhrung besondere Ereignisse eintreten. So wird z.B. bei einer Division durch 0 dem entsprechenden Proze das Signal SIGFPE (FPE=floating point error) geschickt. Ein Proze hat drei verschiedene Mglichkeiten, auf das Eintreffen eines Signals zu reagieren:

30

1

berblick ber die Unix-Systemprogrammierung

1. Ignorieren des SignalsDies ist nicht fr Signale empfehlenswert, die einen Hardwarefehler (wie Division durch 0 oder Zugriff auf unerlaubte Speicherbereiche) anzeigen, da der weitere Ablauf eines solchen Prozesses zu nicht vorhersagbaren Ergebnissen fhren kann.

2. Voreingestellte ReaktionFr jedes mgliche Signal ist eine bestimmte Reaktion festgelegt. So ist z.B. die voreingestellte Reaktion auf das Signal SIGFPE die Beendigung des entsprechenden Prozesses. Trifft ein Benutzer keine besonderen Vorrichtungen fr das Eintreffen eines Signals, so ist die voreingestellte Reaktion (meist Beendigung des Prozesses) fr dieses Signals eingerichtet.

3. Ausfhren einer eigenen FunktionFr jedes Signal kann ein Proze auch seine eigene Reaktion festlegen. Dazu mu er mit der Funktion signal sogenannte Signalhandler (Funktionen) einrichten. Bei Eintreffen der entsprechenden Signale werden dann automatisch diese eingerichteten Signalhandler ausgefhrt. Mit solchen Funktionen kann somit der Proze seine eigene Reaktion auf das Eintreffen eines bestimmten Signals festlegen.Beispiel

Einrichten eines eigenen Signalhandlers Das folgende Programm 1.9 (sighandl.c) demonstriert, wie man sich mit der Funktion signal einen eigenen Signalhandler einrichten kann.#include #include #include #include static int "eighdr.h" intr_aufgetreten = 0;

/*----------- sig_intr ----------------------------------------------*/ void sig_intr(int signr) { printf("Du willst das Programm abbrechen?\n"); printf("Noch nicht ganz, du must noch ein bisschen warten\n"); sleep(5); /* 5 Sekunden warten, bevor Programm fortgesetzt wird */ intr_aufgetreten = 1; } /*----------- main --------------------------------------------------*/ int main(void) { int a = 0;

1.7

Signaleprintf("Programmstart\n"); if (signal(SIGINT, sig_intr) == SIG_ERR) fehler_meld(FATAL_SYS, "kann Signalhandler sig_intr nicht einrichten"); while (intr_aufgetreten == 0) /* Endlosschleife: Warten auf das */ ; /* Eintreffen des interrupt-Signals */ printf("Schleife verlassen\n"); printf("%d\n", 2/a); printf("----- Fertig -----\n"); exit(0);

31

}

Programm 1.9 (sighandl.c): Einrichten eines eigenen Signalhandlers

Nachdem man das Programm 1.9 (sighandl.c) kompiliert und gelinkt hatcc -o sighandl sighandl.c fehler.c

kann sich z.B. folgender Ablauf ergeben:$ sighandl Programmstart Strg-C [Drcken der Interrupt-Taste] Du willst das Programm abbrechen? Noch nicht ganz, du must noch ein bisschen warten Schleife verlassen Floating exception $

In dem Programm 1.9 (sighandl.c) wird ein Signalhandler sig_intr zum Signal SIGINT eingerichtet. Das Signal SIGINT wird geschickt, wenn der Benutzer die Interrupt-Taste (meist Strg-C oder DELETE) drckt. Das Programm 1.9 (sighandl.c) begibt sich nach dem Einrichten des Signalhandlers in eine Endlosschleife. Drckt der Aufrufer dann irgendwann die Interrupt-Taste, so wird die Funktion sig_intr angesprungen, die zunchst etwas Text ausgibt, bevor sie mit sleep(5) die Ausfhrung des Programms fr fnf Sekunden anhlt. Danach setzt sie die globale Variable intr_aufgetreten auf 1, was dazu fhrt, da nach Beendigung der Funktion sig_intr die Schleife beendet und das durch Ausgabe eines entsprechenden Textes dem Benutzer mitteilt. Die darauffolgende Division durch 0 (Signal SIGFPE) bewirkt allerdings, da die voreingestellte Reaktion auf das Signal SIGFPE aktiviert wird, da fr dieses Signal kein eigener Signalhandler eingerichtet wurde. Die voreingestellte Reaktion auf das Signal SIGFPE ist die Beendigung des Programms, so da die letzte printf-Anweisung (printf("----- Fertig -----\n")) nicht mehr ausgefhrt wird, sondern das Programm vorzeitig mit der Meldung Floating exception vom System beendet wird.

32

1

berblick ber die Unix-Systemprogrammierung

1.81.8.1

Zeiten in UnixKalenderzeit und CPU-Zeit

Unix unterscheidet zwischen zwei Zeiten:

1. KalenderzeitDiese Zeit wird im Systemkern als die Anzahl der Sekunden dargestellt, die seit 00:00:00 Uhr des 1. Januars 1970 (UTC4) vergangen sind. Diese Kalenderzeit, die immer im Datentyp time_t dargestellt wird, benutzt z.B. das Kommando date zur Ausgabe der aktuellen Datums- und Zeitwerte. Ebenso wird diese Zeit fr die Eintrge der Zeitmarken bei Dateien (z.B. letzte Zugriffs- oder Modifikationszeit) verwendet.

2. CPU-ZeitDiese Zeit gibt an, wie lange ein bestimmter Proze die CPU benutzte. Die CPU-Zeit wird anders als die Kalenderzeit nicht in Sekunden, sondern in sogenannten clock ticks ("Uhr-Ticks") pro Sekunde gemessen. Ein typischer Wert fr clock ticks pro Sekunde ist z.B. 50 oder 100. Seit ANSI C ist dieser Wert in der Konstante CLOCKS_PER_SEC in der Headerdatei definiert, whrend frher die Konstante CLK_TCK; diesen Wert definierte. Die CPU-Zeit wird immer im Datentyp clock_t dargestellt.

1.8.2

Prozezeiten

Fr einen Proze unterhlt der Kern drei Zeitwerte: abgelaufene Uhrzeit seit Start Benutzer-CPU-Zeit System-CPU-Zeit Die abgelaufene Uhrzeit ist die Zeit, die seit dem Start eines Prozesses vergangen ist. Je mehr Prozesse gleichzeitig im System ablaufen, um so lnger dauert die Ausfhrung eines Prozesses und um so grer wird dieser Wert sein. Die Benutzer-CPU-Zeit ist die Zeit, die ein Proze die CPU zur Ausfhrung von Benutzeranweisungen beansprucht. Die System-CPU-Zeit ist die Zeit, die ein Proze die CPU zur Ausfhrung von Kernroutinen beansprucht. Die Summe aus Benutzer-CPU- und SystemCPU-Zeit bezeichnet man blicherweise als CPU-Zeit. Um die von einem Programm verbrauchte Uhrzeit, Benutzer-CPU- und System-CPU-Zeit zu erfahren, mu man der entsprechenden Kommandozeile nur das Kommando time voranstellen, wie z.B.:

4. Abkrzung fr Universal Time Coordinated, die der GMT (Greenwich Mean Time) entspricht.

1.9

Unterschiede zwischen Systemaufrufen und Bibliotheksfunktionen

33

$ time find / -name "*.h" -print ............. ............. 1.54user 9.42system 1:06.34elapsed 16%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (0major+0minor)pagefaults 0swaps $

Das Ausgabeformat des time-Kommandos ist von der benutzten Shell abhngig.

1.9

Unterschiede zwischen Systemaufrufen und Bibliotheksfunktionen

Obwohl in den spteren Kapiteln immer nur von Funktionen gesprochen wird, soll hier darauf hingewiesen werden, da es zwei verschiedene Arten von Funktionen gibt: Systemaufrufe und Bibliotheksfunktionen. Nachfolgend werden die Unterschiede zwischen diesen beiden Arten von Funktionen vorgestellt.

1.9.1

Systemaufrufe sind Systemkern-Schnittstellen

Die Systemaufrufe sind die Schnittstellen zum Kern. Sie sind in Section 2 des Unix Programmer's Manual beschrieben, wo sie in Form von C-Funktionsdeklarationen angegeben sind. Alle diese Systemfunktionen befinden sich ebenso wie die nachfolgend beschriebenen Bibliotheksfunktionen in der C-Standardbibliothek, so da aus Benutzersicht kein Unterschied zwischen diesen beiden Funktionsarten besteht. Beim Aufruf von Systemfunktionen wird aber anders als bei den Bibliotheksfunktionen Systemkern-Code ausgefhrt.

1.9.2

Bibliotheksfunktionen sind keine Schnittstellen zum Kern

Die Bibliotheksfunktionen, die in Section 3 des Unix Programmer's Manual beschrieben sind, stellen anders als die Systemfunktionen keine Schnittstellen zum Systemkern dar, wenn auch einige Bibliotheksfunktionen eine oder mehrere Systemfunktionen ihrerseits aufrufen. So ruft z.B. die Bibliotheksfunktion printf zur Ausgabe die Systemfunktion write auf. Andere Bibliotheksfunktionen dagegen, wie z.B. strlen (ermittelt Lnge eines Strings) oder sqrt (berechnet Quadratwurzel), kommen ohne jeglichen Aufruf einer Systemfunktion aus. Whrend Bibliotheksfunktionen leicht durch neue ersetzt werden knnen, knnen Systemfunktionen nicht so einfach ausgetauscht werden. Im letzteren Fall wre eine nderung des Kerns notwendig. Abbildung 1.2 verdeutlicht noch einmal, da ein Benutzerprogramm sowohl Systemfunktionen als auch Bibliotheksfunktionen aufrufen kann. Zudem zeigt Abbildung 1.2, da einige Bibliotheksfunktionen ihrerseits Systemfunktionen aufrufen.

34

1

berblick ber die Unix-Systemprogrammierung

Benutzer-Code

Bibliotheksfunktionen

Benutzerproze

Systemaufrufe

Systemkern

Abbildung 1.2: Beziehungen zwischen Anwenderprogrammen, Bibliotheksfunktionen und SystemaufrufenBeispiel

Systemaufruf time und Bibliotheksfunktionen aus Die Headerdatei enthlt Funktionen, die sich fr das Erfragen von Datums- und Zeitwerten eignen. Von diesen Funktionen ist die Funktion time ein Systemaufruf, whrend alle anderen Bibliotheksfunktionen sind. Die Systemfunktion time erfragt vom Kern die aktuelle Zeit und liefert diese als die Anzahl von Sekunden, die seit 00:00:00 Uhr am 1. Januar 1970 verstrichen sind. Die Interpretation der zurckgelieferten Sekundenzahl, wie z.B. die Konvertierung in ein verstndliches Datumsformat (wie z.B. Mon Jun 05 03:57:12 1995), ist Sache des Benutzerprozesses. Aber auch in sind Bibliotheksfunktionen vorhanden, die eine solche Konvertierung ermglichen, wie z.B. ctime (siehe auch Kapitel 7). Whrend also time ein Systemaufruf ist, der die Zeit direkt vom Kern erfragt, sind alle anderen Zeitfunktionen aus Bibliotheksfunktionen, die keinerlei Dienste vom Kern anfordern, sondern lediglich mit dem von time zurckgelieferten Wert arbeiten (siehe Abbildung 1.3).

Benutzer-Code Benutzer-DatenSekunden

Bibliotheksfunktionen

Benutzerproze

ctime

time

Systemaufrufe

Systemkern

Abbildung 1.3: Systemaufruf time und Bibliotheksfunktionen zur Interpretation des Zeitwertes

1.10

Unix-Standardisierungen und -Implementierungen

35

1.10 Unix-Standardisierungen und -ImplementierungenWhrend der achtziger Jahre wurden groe Anstrengungen unternommen, Unix zu standardisieren. Im Laufe der Jahre hatte sich nmlich eine Vielzahl von unterschiedlichen Unix-Versionen herausgebildet. Um dieser Wucherung von Unix-Versionen mit ihren vielen kleinen Unterschieden Einhalt zu gebieten, wurde der Ruf nach einem Unix-Standard immer lauter. Hier werden die Standardisierungen und Implementierungen vorgestellt, auf die dieses Buch ausgerichtet ist.

1.10.1 Unix-StandardisierungenPOSIXDie Standardisierungsbestrebungen der amerikanischen Unix-Benutzergemeinde wurden 1986 vom amerikanischen Institute for Electrical and Electronic Engineers (IEEE) unter dem Namen POSIX (Portable Operating System Interface) aufgegriffen. POSIX ist nicht nur ein Standard, sondern eine ganze Familie von Standards. Der Standard IEEE POSIX 1003.1 fr die Betriebsystem-Schnittstellen wurde bereits 1988 verabschiedet. Weitere Standards, wie IEEE POSIX 1003.2 (Shells und Utilities), wurden im wesentlichen 1991/1992 abgeschlossen. An zahlreichen weiteren Standards wird momentan noch gearbeitet. Fr das vorliegende Buch ist insbesondere der Standard 1003.1 (System-Schnittstellen) von Wichtigkeit. Dieser Standard definiert die Dienste, die jedes Betriebssystem anbieten mu, wenn es vorgibt, die POSIX-1003.1-Forderungen zu erfllen. Die meisten heutigen Unix-Systeme gengen diesem POSIX.1-Standard. Der POSIX-Standard basiert zwar auf Unix, ist jedoch nicht nur auf Unix-Systeme begrenzt. Es existieren auch andere Betriebssysteme, die den POSIX-Standard erfllen. Ende 1990 wurde eine Revision des POSIX-1003.1-Standards durchgefhrt. Den dabei verabschiedeten Standard bezeichnet man allgemein als POSIX.1. 1992 wurden einige Erweiterungen dem 1990 verabschiedeten Standard hinzugefgt, woraus die Version 1003.1a von POSIX.1 resultierte.

X/Open XPG1984 grndeten 13 fhrende Computerhersteller, darunter AT&T, BULL, DEC, Ericson, Hewlett Packard, ICL, Nixdorf, Olivetti, Phillips, Siemens und Unisys, die sogenannte X/ Open-Gruppe mit dem Ziel, Industriestandards fr offene Systeme zu schaffen.

36

1

berblick ber die Unix-Systemprogrammierung

Ein wesentliches Ergebnis der Arbeit der X/Open-Gruppe war der sogenannte X/Open Portability Guide (XPG), dessen erste Ausgabe 1985 (XPG1) erschien. Die meisten heutigen Unix-Implementierungen untersttzen die 3. Ausgabe des XPG (XPG3), die 1988 herauskam, obwohl zwischenzeitlich eine neue Ausgabe (XPG4) existiert, die Mitte 1992 verabschiedet wurde. XPG4 wurde notwendig, da XPG3 nur auf einen Entwurf des ANSI-CStandards basierte, der erst 1989 mit einigen nderungen verabschiedet wurde.

ANSI CEnde 1989 wurde der ANSI5-Standard X3.159-1989 fr die Programmiersprache C verabschiedet. Dieser Standard wurde im Jahre 1990 auch als internationaler Standard ISO/ IEC 9899:1990 fr die Sprache C anerkannt. Der ANSI-C-Standard wird in Kapitel 2 ausfhrlicher beschrieben.

1.10.2 Unix-ImplementierungenWhrend Standardisierungen wie IEEE POSIX, X/Open XPG4, ANSI C von unabhngigen Organisationen durchgefhrt werden, werden die eigentlichen Unix-Implementierungen, die diesen gesetzten Standards mehr oder weniger gengen, von speziellen Computerfirmen vorgenommen. In diesem Buch wird auf drei wichtige Unix-Implementierungen eingegangen, die sich heute auf dem Markt befinden.

System V Release 4 (SVR4)System V Release 4 (SVR4) ist ein Produkt von USL (Unix System Laboratories) der Firma AT&T. SVR4 erfllt die beiden Standards POSIX 1003.1 und X/Open XPG3. AT&T verffentlichte 1984 ebenfalls die System V Interface Definition (SVID). 1986 brachte AT&T eine berarbeitete System V Interface Definition, Issue 2 (SVID-2) heraus, die im wesentlichen XPG3 prgte. SVID-2 lag System V Release 3 (SVR3) zugrunde. Die 3. Ausgabe des SVID (SVID-3), die die Kompatibilitt mit POSIX herstellte, war die Grundlage fr die Implementierung von SVR4. SVR4 enthlt auch eine sogenannte Berkeley Compatibility Library, die Funktionen und Kommandos enthlt, die sich wie unter 4.3BSD-Unix verhalten, was jedoch nicht immer dem POSIX-Standard entspricht. Deshalb sollte man bei neuen Applikationen von diesen Funktionen und Kommandos keinen Gebrauch machen.

BSD-UnixBSD (Berkeley Software Distribution) ist eine Unix-Linie, die an der UCB (University of California at Berkeley) entstanden ist und dort auch weiterentwickelt wird. Die Version 4.2BSD wurde 1983 und die Version 4.3BSD wurde 1986 freigegeben. Beide Versionen liefen auf einem VAX-Minicomputer. Inzwischen ist die Version 4.4BSD erschienen.

5. American National Standards Institute

1.10

Unix-Standardisierungen und -Implementierungen

37

LinuxLinux ist ein frei verfgbares Unix-System fr PCs, das sich heute sehr groer Beliebtheit erfreut. Es umfat Teile der Funktionalitt von SVR4, des POSIX-Standards und der BSDLinie. Wesentliche Teile des Unix-Kerns wurden von Linus Torvalds, einem finnischen Informatik-Studenten, entwickelt. Er stellte die Programmquellen des Kerns unter die GNU Public License. Somit hat jeder das Recht, sie zu kopieren. Die erste Version des Linux-Kerns war Ende 1991 im Internet verfgbar. Es bildete sich schnell eine Gruppe von Linux-Entwicklern, die die Entwicklung dieses Systems vorantrieben. Die Linux-Software wird unter offenen und verteilten Bedingungen entwickelt, was bedeutet, da jeder, der dazu in der Lage ist, sich beteiligen kann. Das Kommunikationsmedium der Linux-Entwickler ist das Internet. An entsprechenden Stellen wird in diesem Buch die Umsetzung von wichtigen Betriebssystemkonzepten und -algorithmen am System Linux gezeigt. Dieses System wurde nicht nur aufgrund seiner groen Beliebtheit hierfr ausgewhlt, sondern eben auch, weil Linux alle seine Quellprogramme der ffentlichkeit zur Verfgung stellt.

1.10.3 HeaderdateienDie Tabelle 1.1 gibt einen berblick darber, welche Headerdateien von den einzelnen Standards gefordert bzw. in den einzelnen Implementierungen angeboten werden. Bei der Kurzbeschreibung ist dabei in Klammern das Kapitel angegeben, in dem diese Headerdateien nher beschrieben werden.Standards Headerdatei x x x x x x x x x x ANSI C POSIX.1 XPG x x Implementierung SVR4 x x x x x x x x x x x x x x x BSD x Kurzbeschreibung Testmglichkeiten in einem Programm (2.4) cpio-Archivwerte Umwandlung/Klassifikation von Zeichen (2.4) Directory-Eintrge (5.9) Fehlerkonstanten (1.5) Elementare E/A-Operationen (4.2) Limits/Eigenheiten fr Gleitpunkt-Typen (2.4) Rekursives Durchlaufen eines Dir.-Baums (5.9) Gruppendatei (6.2)

Tabelle 1.1: Headerdateien in den einzelnen Standards und Implementierungen

38

1

berblick ber die Unix-Systemprogrammierung

Standards Headerdatei x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x ANSI C POSIX.1 XPG x

Implementierung SVR4 x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x BSD Kurzbeschreibung Sprachenspezifische Konstanten Implementierungskonstanten (1.11 und 2.4) Lnderspezifische Gegebenheiten (2.4) Mathemat. Konstanten/Funktionen (2.4) message-Kataloge Pawortdatei (6.1) Regulre Ausdrcke Suchtabellen Nichtlokale Sprnge (8) Signale (13) Variabel lange Argumentlisten (2.3) Standarddefinitionen (2.4) Standard-E/A