Autor Thema: malloc() und free()  (Gelesen 9451 mal)

ReduX

  • Beiträge: 19
    • Profil anzeigen
Gespeichert
« am: 01. May 2007, 20:50 »
Hi,
Ich bin noch neu im os programmieren habe aber vorher schon mit C und PHP gecodet.
Ich habe es soweit geschafft das dass OS bootet und den C Kernel lädt so nun möchte ich mir aber größerer Funktionen anschauen wie z.B. das GUI Tutorial durcharbeiten dafür brauche ich aber die malloc() und free() befehle!
Ich habe gelesen das ein Memory Manager diese Befehle verwaltet etc. nur weiß ich nicht wie man so einen Memory Manager erstellt habe zwar schon gelsesn wie er aufgebaut ist aber wie man ihn codet weiß ich nicht.
Hat jemand einen link zu einem guten Tutorial für mich?

MFG ReduX

FreakyPenguin

  • Administrator
  • Beiträge: 301
    • Profil anzeigen
    • toni.famkaufmann.info
Gespeichert
« Antwort #1 am: 01. May 2007, 21:23 »
Erstmal Willkommen hier im Forum ;-)

Die Speicherverwaltung im Kernel selbst verwaltet im allgemeinen nur Blöcke mit fester Grösse, in den meisten Fällen Pages. (Klar es gibt da auch komplexere Modelle, für den Anfang reicht das aber völlig) malloc(...), free(...) und realloc(...) sind Bibliotheksfunktionen, die (meist per Syscalls) von der Speicherverwaltung im Kernel ganze Pages anfordern und sie sinnvoll verwalten und verteilen.


So auf die schnelle fallen mir zwei gute Tutorials über den Aufbau einer Speicherverwaltung ein. Hier ein Link wo diverse Tutorials dazu aufgelistet sind. Ich würde dir erstmal die zwei von Tim Robinson empfehlen:
http://osdever.net/tutorials.php?cat=6&sort=

