Ich kann mir gut vorstellen, dass die einzelnen Programme (jew. eine Executable) alles enthalten, um zu laufen...wenn sie denn erst einmal kompiliert wurden.
Das ist leider selten der Fall. Irgendwelche Bibliotheken werden eigentlich immer benötigt. Ich versuche das mal vereinfacht darzustellen.
Ein Programm benötigt z.B. eine Funktion aus libcrypt. Wenn diese Lib auf dem System vorhanden ist, wird sie in den Speicher geladen und das Programm kann darauf zugreifen. Ist sie nicht vorhanden, scheitert der Programmstart.
Wird jetzt ein weiteres Programm gestartet, welches ebenfalls libcrypt benötigt, stellt das System fest, das die Lib bereits geladen ist und macht diese dann auch dem neuen Programm bekannt. Die Bibliothek liegt also nur einmal im Speicher, kann aber von mehreren Programmen genutzt werden. Bei Linux heißen sie deshalb auch "shared libraries" und haben die Endung ".so" (bei Windows .dll).
Das hat einige Vorteile: Es spart Speicherplatz und macht die Programmdateien kleiner. Und bei einer Fehlerhafen Bibliothek muss nur die korrigierte Version ausgetauscht werden. Eine erneute Übersetzung der Anwendungsprogramme ist nicht erforderlich.
Es gibt natürlich auch Fälle, wo das nachteilig ist. Also wenn man z.B. für Service Zwecke ein Programm benötigt, das ohne Neuübersetzung auf verschiedenen Systemen direkt einsatzfähig ist. Aber wenn man das zum Standard macht, hebelt man die eigentlichen Vorteile von Linux aus (s.o.).
Man kann natürlich auch statisch linken. Der Linker fügt alle Objektdateien (.o), die man ihm übergibt, zusammen. Man kann den Linker aber auch dazu veranlassen, fehlende Funktionen in einer Archivdatei (.ar) suchen zu lassen. Dann sind diese auch in der ausführbaren Datei vorhanden. Aber wie man von einer .so-Datei zu einer .ar-Datei kommt, kann ich nicht sagen.
Das statische Linken benutze ich für meine Programme, die mit einer Entwicklerversion des FLTK Toolkits erstellt wurden. Dies ist möglich, da ich den kompletten Quelltext habe und notwendig ist es, weil es sonst Komplikationen mit libfltk* des Systems gäbe. Das Problem dabei ist, dass sich bei unterschiedlichen Versionen die Funktionsschnittstellen unterscheiden können.
Wenn man das nicht beachtet, bekommt man unerklärliche Abstürze. Anfangs hatte ich das nicht beachtet und bin auch prompt auf die Nase gefallen.
Edit: typo