Archiv verlassen und diese Seite im Standarddesign anzeigen : Heap
Hy,
also ich hab Heute halb google auseinander genommen um herauszufinden wo der Heap nun eigentlich im Arbeitsspeicher liegt.
1. Einige meinten es gibt das Code,Daten,Stack,und ein Heap Segment.
Innerhalb dieses Heap Segments mit fester Größe kann dann ein freier Speicherplatz über Systemfunktionen ermittelt werden. Dann bekommt man die Startadresse zurück und kann darauf schreiben. Das Betriebssystem überprüft aber nicht ob man beispielsweise zu viel dort hin schreibt.
2. Andere meinten das Heap Segment gibt es so nicht sondern das Betriebssystem verwaltet freie Speicherbereiche über den ganzen Arbeitsspeicher und gibt bei Bedarf einem Programm eine passende freie Stelle. Das heißt ein Programm kann Theoretisch beliebig viel Heap für sich beanspruchen. Wobei man wie ich das sehe warscheinlich durch die Anzahl der zur Adressierung verfügbaren Bits beschränkt ist.
3. Die letzte Theorie war es gibt gar kein Daten und Heap Segment sondern das Heap Segment ist ein und das selbe bei Programmen.
Ich kann nur sagen :mauer: :mauer: :mauer:
Bitte helft mir was stimmt nun?
Hy,
also ich hab Heute halb google auseinander genommen um herauszufinden wo der Heap nun eigentlich im Arbeitsspeicher liegt.
Versuch's mal bei Wiki ;^)
http://de.wikipedia.org/wiki/Dynamischer_Speicher
Da steht nur oberflächliches Blabla aber nicht die Antwort.
butterkeks
23.08.2006, 14:40
Wenn du etwas low-leveliges wissen willst, wäre die PLattform (OS, compiler, ...) interessant... aber allgemein gesehen ist der Wikipedia Artikel eigentlich ganz ordentlich
// edit:
die englische Version des Artikels ist etwas informativer (lies dir auch die 3 Artikel in der Liste nach dem ersten Absatz durch)
Jan Krüger
23.08.2006, 16:13
Im Protected Mode bei x86 ist der Begriff "Segment" nicht mehr wörtlich zu verstehen. Im PM wird normalerweise durch Paging virtueller Speicher verwendet; d.h. Speicheradressen sind virtuell und werden vom System mehr oder weniger beliebig auf physikalischen Speicher sowie auf ausgelagerte Daten oder einfach auf gar nichts abgebildet. Damit beantwortet sich eigentlich auch schon die Frage: rein technisch gesehen kann der Heap sonstwo liegen. Die virtuelle Adresse kannst du mit einem kleinen Testprogramm leicht abschätzen:
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char** argv)
{
unsigned int *foo;
foo = malloc(sizeof(unsigned int));
printf("Zeiger: 0x%08X\n", (unsigned int) foo);
return 0;
}
Bei mir fängt der Heap anscheinend bei etwa 0x0804A008 (virtuell) an.
Kurz zu malloc(): diese Funktion der libc allokiert Speicher auf dem Heap des aktuellen Prozesses und gibt einen Zeiger auf den Start dieses Speicherbereichs zurück. Schreibzugriffe über die allokierte Grenze hinaus werden tatsächlich nicht abgefangen (es sei denn, sie gehen aus dem virtuellen Speicherbereich heraus, der tatsächlich auf physikalischen Speicher oder ausgelagerten Speicher abgebildet wird; dann gibt es nämlich einen Segmentation Fault, unter Unix auch als SEGV bekannt).
Dank Paging können auch Teile des Heaps eines Prozesses ausgelagert sein und sich somit überhaupt nicht im Arbeitsspeicher befinden.
Danke erstmal, das klingt ja schon gut.
Also ich hatte von einem Prozess eben immer das Bild von Code,Daten,Heap und Stack Segment.
Die Adressen werden wohl erst zur Laufzeit auf die echte physische Adresse umgesetzt. Wie ist es aber mit der Aufteilung beim schreiben eines Programmes Assembler oder Assemlberergebnis eines C++ Compilers? Wird der Code (virtuell) trozdem noch in Segmente aufgeteilt oder ist das dann ganz hinfällig.
Wenn ja gäbe es in dem Fall ja nur die relative Adressierung ausgehend vom Beginn des Programmcodes.
Gibt es dann auch keinen geschützen Adressraum mehr für jeden Prozess?
butterkeks
23.08.2006, 19:30
Wie gesagt werden Segmente im Protected Mode zumindest zur Addressierung nciht mehr verwendet.
Wenn ja gäbe es in dem Fall ja nur die relative Adressierung ausgehend vom Beginn des Programmcodes.
afaik hat es nichts damit zu tun an welche virtuelle oder physische Adresse das OS deinen Programmcode lädt... du hast halt einen 32 bit Wert, den du zum adressieren benutzen kannst.
Segmente tauchen allerdings immer noch in einer anderen Form auf, z.B. in der ausführbaren Datei selber (Stichworte PE, ELF, ...), aber die haben halt nur bedingt etwas mit den Segmenten zu tun, die du vlt. vom Realmode her kennst.
Gibt es dann auch keinen geschützen Adressraum mehr für jeden Prozess?
Doch. 0x0804A008 kann z.B. für jeden Prozess auf eine andere, physische Stelle im Speicher zeigen (was nicht immer sein muss... bei DLLs z.B.)
Hat diese Frage überhaupt etwas mit UNIX zu tun, oder warum hast du sie in diesem Bereich gestellt?
Jan Krüger
23.08.2006, 19:48
Zwischen Segmenten in einer ausführbaren Binarydatei (z.B. PE-Format; mit ELF kenne ich mich leider nicht aus) und Speichersegmenten muss man unterscheiden. Wenn ein Binary in mehrere Segmente unterteilt ist, werden die vom Loader des Betriebssystems irgendwo im Speicher (wir kennen das ja inzwischen :)) angesiedelt und sämtliche Verweise darauf umgeschrieben, um die Offsets im virtuellen Speicher zu berücksichtigen. Letztendlich landen aber alle Daten aus dem Binary irgendwo im virtuellen Speicherimage des Prozesses, von daher ist da dann auch nicht mehr viel mit Segmenten.
butterkeks
23.08.2006, 20:32
ja, deshalb die Warnung, dass dies nicht den Segmenten entspricht, die man z.B. vom Realmode her kennt... oder was meinst du genau?
i.d.R. nennt man diese Segmente, die in der Binary angelegt werden "Sections", fällt mir gerade noch ein. Hat also nicht mal vom Namen her ncoh etwas mit Segmenten zu tun ^^
Also ist die Darstellung die Ihr auf dieser Seite zur Beschreibung eines Prozesses findet Heute falsch?
http://www.wachtler.de/ck/9_Speichermodell_Prozesses.html
Oder hier Heise.de
Bei modernen Betriebssystemen arbeitet jedes Programm in einem eigenen, virtuellen Adressraum, dessen Adressen die Hardware -- konkret die Memory Management Unit (MMU) -- erst bei Bedarf physikalischen Speicher zuordnet. Im virtuellen Speicher legt das Betriebssystem beim Start eines Programms drei Segmente an: das Code-Segment, das Daten-Segment (auch Heap genannt) und das Stack-Segment. Das Stack-Segment ist ein Zwischenspeicher für lokale Variable und gesicherte Prozessorregister, die das Programm zu einem späteren Zeitpunkt wieder benötigt. Der Stack beginnt am oberen Ende des Adressraums und wächst nach unten. Er funktioniert als Last-in-first-out-Puffer, den man erst abräumen muss, bevor man an früher abgelegte Daten kommt. Der Stack Pointer (ESP) markiert das Ende des Stacks und zeigt damit immer auf den letzten Eintrag.
Quelle: http://www.heise.de/security/artikel/37958
Im wesentlichen geht es mir nur um den Aufbau eines Prozesses.
Wenn wir die Segmente mal weglassen und annehmen das alles nur noch in einem Bereich (Segment wenn man so will) in der Datei steht.
Ist es dann trozdem noch so das in der Datei immer noch die Daten und dann der Code getrennt stehen und so auch im virtuellen Speicher adressiert werden?
Wenn ja wie verhält es sich dann eigentlich mit dem Loader er kann ja nun nicht mehr einfach den Prozess mit Daten und Code in einem Rutsch in den Speicher kopieren
Achso und wie ist das dann noch mit der Heapverwaltung nehmen wir mal an über eine Bitmap zeigt die dann auf virtuelle oder physische Adressen?
Und wie verhält es sich dann mit dem Stackpointer Stacksegmentregister wird des ja nicht mehr geben aber den Stackpointer gibts immer noch oder?
butterkeks
23.08.2006, 22:15
Also ist die Darstellung die Ihr auf dieser Seite zur Beschreibung eines Prozesses findet Heute falsch?
http://www.wachtler.de/ck/9_Speicher...Prozesses.html
Was genau soll daran falsch sein?
Ist es dann trozdem noch so das in der Datei immer noch die Daten und dann der Code getrennt stehen und so auch im virtuellen Speicher adressiert werden?
Ja, Code und Daten werden eigene Bereiche im virtuellen Speicher reserviert; Wie das genau verteilt wird, hängt vom OS bzw. dem Loader ab.
Wenn ja wie verhält es sich dann eigentlich mit dem Loader er kann ja nun nicht mehr einfach den Prozess mit Daten und Code in einem Rutsch in den Speicher kopieren
Richtig, das geht nciht so einfach... wie Jan schon sagte, muss der Loader zum Beispiel einige Offsets abändern (der Vorgang nennt sich afaik "Relokation"), Libraries laden/einbinden, ...
Und wie verhält es sich dann mit dem Stackpointer Stacksegmentregister wird des ja nicht mehr geben aber den Stackpointer gibts immer noch oder?
jepp und der Stackpointer zeigt halt auch wieder nur auf virtuelle Adressen...
Die Segmentregister gibt es im PM noch, doch sie haben dort eine andere Bedeutung
Zitat:
Also ist die Darstellung die Ihr auf dieser Seite zur Beschreibung eines Prozesses findet Heute falsch?
http://www.wachtler.de/ck/9_Speicher...Prozesses.html
Was genau soll daran falsch sein?
Mhh verdammt wie bring ich das rüber. Nehmen wir mal an ich schreibe ein Programm in Assembler im Protected Mode. Da es keine Segmente mehr gibt kann ich Daten und Code ja praktisch auch durcheinander mischen. Also erst ein paar Codezeilen und dann erst die globalen Variablen.
Dadurch wäre die Trennung von Daten und Code ja futsch.
Unabnhängig davon stimmt das Bild oben aus dem Link oben ja auch nicht da die virtuellen Adressen ja beliebig im physikalischen Speicher verteilt sein können so das nebeneinander ein bischen Code dann wieder Daten und dann wieder Code liegen kann.
Wenn ich mist schreibe hau zu :mauer: aber ich bin jetzt echt verwirrt.
Richtig, das geht nciht so einfach... wie Jan schon sagte, muss der Loader zum Beispiel einige Offsets abändern (der Vorgang nennt sich afaik "Relokation"), Libraries laden/einbinden, ...
Ja das schon aber wenn nun Prozesse nicht mehr ganz im Speicher sind dann lädt er ja auch nicht mehr alles rein, wie wird das verwaltet? Und wenn jetzt keine zusammenhängenden Bereiche im Speicher frei sind dann muss er das was er in den AS ladet ja noch splitten. Oder bin ich auf dem Holzweg?
Übringens danke das ihr helfen wollt.
mnemonic
23.08.2006, 23:08
Nehmen wir mal an ich schreibe ein Programm in Assembler im Protected Mode. Da es keine Segmente mehr gibt kann ich Daten und Code ja praktisch auch durcheinander mischen. Also erst ein paar Codezeilen und dann erst die globalen Variablen.
Rein terroristisch wäre das möglich, aaaaaber...
Jedes moderne OS würde Dir auf die Finger klopfen wenn Du versuchen würdest einfach so in den Code-Bereich zu schreiben, oder die Ausführung innerhalb von Daten weiterführen würdest (z.B. einen JMP auf einen String).
Wer jetzt was wo darf wird halt vom OS geregelt (Anhand der Sektionen - Code, Data, BSS, etc.). Deine Daten haben ein Schreib-/Lese-Attribut und Dein Code hat Ausführ-/Lese-Attribut.
Das ganze wird über Paging, Deskriptoren und noch andere unartige Mechanismen realisiert.
Unabnhängig davon stimmt das Bild oben aus dem Link oben ja auch nicht da die virtuellen Adressen ja beliebig im physikalischen Speicher verteilt sein können so das nebeneinander ein bischen Code dann wieder Daten und dann wieder Code liegen kann.
Joa, aber davon bekommt man als Programmierer nix mit und das ist auch fein so. Als Programmierer kannst Du z.B. davon ausgehen, dass Dir (z.B. unter Win32) rein theoretisch 4 GB (Ok, es sind nur 2...) Speicher zur verfügung stehen (pro Prozess!). Wie das OS das realisiert kann Dir schnuppe sein, das paged und swappt in der Gegend rum wie es gerade erforderlich ist.
Anhand Deiner Fragen in den letzten Tagen/Wochen, würde ich vorschlagen, dass Du mal einen Blick in "Das Assemblerbuch" (Autor: Trutz Eyke Podschun, Verlag: Addison & Wesley) reinwirfst. Ich finde, das Buch wird Deine Neugier weitestgehend befriedigen. Da werden alle Deine Fragen bis ins Detail und illlustriert beantwortet.
Ok danke für den Tip das Buch werde ich mir mal anschauen.
Mal kurze ne Zwischenfrage in einem Deskriptor stehen doch grob Zugrifssrechte, Verwendungszweck, Länge und Lage im physischen Arbeitsspeicher.
Das kann aber doch gar nicht gehen denn ich kann keine 4 GB adressieren wenn ich sie nicht hab??
Und wie spielt da jetzt Paging rein?
Unabhängig davon. So wie ich es verstanden habe kann ich jetzt für jede Section, Speicherbereich, Segment (wie auch immer man diese Blöcke nennen will) 4GB haben. Wird dann für den Heap ein eigener 4 GB Datenbereich angelegt oder wo sucht das Betriebssystem dann nach einem freien Bereich. Für den Stack habe ich gesehen gibt es ja ein eigenen Bereich mit umgedrehter Spitze.
mnemonic
24.08.2006, 18:51
Das kann aber doch gar nicht gehen denn ich kann keine 4 GB adressieren wenn ich sie nicht hab??
Doch, theoretisch sind die verfügbar. Praktisch jedoch, hängt der verfügbare Speicher davon ab wieviel physikalisches RAM installiert ist und wie gross die Swapfile/Swappartition ist.
Wenn alles aufgebraucht ist, wird dicht gemacht.
Und wie spielt da jetzt Paging rein?
Der Paging-Mechanismus ist dafür zuständig welcher Teil des virtuellen Speichers momentan da ist, bzw. ausgelagert (geswappt) ist oder auch wird und bei Bedarf aus der Swapfile in den physikalischen Speicher geladen wird.
Unabhängig davon. So wie ich es verstanden habe kann ich jetzt für jede Section, Speicherbereich, Segment (wie auch immer man diese Blöcke nennen will) 4GB haben. Wird dann für den Heap ein eigener 4 GB Datenbereich angelegt oder wo sucht das Betriebssystem dann nach einem freien Bereich. Für den Stack habe ich gesehen gibt es ja ein eigenen Bereich mit umgedrehter Spitze.
Nein, ein Prozess besteht bekanntlich aus Code und Daten (den Stack mal bei den Daten eingeschlossen) und jeder Prozess verfügt über theoretisch 4 GB (zumindest wird ihm das vorgegaukelt).
butterkeks
24.08.2006, 21:30
Unabhängig davon. So wie ich es verstanden habe kann ich jetzt für jede Section, Speicherbereich, Segment (wie auch immer man diese Blöcke nennen will) 4GB haben. Wird dann für den Heap ein eigener 4 GB Datenbereich angelegt oder wo sucht das Betriebssystem dann nach einem freien Bereich.
diese Bereiche, von denen du sprichst, sind wie gesagt nicht direkt mit Realmode-Segmenten vergleichbar... das ist einfach nur jeweils der Platz zwischen zwei 32bit Speicherstellen. Code geht von hier bis hier, Daten von da bis dort, ...
Du hast keine "Segmente" mehr, sondern nur noch "Offsets", sozusagen
Ok, hat der Stack dann einen eigenen Speicherabschnitt in dem 4 GB Bereich? Ich hab in dem Buch gesehen das es ein extra Bit gibt das diesen Bereich virtuell andersrum wachsen lässt.
Wichtig: Und wie ist es nun mit dem Heap in welchem virtuellen Bereich wird dieser angelegt. Das BS muss ja in irgendeinem virtuellen Speicherbereich den Pageeintrag vornehmen wenn neuer Speicher angefordert wird. Und im Assemblerprog muss ich ja auch über irgendeinen Deskriptor + Wert diesen Eintrag adressieren. Und wie war das eigentlich im Realmode musste man da ein Heapsegment erstellen?
Und ich habs noch nicht ganz gelesen aber ich nehme mal an das der Loader jetzt nur noch beim Laden die Pageeinträge ändert falls zuvor was ausgelagert wurde und nun wieder eingelagert wird. Die Deskriptoren müssten ja eigentlich gleich bleiben.
Wenn ich kein Paging hätte also nur mit Deskriptoren arbeiten würde, würde die ganze Sache nicht funktionieren nehme ich an da man ja nicht mehrfach bzw. nicht mal einfach 4GB hat aber das nur am Rande.
Also,
so wie ich es jetzt raus gelesen habe gibt es für virtuelle Speicherverwaltung zwei Möglichkeiten.
1. Ein einziger Linearer Adressraum (Paging) von 32Bit für ein komplettes Programm. Ob man das Programm hier separiert ist das eigene Problem. Man darf nur keine Sprünge auf Adressen des BS machen.
Könnt ihr mir ein Beispiel nennen wo das noch so gemacht wird?
2. Man hat Segmentiertes-Paging in dem Segmente verwendet werden d.h. genauer der lineare Adressraum in einzelne Bereiche eingeteilt wird und über separate Zugriffsrechte geschützt wird. (Steht so in dem Assembler-Buch)
Kann es sein das Nr1 gar nicht mehr verwendet wird? Ich stelle mir das schwierig vor ein Programm so zu schreiben das z.B. zwischen Stack und Daten genug Platz bleibt ohne dazu Segmentiertes-Paging zu verwenden.
So nun die Fragen:
1. Wenn das Prog vom Loader in den Speicher geladen wird, erstellt dann das BS die Seitentabelle? Und wenn ja dann müsste es ja eigentlich immer eine Seitentabelle haben in denen die aktuellen 2GB Systemeinträge schon enthalten sind und in die dann nur das neue Programm eingefügt wird und dann noch nur diese Einträge verzweigt.
2. Es gibt dann zwei Möglichkeiten ein Programm zu laden. Entweder das BS erstellt eine Seitentabelle mit einem Eintrag für den Startcode und alle anderen Daten liegen auf der SWAP-Partition und werden nach und nach eingelagert.
Die zweite Möglichkeit ist gleich alles in den Speicher zu laden und dann nach und nach nicht benötigtes auszulagern.
So nun aber die Frage die sich mir stellt. Jeder Prozess hat ja seine eigene Seitentabelle. Wenn jetzt nach der zweiten Methode ein Prozess in den Speicher kommt werden ja andere Seiten verdrängt. Woher weis das BS dann in welcher Seitentabelle die verdrängten Seiten geändert werden muss?
Und eigentlich habe ich doch auch keine Relokationsprobleme mehr im Prinzip würde es doch reichen immer relativ von einer fixen Startadresse innerhalb des virtuellen Speicherbereiches starten zu lassen und fertig. In dem Fall müsste der Loader ja auch nichts mehr machen.
3. Der Speicheraufbau scheint ja nun vom Fileformat abhängig zu sein. In Assembler arbeitet man ja direkt mit den alten Registern nur das dort nur noch ein Verweis auf einen Deskriptor steht der den jeweiligen zusammenhängenden virtuellen Speicherbereich adressiert.
Wie wird das beim PE-Format umgesetzt. Werden dort auch diese Register verwendet und wie??
Wo liegt im PE-Format der Heap woher weis das BS das es dort hin muss und in welchen virtuellen Bereichen es schreiben muss und wo lag beim Realmode der Heap, weil extra angelegt wurde er ja nicht.
Mehr konnt ich nicht rauskriegen bitte um Hilfe.
Hab mir jetzt mal den Aufbau Speicherverwaltung etc. an Windows angeschaut. Mit Objektmanager usw. also ich blick jetzt wirklich nichts mehr. Ich überlege mir gerade ob ich Info nicht stecke und was anderes mache. Jetzt hab ich 3 Wochen gelernt und jetzt ist in Windows doch wieder alles anders. Nirgendwo findet man gescheite Infos echt zum kotzen.
Wenn jemand noch was weis gerne, auch Nachhilfe im Kreis Bodensee aber ich gebs echt so ziemlich auf. PE-Format,Dynamische Speicherverwaltung jetzt liegen noch Objekmanager drübert. Ich hab keine Übersicht mehr.
Quantumseeker
26.08.2006, 23:16
Muesst ihr das denn so uebel im Detail und letzten Bit wissen? Bei betriebssysteme VL hier an der Uni hat keiner nach dem PE-Format gefragt ...
ich kann dir nur sagen, gib nicht auf. finde eine lernmethode, und ruh dich auch mal aus, ausserdem, fuer die uni wirst du doch wohl nicht in den code von Betriebssystemen schauen muessen?!
vBulletin® v3.8.6, Copyright ©2000-2012, Jelsoft Enterprises Ltd.