Hallo Ich wollte wissen, wie das OS grundsätzlich Programme lädt. Wenn z.B. bei einem Linuxrechner die GUI deaktiviert ist, sieht man nach dem Start die Shell. Das ist ja im Prinzip ein Programm (es gehört zwar zum OS, aber nicht zum Kernel). Aber wie wird die Shell geladen? Woher weiß das OS bzw. der Programloader des OS', an welcher Adresse in der HDD der Code zur Shell gespeichert ist? Gibt es da eine Tabelle, in der alle vorhandenen Programme inkl. Speicheradresse gelistet sind? Das bringt mich dann zur nächsten Frage: Wie kam der Code für die Shell zum ersten Mal in die HDD? Die wurde ja nicht samt dem Kernel mitkompliert, oder? Es wird ja nicht irgendwo im Kernelcode stehen: ... irg welche Initialisierungen... shell(); ... :D Das geht ja nicht, weil der Kernel ja die "Funktion" shell nicht kennt. Ich hoffe ihr versteht meine Frage. Das Problem ist (schriftlich) nicht so einfach zu erklären :P lg samuel
:
Bearbeitet durch User
Mir geht es nicht um Linux, sondern um die Theorie von Betriebssystemen.
Samuel J. schrieb: > Gibt es da eine Tabelle, in der > alle vorhandenen Programme inkl. Speicheradresse gelistet sind? Ja, nennt sich Directory oder dt. Inhaltsverzeichnis und ist genau das. Dahinter stecken noch andere Verwaltungen, wie Partitionstabellen, aber das Prinzip bleibt das gleiche. Samuel J. schrieb: > ... irg welche Initialisierungen... > shell(); Doch, nur das da nicht shell() steht, sondern 'init' bei Linux. 'init' ist die Mutter aller Prozesse. In init stehen dann so Sachen wie das Starten eines Terminals, was wiederum den 'login' Prozess startet, usw. Nach einem erfolgreichen Login wird dann die Shell gestartet.
:
Bearbeitet durch User
Samuel J. schrieb: > Ich wollte wissen, wie das OS grundsätzlich Programme lädt. Es gibt nicht "das OS". Man muss u.a. unterscheiden, ob das Betriebssystem und die Anwendungen schon zur Kompilierzeit gelinkt sind oder nicht. Bei sehr vielen RTOS für Microcontroller o.ä. ist dies durchaus der Fall. Dort erfolgt die Registrierung der zu startenden Prozesse z.B. über eine vorinitialisierte Tabelle mit den Startadressen der zusammen mit dem Kernel geladenen Programme. Ob ein Bootloader oder nur ein kleiner Startup-Code vorgeschaltet ist, hängt hauptsächlich von der Hardware bzw. Speicherausstattung ab. Ganz anders bei: > Wenn z.B. bei einem Linuxrechner die GUI deaktiviert ist, sieht man nach > dem Start die Shell. Das ist ja im Prinzip ein Programm (es gehört zwar > zum OS, aber nicht zum Kernel). Aber wie wird die Shell geladen? Hierfür empfehle ich sehr das ausführliche Studium der Datei /usr/src/linux/init/main.c , insbesondere die Funktion:
1 | static noinline int init_post(void) |
> Woher weiß das OS bzw. der Programloader des OS', an welcher Adresse in der > HDD der Code zur Shell gespeichert ist? Gibt es da eine Tabelle, in der > alle vorhandenen Programme inkl. Speicheradresse gelistet sind? Der gestartete Kernel kennt schon sein root-Dateisystem. Dort sucht er zunächst an verschiedenen Orten nach einem Executable namens "init", z.B. /sbin/init. Dieser Prozess erhält die PID 1 und darf niemals beendet werden. Alle anderen Prozesse sind Kinder von init. Bevor bei einem Linux-System ein Shell-Login bzw. direkt eine Benutzer-Shell erscheint, ist schon sehr viel passiert, d.h. etliche Startup-Skripte wurden/werden ausgeführt. Dies ist jedoch sehr systemspezifisch. > Das bringt mich dann zur nächsten Frage: > Wie kam der Code für die Shell zum ersten Mal in die HDD? Durch Erzeugen des root-Dateisystems mit Hilfe eines schon laufenden Systems. Man kann solch ein root-Dateisystem auch als Datei in einem anderen System erzeugen und dann als Abbild kopieren. Die allerersten Linux-Systeme waren nicht in der Lage, sich selbst zu installieren, da es noch keine Dienstprogramme zur Erzeugung von Dateisystemen gab. Man benötigte daher anfangs immer ein lauffähiges Minix, um das Dateisystem auf einer Festplattenpartition zu erzeugen. Die anschließende Installation auf dem so erzeugten Dateisystem konnte Linux dann aber selbst durchführen. > Die wurde ja nicht samt dem Kernel mitkompliert, oder? Es wird ja nicht > irgendwo im Kernelcode stehen: > > ... irg welche Initialisierungen... > shell(); > ... > :D > > Das geht ja nicht, weil der Kernel ja die "Funktion" shell nicht kennt. Jein. Die betreffende Funktion heißt "run_init_process()" und lädt zunächst die betreffende Datei vom root-Dateisystem ins RAM.
Ok, erstmal danke Andreas für deine ausführliche Antwort! > Man muss u.a. unterscheiden, ob das > Betriebssystem und die Anwendungen schon zur Kompilierzeit gelinkt sind > oder nicht. Genau darum ging es mir! Wenn der gesamte Code miteinander kompiliert wurde, ist es mir schon klar, dass der Kernelcode jedes Programm bzw. jede Funktion kennt. Aber wenn dies eben nicht der Fall ist... das wollte ich wissen. Danke! > Jein. Die betreffende Funktion heißt "run_init_process()" und lädt > zunächst die betreffende Datei vom root-Dateisystem ins RAM. Also greift diese Funktion auf die HDD zu und lädt das dort liegende executable an eine festgelegte Adresse im RAM? Danke, du hast mir sehr weitergeholfen.
Samuel J. schrieb: > Also greift diese Funktion auf die HDD zu und lädt das dort liegende > executable an eine festgelegte Adresse im RAM? warum soll es eine festgelegt Adresse gebe. Der Kernel ist nach dem start in der lage einfach Programm zu starten und init ist auch nur ein Programm. Wenn man will kann man auch von kernel sich gleich eine Shell starten lassen. init=/bin/bash
Peter II schrieb: >> Also greift diese Funktion auf die HDD zu und lädt das dort liegende >> executable an eine festgelegte Adresse im RAM? > > warum soll es eine festgelegt Adresse gebe. Stimmt beides. Im physikalischen Adressraum ist die Adresse beliebig. Im logischen Adressraum des Prozesses landen sie hingegen stets an der gleichen Adresse (DLLs bzw. shared libs freilich nicht unbedingt).
A. K. schrieb: > Im > logischen Adressraum des Prozesses landen sie hingegen stets an der > gleichen Adresse auch nicht immer http://de.wikipedia.org/wiki/Address_Space_Layout_Randomization
Für das dynamische Laden ist normalerweise sowas wie ld-linux.so zuständig -- siehe man ld-linux.so
Also da hat man unterschiedliche Systeme die miteinander Interagieren. Da gibts zum einen das Urladesystem, welches die ersten Teile des Betriebssystems in den Speicher läd und ausführt. Auf PCs ist das das BIOS, es läd den ersten Sektor der Diskette oder Festplatte an eine bestimmte feste Adresse im Speicher und führt ihn aus. In diesem Sektor ist der Urlader enthalten, der dann ggf. noch weitere Teile läd, welche dann das Betriebssystem laden. Im Prinzip ist das eine mehr oder weniger lange Kette. Bei Linux zum Beispiel steht da wirlich, dass er die Shell unter /bin/sh ausführt, falls er /bin/init nicht findet... Dann gibts noch das Dateisystem. Das ist meistens ein Teil des Kernels. Es hat funktionien wie "Lese mir x Bytes von Datei X an diese Adresse des Speichers". Das Dateisystem abstrahiert die Position der Datei auf der Platte. Jetzt gibts mehrere Möglichkeiten den Code zu laden. Das einfachste ist Code an einer festen Speicherstelle. Das ist aber relativ unflexibel. Mit einer Speicherverwaltungseinheit (MMU) kann man aber dem Programm einen virtuellen Arbeitsspeicher vorgaukeln, so dass das trotzdem funktioniert. Jedes Programm würde dann zum Beispiel an Adresse $1000 geladen, obwohl $1000 für jedes Programm physikalisch im Speicher wo anders ist. Dann gibts noch positionsunabhängigen Code. Den hast Du dann wenn Du den Code an jede beliebige Stelle im RAM schreiben kannst, und einfach ausführen kannst. Dazu dürfen da nur relative Sprünge im Code vorkommen, und alle Zugriffe auf das Programm müssen relativ zum Programmzeiger stattfinden. Man kann da auch nicht einfach globale Variablen verwenden, da diese an vom Compiler bestimmten Stellen liegen. Heute hat man leider auch noch aufwändige Lader, die in der Lage sind, die Adressen von Programmen und Bibliotheken um zu schreiben. Das ist ziemlich aufwändig aber es funktioniert.
Christian Berger schrieb: > Heute hat man leider auch noch aufwändige Lader, die in der Lage sind, > die Adressen von Programmen und Bibliotheken um zu schreiben. Das ist > ziemlich aufwändig aber es funktioniert. Die kannte man schon vor Jahrzehnten. Vergleichsweise neuer ist die Variante, positionsunabhängigen Code zu generieren um diese Relokation zu vermeiden. Auch deshalb, weil das u.U. etwas die Performance drückt, beispielsweise bei x86 32-bit. In x86 64-bit wurde das behoben.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.