Forum: PC Hard- und Software Wie werden Programme geladen?


von Samuel J. (capstrovor)


Lesenswert?

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
von Samuel J. (capstrovor)


Lesenswert?

Mir geht es nicht um Linux, sondern um die Theorie von Betriebssystemen.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

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
von Samuel J. (capstrovor)


Lesenswert?

> Ja, nennt sich Directory
Ah, ok danke!

danke für die Antwort!

von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

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.

von Samuel J. (capstrovor)


Lesenswert?

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.

von Peter II (Gast)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

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).

von Peter II (Gast)


Lesenswert?

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

von Samuel J. (capstrovor)


Lesenswert?

Ok danke für die Hilfe!

von Sven B. (scummos)


Lesenswert?

Für das dynamische Laden ist normalerweise sowas wie ld-linux.so 
zuständig -- siehe man ld-linux.so

von Christian B. (casandro)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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
Noch kein Account? Hier anmelden.