Autor Thema: Zeiger auf lokale Variablen  (Gelesen 3946 mal)

[MM]

  • Beiträge: 130
    • Profil anzeigen
    • www.mmcoding.eu
Gespeichert
« am: 11. February 2006, 14:10 »
Hallo, ich bin grade am Grübeln wie man das folgende Problem am besten Lösen kann:
Mal angenommen man hat diese zwei Funktionen:

int gvar;
void func(int *ptr){
  *ptr=0;
}
void main(void){
  int lvar;
  func(&lvar);
  func(&gvar);
}

Die Variable lvar befindet sich auf dem Stack und gvar im Datensegment. Wenn man nun keine Far-Zeiger verwendet (also nur 32-Bit Adressen) so müssen Stack und Datensegment sich ja überlappen, so dass man auch mit ds: auf die Adresse von lvar zugreifen kann (der Stack befindet sich also im Datensegment).
Weiß jemand von euch, wie dieses Problem zB bei Windows gelöst wird? Eventuell genauso?

Für normale Anwendungen funktioniert dieses Konzept zumindest recht gut, jedoch jetzt will ich einen Kernel schreiben, dessen API-Funktionen per Interrupt aufgerufen werden. Das Problem ist nun, dass ich zwar das Datensegment des Kernels in der API-Funktion laden kann, jedoch weiterhin das Stacksegment des Aufrufers benutzen muss. Dadurch würde das Programm abstürtzen, wenn wie in func() auf einen Zeiger einer lokalen Variable zugegriffen würde.
Wie könnte man dieses Problem am elegantesten lösen?

MM

SSJ7Gohan

  • Beiträge: 398
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 11. February 2006, 15:09 »
Alle Segmente auf Basis 0, Limit 0xFFFFFFFF setzen, und Paging für den Speicherschutz benutzen. Das machen alle modernen x86 Betriebssysteme, Windows benutzt glaubich FS oder GS um auf Threadspezifische Daten zuzugreifen.
C ist nicht gut für segmentierte Addressräume geeignet, da es auf Daten auf dem Stack und dem Heap gleich zugreift. Wenn du deinen eignen Compiler nutzt, kannst du dass eventuell lösen, indem du auf alle Daten über ein Segment zugreifst, oder halt mehrere Segmente überlappen lässt, das flache Speichermodell ist aber am einfachsten und wohl auch am schnellsten.

[MM]

  • Beiträge: 130
    • Profil anzeigen
    • www.mmcoding.eu
Gespeichert
« Antwort #2 am: 11. February 2006, 18:04 »
Ja, dass das mit einem flachen Speichermodell am einfachsten funktioniert sehe ich auch so, nur wie ließen sich dann Parameter bei API-Aufrufen von der Applikation an den Kernel weiterreichen (wenn beide je ihren eigenen 4GB Adressraum hätten)?
Ich meine wenn die Anwendung zB einen Zeiger auf die Adresse 0x1234 übergibt und der Kernel dann seine eigene Pagetabelle läd um arbeiten zu können, dann liegt da ja was ganz anderes (wie könnte man die Kernelfunktion so überhaupt aufrufen, wenn sie nicht im virtuellen Adressraum der Anwendung liegt?).
Wäre es da nicht sinnvoll wenn der Kernel mit seinem Code/Daten/Stack/Heap zB bei 0-512MB liegt und alle Anwendungen den Bereich von 512MB-4GB nutzen würden?
Wobei ich mir aber noch nicht ganz sicher bin, wie man dann den Bereich von 0-512MB schützen sollte, da wenn man ihn einfach in der Pagetabelle der Anwendung freilassen würde ich ja auch nicht per Interrupt in das Codesegment des Kernels springen könnte.
Hast du da auch eine Idee SSJ7Gohan?

MM

SSJ7Gohan

  • Beiträge: 398
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 11. February 2006, 18:29 »
Ja, ich würde auch einen kleinen Bereich für den Kernel reservieren. Es gibt ein Bit in jeder Pagetable, mit dem du Zugriffe von Ring3 Anwendungen sperren kannst. Der Kernel wird dann also in alle Prozesse gemappt, und kann über INTs oder andere Prozessorfunktionen aufgerufen werden. (SYSENTER, SYSCALL, Callgates usw.)

[MM]

  • Beiträge: 130
    • Profil anzeigen
    • www.mmcoding.eu
Gespeichert
« Antwort #4 am: 11. February 2006, 18:49 »
Hm, stimmt da gibt es ja das Bit No. 2 (User/Supervisor). So sollte es gehen...

MM

 

Einloggen