ReduX

  • Beiträge: 19
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 02. May 2007, 18:54 »
HI,
Danke für deine Antwort also berfor ich meinen Memory Manager nun baue brauch ich ja moch die Paging function in dem Tutorial steht ein asm Source Code dafür nun will ich ihn aber in C einbinden dzu habe ich volgendes gemacht:
__asm__ ("
[global _read_cr0]
read_cr0:
mov eax, cr0
retn

[global _write_cr0]
write_cr0:
push ebp
mov ebp, esp
mov eax, [ebp+8]
mov cr0,  eax
pop ebp
retn

[global _read_cr3]
read_cr3:
mov eax, cr3
retn

[global _write_cr3]
write_cr3:
push ebp
mov ebp, esp
mov eax, [ebp+8]
mov cr3, eax
pop ebp
retn");
CIh führe den Code direkt am Anfang in der Main function aus!
Aber es kommen sehr viele Fehlrmeldungen habe von asm leider keinen plan
Fehlermeldungen:
main.c:6:10: warning: multi-line string literals are deprecated
c:/djgpp/tmp/ccCTDQjd.s: Assembler messages:
c:/djgpp/tmp/ccCTDQjd.s:14: Warning: rest of line ignored; first ignored charact
er is `['
c:/djgpp/tmp/ccCTDQjd.s:16: Error: too many memory references for `mov'
c:/djgpp/tmp/ccCTDQjd.s:17: Error: no such instruction: `retn'
c:/djgpp/tmp/ccCTDQjd.s:19: Warning: rest of line ignored; first ignored charact
er is `['
c:/djgpp/tmp/ccCTDQjd.s:22: Error: too many memory references for `mov'
c:/djgpp/tmp/ccCTDQjd.s:23: Error: invalid char '[' beginning operand 2 `[ebp+8]
'
c:/djgpp/tmp/ccCTDQjd.s:24: Error: too many memory references for `mov'
c:/djgpp/tmp/ccCTDQjd.s:26: Error: no such instruction: `retn'
c:/djgpp/tmp/ccCTDQjd.s:28: Warning: rest of line ignored; first ignored charact
er is `['
c:/djgpp/tmp/ccCTDQjd.s:30: Error: too many memory references for `mov'
c:/djgpp/tmp/ccCTDQjd.s:31: Error: no such instruction: `retn'
c:/djgpp/tmp/ccCTDQjd.s:33: Warning: rest of line ignored; first ignored charact
er is `['
c:/djgpp/tmp/ccCTDQjd.s:36: Error: too many memory references for `mov'
c:/djgpp/tmp/ccCTDQjd.s:37: Error: invalid char '[' beginning operand 2 `[ebp+8]
'
c:/djgpp/tmp/ccCTDQjd.s:38: Error: too many memory references for `mov'
c:/djgpp/tmp/ccCTDQjd.s:40: Error: no such instruction: `retn'

Was mache ich falsch?

MFG ReduX

FreakyPenguin

  • Administrator
  • Beiträge: 301
    • Profil anzeigen
    • toni.famkaufmann.info
Gespeichert
« Antwort #3 am: 02. May 2007, 19:17 »
Inline-ASM in GCC muss in der A&T Syntax sein. Zusätzlich müssen noch ein paar weitere Dinge beachtet werden. Siehe dazu: http://lowlevel.brainsware.org/wiki/index.php/Inline-Assembler_mit_GCC

ReduX

  • Beiträge: 19
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 02. May 2007, 21:21 »
Hi,
Danke für deine Hilfe!
Habe den Code nun nach dem Artikel geänder bekomme aber immernoch fehler.  Hier der Code:
__asm__ ("
read_cr0:
mov %eax, %cr0
retn

write_cr0:
push %ebp
mov %ebp, %esp
mov %eax, $ebp+8
mov %cr0,  %eax
pop %ebp
retn

read_cr3:
mov %eax, %cr3
retn

write_cr3:
push %ebp
mov %ebp, %esp
mov %eax, $ebp+8
mov %cr3, %eax
pop %ebp
retn");

Fehler:
main.c:5:10: warning: multi-line string literals are deprecated
c:/djgpp/tmp/cckn2Ntr.s: Assembler messages:
c:/djgpp/tmp/cckn2Ntr.s:16: Error: no such instruction: `retn'
c:/djgpp/tmp/cckn2Ntr.s:21: Error: suffix or operands invalid for `mov'
c:/djgpp/tmp/cckn2Ntr.s:24: Error: no such instruction: `retn'
c:/djgpp/tmp/cckn2Ntr.s:28: Error: no such instruction: `retn'
c:/djgpp/tmp/cckn2Ntr.s:33: Error: suffix or operands invalid for `mov'
c:/djgpp/tmp/cckn2Ntr.s:36: Error: no such instruction: `retn'

MFG ReduX

FreakyPenguin

  • Administrator
  • Beiträge: 301
    • Profil anzeigen
    • toni.famkaufmann.info
Gespeichert
« Antwort #5 am: 02. May 2007, 21:39 »
Ich bin mir nicht ganz sicher, aber ich glaube, du kannst im Inline-ASM keine rets benutzen. Aber warum verpackst du das nicht einzeln in C-Funktionen. Dann kannst du sie auch einfach aus dem C-Code aufrufen. Sonst musst du noch mit dem Stack rumbasteln.
Beispiel:

unsigned int read_cr0()
{
    unsigned int cr0;
    __asm__("movl %%cr0, %0" : "=a" (cr0));
   return cr0;
}

Bist du dir sicher, dass du dir den Artikel genau angeschaut hast? Dort steht bestimmt auch, dass die Operanden vertauscht werden. Denn ein mov %eax, %cr0 schreibt mit der A&T-Syntax den Inhalt des eax-Registers in cr0.


kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 02. May 2007, 21:49 »
Ich bin mir nicht ganz sicher, aber ich glaube, du kannst im Inline-ASM keine rets benutzen.
Doch. Aber dazu sollte man sie auch ret nennen, nicht retn. Unsauber ist es natürlich trotzdem.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

ReduX

  • Beiträge: 19
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 03. May 2007, 13:52 »
Hi,
Danke für eure Antworten.
Also ich habe es mal in C umgewandelt hier der Code:
unsigned int read_cr0()
{
    unsigned int cr0;
    __asm__("movl %%cr0, %0" : "=a" (cr0));
   return cr0;
}

unsigned int write_cr0()
{
    unsigned int cr0;
    __asm__("push %%ebp" : "=a" (cr0));
    __asm__("movl %%esp, %%ebp" : "=a" (cr0));
    __asm__("movl %%ebp+8, %%eax" : "=a" (cr0));
    __asm__("movl %%eax, %0" : "=a" (cr0));
    __asm__("pop %%ebp" : "=a" (cr0));
   return cr0;
}

unsigned int read_cr3()
{
    unsigned int cr3;
    __asm__("movl %%cr3, %0" : "=a" (cr3));
   return cr3;
}

unsigned int write_cr3()
{
    unsigned int cr3;
    __asm__("push %%ebp" : "=a" (cr3));
    __asm__("movl %%esp, %%ebp" : "=a" (cr3));
    __asm__("movl %%ebp+8, %%eax" : "=a" (cr3));
    __asm__("movl %%eax, %0" : "=a" (cr3));
    __asm__("pop %%ebp" : "=a" (cr3));
   return cr3;
}

Hab nurnoch Probleme das bei dem ebp + 8 der Fehler :
Error: junk `+8' after register kommt.
Ist der Code ansonsten korrekt? Nicht das ich später irgendwie hänge und es liegt daran!
Noch eine Frage und zwar waurm macht man z.b. hier:
    __asm__("movl %%eax, %0" : "=a" (cr3));Bei dem mov ein l hintendrann? und warum schreibt mann %o anstatt %%cr3???

MFG ReduX

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 03. May 2007, 14:13 »
Hast du Freakys Link (http://lowlevel.brainsware.org/wiki/index.php/Inline-Assembler_mit_GCC) eigentlich gelesen und verstanden? Eigentlich sollten dort die Antworten auf deine Fragen drinstehen.

Hab nurnoch Probleme das bei dem ebp + 8 der Fehler :
Error: junk `+8' after register kommt.
In AT&T-Syntax schreibt sich das 8(%ebp).

Zitat
Noch eine Frage und zwar waurm macht man z.b. hier:
    __asm__("movl %%eax, %0" : "=a" (cr3));Bei dem mov ein l hintendrann?
Wie ich im Wiki geschrieben habe:
Zitat von: Wiki
Die Operandengrößen sind im Mnemonic enthalten. Wird die Größe nicht angegeben, versucht der Assembler sie anhand der Operanden festzustellen.

movl $123, %eax
movw $123, %ax
movb $123, %al

Zitat
und warum schreibt mann %o anstatt %%cr3???
Macht man nicht. %%cr3 ist ein Zugriff auf das Register cr3, %0 auf die erste Variable in der Parameterliste. Das sind zwei völlig unterschiedliche Sachen.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

ReduX

  • Beiträge: 19
    • Profil anzeigen
Gespeichert
« Antwort #9 am: 03. May 2007, 17:10 »
Hi,
Danke für deine Hilfe es funktioniert jetzt!

MFG ReduX

FreakyPenguin

  • Administrator
  • Beiträge: 301
    • Profil anzeigen
    • toni.famkaufmann.info
Gespeichert
« Antwort #10 am: 03. May 2007, 18:24 »
unsigned int write_cr0()
{
    unsigned int cr0;
    __asm__("push %%ebp" : "=a" (cr0));
    __asm__("movl %%esp, %%ebp" : "=a" (cr0));
    __asm__("movl %%ebp+8, %%eax" : "=a" (cr0));
    __asm__("movl %%eax, %0" : "=a" (cr0));
    __asm__("pop %%ebp" : "=a" (cr0));
   return cr0;
}

unsigned int write_cr3()
{
    unsigned int cr3;
    __asm__("push %%ebp" : "=a" (cr3));
    __asm__("movl %%esp, %%ebp" : "=a" (cr3));
    __asm__("movl %%ebp+8, %%eax" : "=a" (cr3));
    __asm__("movl %%eax, %0" : "=a" (cr3));
    __asm__("pop %%ebp" : "=a" (cr3));
   return cr3;
}

Als ich mir vorhin den Code angeschaut habe, fragte ich mich, ob ich denn so schlimm übermüdet sei, oder ob da wirklich das steht, was ich gelesen habe ;-).

Jedenfalls hat der Code in deinen Funktionen write_cr3 und write_cr0 nicht viel mit dem Funktionsnamen gemeinsam. Diese müssten doch mindestens ein Dword als Parameter haben, welches sie dann in die betreffenden Register schreiben.

Hier ein vorschlag dafür:
void write_cr0(unsigned int cr0)
{
    __asm__("movl %0, %%cr0" : : "a" (cr0));
}

ReduX

  • Beiträge: 19
    • Profil anzeigen
Gespeichert
« Antwort #11 am: 03. May 2007, 19:36 »
HI,
Ja da haste Recht der Code ist von Bona Fide OS Dev. aus nem Tutorial für Paging!
Beim ausprobieren hab ich dann auch gemerkt das sie keine Parameter annahmen.
Aber trozdem danke für deine Mühe!

Edit:
Noch ne kleine Frage
In dem Tutorial steht folgender Code zum ausführen:
unsigned long *page_directory = (unsigned long *) 0x9C000;
unsigned long *page_table = (unsigned long *) 0x9D000;
unsigned long address=0;
unsigned int i;

for(i=0; i<1024; i++)
{
page_table[i] = address | 3;
address = address + 4096;
};
page_directory[0] = page_table;
page_directory[0] = page_directory[0] | 3;
for(i=1; i<1024; i++)
{
page_directory[i] = 0 | 2;

};

write_cr3(page_directory);
write_cr0(read_cr0() | 0x80000000);
Ich habe aber jetzt das Problem das bei write_cr0 ja zwei Prameter übergeben werden aber die Function kann ja nur einer entgegennehmen?!?
Außerdem wir noch ein Fehler mit dem Ointer ausgegeben:
main.c:48: warning: assignment makes integer from pointer without a cast
main.c:56: warning: passing arg 1 of `write_cr3' makes integer from pointer with
out a cast

MFG ReduX
« Letzte Änderung: 03. May 2007, 19:45 von ReduX »

FreakyPenguin

  • Administrator
  • Beiträge: 301
    • Profil anzeigen
    • toni.famkaufmann.info
Gespeichert
« Antwort #12 am: 03. May 2007, 20:00 »
Ok, wie befürchtet muss ich dich erstmal wieder darauf hinweisen, dass es nicht sehr geschickt ist, einen Kernel in C schreiben zu wollen, wenn man es nicht fliessend spricht.

Wo werden denn da mehrere Parameter übergeben? Meinst du das?:
write_cr0(read_cr0() | 0x80000000);
Da ist ja kein Komma dazwischen, sondern nur ein Binär-Oder.

Bei der zweiten Warnung kannst du entweder die Funktions-Deklaration für write_cr3 ändern, so dass es einen Long-Pointer nimmt, oder beim aufruf casten:

write_cr3((unsigned int)page_directory);
Auch für die 2. Warnung hilft ein einfacher cast:
page_directory[0] = (unsigned int)page_table;

ReduX

  • Beiträge: 19
    • Profil anzeigen
Gespeichert
« Antwort #13 am: 04. May 2007, 14:54 »
Hi,
Obwohl bei dem Befehl nur ein Binär Order und kein komma ist kommt trozdem immer der Fehler to few arguments for read_cr0 aber warum?
Wenn ich das ganze aufteile und den read befehl erst mit der 0x... laufen lassen und dannach dann den write mit dem 0x... dann stürzt der Rechner bei booten ab!

MFG ReduX

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #14 am: 04. May 2007, 19:26 »
Zeig mal den momentanen Code, ich glaub du hast für read_cr0 uberflüssige Parameter in der Funktionsdefinition.
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

ReduX

  • Beiträge: 19
    • Profil anzeigen
Gespeichert
« Antwort #15 am: 05. May 2007, 00:00 »
Hi,
Hier der gesamte Code der main.c:
unsigned long *page_directory = (unsigned long *) 0x9C000;
unsigned long *page_table = (unsigned long *) 0x9D000;

unsigned int read_cr0(unsigned int cr0)
{
    __asm__("movl %%cr0, %0" : "=a" (cr0));
   return cr0;
}

unsigned int write_cr0(unsigned int cr0)
{
    __asm__("push %%ebp" : "=a" (cr0));
    __asm__("movl %%esp, %%ebp" : "=a" (cr0));
    __asm__("movl 8(%%ebp), %%eax" : "=a" (cr0));
    __asm__("movl %%eax, %0" : "=a" (cr0));
    __asm__("pop %%ebp" : "=a" (cr0));
   return cr0;
}

unsigned int read_cr3(unsigned int cr3)
{
    __asm__("movl %%cr3, %0" : "=a" (cr3));
   return cr3;
}

unsigned int write_cr3(unsigned int cr3)
{
    __asm__("push %%ebp" : "=a" (cr3));
    __asm__("movl %%esp, %%ebp" : "=a" (cr3));
    __asm__("movl 8(%%ebp), %%eax" : "=a" (cr3));
    __asm__("movl %%eax, %0" : "=a" (cr3));
    __asm__("pop %%ebp" : "=a" (cr3));
   return cr3;
}

void main()
{

unsigned long address=0;
unsigned int i;

for(i=0; i<1024; i++)
{
page_table[i] = address | 3;
address = address + 4096;
};
page_directory[0] = (unsigned int)page_table;
page_directory[0] = page_directory[0] | 3;
for(i=1; i<1024; i++)
{
page_directory[i] = 0 | 2;

};

write_cr3((unsigned int)page_directory);
write_cr0(read_cr0() | 0x80000000);


  for(;;);
}

MFG ReduX

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #16 am: 05. May 2007, 06:32 »
so würde ich das machen:

unsigned int read_cr0()
{
    unsigned int cr0;
    asm volatile ("movl %%cr0, %0" : "=a" (cr0));
   return cr0;
}
void write_cr0(unsigned int cr0)
{
    asm volatile ("movl %0, %%cr0" : "=a" (cr0));
}
unsigned int read_cr3()
{
   unsigned int cr3;
    asm volatile ("movl %%cr3, %0" : "=a" (cr3));
   return cr3;
}
void write_cr3(unsigned int cr3)
{
     asm volatile("movl %0, %%cr3" : "=a" (cr3));
}

Ich muss FreakyPenguin mal wieder Recht geben: Bitte lern Sprache XY zuerst gescheit und dann fang mit einem Kernel an. So hat das nämlich keinen Sinn. Du verdrehst ja die Basissachen wie Funktionsrückgabewerte und Funktionsargumente, kennst die Syntax nicht wirklich, etc...
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

 

Einloggen