Eigenes OS?
-
Erhard Henkes schrieb:
Ist das ein ernsthaftes Problem? Beim verwendeten DJGPP entspricht int nämlich 32 Bit. ...
Für PC-Programmierer ist es wahrscheinlich kein Problem.
Bei dem Compiler, den ich grade verwende (verwenden muss ;)), ist z.B. sizeof(int) == 4 (32 Bit) und sizeof(long) == 5 (40 Bit)...
-
Bei dem Compiler, den ich grade verwende (verwenden muss ;)), ist z.B. sizeof(int) == 4 (32 Bit) und sizeof(long) == 5 (40 Bit)...
Danke für das Feedback. Momentan möchte ich diese Zahlen in den Typen vermeiden. Bei seltsamen Breiten von long kann man ja in os.h im typedef von long auf int umschalten, oders ehe ich das verkehrt?
Ich habe da noch eine Warnung im Compiler, bei der ich nicht ganz sicher bin, wie man sie am saubersten abschaltet:
ULONG fetchESP() { asm ( "mov %esp,%eax" ); }
Verwendung:
printformat("SS: %x, ESP: %x, EBP: %x\n", fetchSS(),fetchESP(),fetchEBP());
Warnung:
control reaches end of non-void function
Wie muss die Rückgabezeile aussehen? Ich möchte nicht void* als Rückgabewert verwenden, sondern ULONG, das in PrettyOS für 32-Bit-Speicheradressen Verwendung findet.
Selbe Frage wie hier: http://www.c-plusplus.net/forum/viewtopic-var-p-is-1697586.htmlIch habe mal folgendes probiert, was offenbar funktioniert, bin bei der AT&T Syntax nie ganz sicher, aber offenbar wird es langsam:
ULONG fetchESP() { register int eax asm("%eax"); asm volatile ( "movl %esp,%eax" ); return eax; }
Benötigt man hier movl oder geht auch mov? Ist asm volatile notwendig?
-
Noch ein Punkt: Ich möchte "Files" in die kommende "RAM disk" laden und dort mit dem virtuellen Filesystem bearbeiten. Dabei habe ich die Aufgabe eine bin- oder img-Datei von Floppy (hat nicht jeder) oder Festplatte (gefährlich bei Fehler) an eine feste Stelle im Speicher zu laden. Dies erfolgt typisch mittels GRUB, unser System soll ja aber ohne GRUB laufen. Welches Tool nimmt man da bei MS Windows in makefile, um ein file.img (sagen wir mal von Festplatte) sicher an eine bestimmte Stelle im RAM zu transportieren?
-
Erhard Henkes schrieb:
Danke für das Feedback. Momentan möchte ich diese Zahlen in den Typen vermeiden. Bei seltsamen Breiten von long kann man ja in os.h im typedef von long auf int umschalten, oders ehe ich das verkehrt?
Was ist dann der Sinn und Zweck von diesen Typdefinitionen... Man strebt eine gewisse Portabilität, z.B. mit der folgenden Typdefinition:
typedef long LONG;
weiss man immer noch nicht, wie viele Bits soll denn ein LONG sein? 32, 40 oder 64 Bit? Es geht ja nicht darum, den Typ long irgendwie zu verstecken, sondern "neue" Typen einzuführen, wo man genau weiss, dass sie so und so viele Bits breit sind.
Erhard Henkes schrieb:
Ich habe da noch eine Warnung im Compiler, bei der ich nicht ganz sicher bin, wie man sie am saubersten abschaltet...
Was würde dagegen sprechen, diese Funktion ganz in Assembler zu realisieren. Diese asm im Quellcode ist wie ein Dorn im Auge Wieder mal meine Phylosophie...
Also in Assembler z.B. so:.global _fetchESP .section .text _fetchESP: movl %esp, %eax ret
Assemblieren geht so:
as datei.s -o datei.o
Dann in irgendeiner Header Datei dem Compiler sagen, wie die Funktion aussieht:
extern uint32_t fetchESP(void);
Und die Objektdatei datei.o noch beim Linken angeben...
Erhard Henkes schrieb:
Benötigt man hier movl oder geht auch mov? Ist asm volatile notwendig?
Bei Befehlen, bei denen der Assembler erkennen kann, wie breit die Operanden sind, kann man l (steht für long) auch weglassen. Ich persönlich mach das nicht, weil defensive Programmierung usw.
-
Diese asm im Quellcode ist wie ein Dorn im Auge
Dank der AT&T Syntax sicherlich. Dafür hat es den Vorteil, dass man den Code im gleichen Modul betrachten kann. In obigem Fall sicher nicht so kritisch, da sprechende Funktionen.
In PrettyOS haben wir eine Mischung aus beidem, so dass der geneigte Leser/Entwickler selbst entscheiden kann, wie er es gerne hätte.
-
Erhard Henkes schrieb:
Diese asm im Quellcode ist wie ein Dorn im Auge
Dank der AT&T Syntax sicherlich. Dafür hat es den Vorteil, dass man den Code im gleichen Modul betrachten kann.
Für mich nicht wegen der AT&T Syntax, sondern wegen diesem gcc-spezifischen Inline und der ganzen Schar von Regeln, die man dabei beachten muss. Diese c-Datei ist nun auf den gcc-Compiler festgenagelt, was ja der Philosophie der C-Sprache, im Sinne höhere Sprache, plattformunabhängig, portabel usw., widerspricht...
-
Ja, das ist ein Argument.
..
Was mir am meisten fehlt, ist eine standardisierte Diagnose-Funktion für die Memory-Darstellung. Vielleicht muss ich da meine "ODA" noch mit ein paar Daten auf Stand halten, die ich dann bei Bedarf loggen kann. Hauptproblem sind momentan page faults.
Das mit dem FIFO (20 Keys) bei den Tasten-Infos hat ja sehr gut geklappt. Danke für den Vorschlag. Die exakte Auswertung der Scans kann man später noch ausgefeilt aufbauen, wenn die Anwendungen (z.B. eine Shell) diese wirklich brauchen.
-
..
-
Das hier ist z.B. die "niedliche" Umschaltung auf User Mode. Da hinten dran wühle ich gerade herum. Jetzt fehlen noch brauchbare syscalls usw. Kämpfe noch mit page faults, weil der user nicht einfach auf kernel code zugreifen darf. PM schlägt voll zu (schön!). Endlich passt alles zusammen.
..
Danach hat man allerdings keinen direkten Zugriff mehr auf den eigenen Code in ckernel.c! Wenn man nach dem Umschalten in den user mode nicht per "page fault" ausgehebelt werden will, muss man dem user sozusagen Supervisor-Rechte geben, funktioniert voll!
..
-
Fragen:
- Welche Privilegstufen sollte man einrichten? Nur 0 und 3, oder auch 1 und 2?
--- Kernel (0) und User (3) ist klar, wozu sollte man den Rest nutzen?
- Wie würdet ihr die "sys calls" (call to the kernel) praktisch einrichten?
--- software interrupt (linux: 0x80), ich würde 0x7F bevorzugen wegen der unsigned char Begrenzung in unserem OS?
-
Erhard Henkes schrieb:
Frage: Wie würdet ihr nun die Syscalls praktisch einrichten?
x86'er haben spezielle befehle dafür: http://www.ews.uiuc.edu/~cjiang/reference/vc311.htm
-
Danke für den Link! Was hältst Du von der Software-Interrupt-Methode (software interrupt bei Linux: 0x80), ich würde allerdings 0x7F bevorzugen wegen der aktuellen Begrenzung auf 0..127 in unserem OS?
-
Erhard Henkes schrieb:
Was hältst Du von der Software-Interrupt-Methode ...
geht im prinzip auch, aber sysenter ist schneller. diese software-interrupt methode funzt ausserdem sogar auf 368'ern. 'sysenter' gibt's ja erst ab pentium-ähnlichen und späteren intel- und AMD-prozessoren. aber ich bin nicht so der x86-freak, warten wir doch mal ab, was nobuo dazu zu erzählen hat.
btw: bei syscalls musste extrem drauf achten, dass du keine backdoors einbaust. das problemchen hatten z.b. die ersten versionen von win-nt 4, die man mit zufallsparametern in syscalls crashen, oder sehr einfach code in den kernel einschleusen konnte. daher auch der imageverlust von windoofs, an dem mickrigsoft bis heute zu knabbern hat.
-
Na, klasse! Bereits die erste Sicherheitsdiskussion. ..
'sysenter' gibt's ja erst ab pentium-ähnlichen und späteren intel- und AMD-prozessoren.
Eines meiner Ziele ist, dass PrettyOS ab 80386 lauffähig ist, denn die späteren CPU haben an der prinzipiellen inneren Technik (GDT, IDT, ...) fest gehalten. Daher auch die komplizierte Umschaltung von einem Gate auf das andere, die bei modernen Pentiums hoffentlich leichter geht.
-
also ich würde euch empfehlen, das ganze über interrupts zu machen. da gibts dann später bei multitasking keine probleme, da bei einem interrupt autamtisch das i-flag in den eflags gelöscht wird, sodass der kernel nicht unterbrochen werden wird, bis er zumindest einen stack gewechselt hat bzw. bis ihr das halt wieder zulasst... Aber nachdem das ja ein Sprung in den Kernel ist, könnte es sein, dass dann zwei Tasks gleichzeitig springen und im Kernel dann Datenstrukturen zerstört werden, weil das nicht synchron geschieht.
Aber das ist nur meine bescheidene Meinung
-
Die Interrupt-Technik habe ich bereits vorbereitet (0x7F = 127).
..
Danke an alle, die mich bisher soweit getragen haben.
Jetzt habe ich soviel OS-Blut geleckt, dass ich keinesfalls aufhöre.
Diesem Assembler-Forum möchte ich für seine konstruktive und offene Haltung ein ganz großes Lob aussprechen. Das findet man sehr selten!
-
blitzmaster schrieb:
also ich würde euch empfehlen, das ganze über interrupts zu machen. da gibts dann später bei multitasking keine probleme, da bei einem interrupt autamtisch das i-flag in den eflags gelöscht wird, sodass der kernel nicht unterbrochen werden wird...
interrupts global zu sperren (macht man das mit dem i-flag?) ist, wenn nicht unbedingt erforderlich, eigentlich keine gute idee, weil dann interrupt-anforderungen verloren gehen können, wenn die sperre zu häufig eingesetzt wird oder lange dauert. und ich weiss nicht, ob die pc-architektur 'nested' interrupts und interrupt-prioritäten kennt (ich glaub' die hardware unterstützt es nicht, aber es geht mit software-tricks).
blitzmaster schrieb:
Aber nachdem das ja ein Sprung in den Kernel ist, könnte es sein, dass dann zwei Tasks gleichzeitig springen und im Kernel dann Datenstrukturen zerstört werden, weil das nicht synchron geschieht.
in einem multitasking-os sollten systemfunktionen sowieso immer reentrant-fähig sein. dass mehrere task gleichzeitig im kernel rumschwirren, oder gar die selbe systemfunktion nutzen, ist keine seltenheit.
-
in einem multitasking-os sollten systemfunktionen sowieso immer reentrant-fähig sein. dass mehrere task gleichzeitig im kernel rumschwirren, oder gar die selbe systemfunktion nutzen, ist keine seltenheit.
Klingt wirklich herausfordernd, erinnert mich an multithreading. Da lauern neben "malicious codes" bestimmt schon die "deadlocks".
interrupt-prioritäten
Je kleiner die Zahl, je höher die Priorität, zumindest habe ich es so gelesen. Also Timer > Keyboard > ...
Hat eigentlich jemand einen Tipp, wie ich "Files" - ohne GRUB - möglichst einfach in diese RAM disk tranferieren kann, so dass man den VFS-Mechanismus mal vorführen könnte?
-
+fricky schrieb:
blitzmaster schrieb:
also ich würde euch empfehlen, das ganze über interrupts zu machen. da gibts dann später bei multitasking keine probleme, da bei einem interrupt autamtisch das i-flag in den eflags gelöscht wird, sodass der kernel nicht unterbrochen werden wird...
interrupts global zu sperren (macht man das mit dem i-flag?) ist, wenn nicht unbedingt erforderlich, eigentlich keine gute idee, weil dann interrupt-anforderungen verloren gehen können, wenn die sperre zu häufig eingesetzt wird oder lange dauert. und ich weiss nicht, ob die pc-architektur 'nested' interrupts und interrupt-prioritäten kennt (ich glaub' die hardware unterstützt es nicht, aber es geht mit software-tricks).
Jo, das IF ignoriert praktisch die IRQ-Line der CPU (nicht aber NMIs, exceptions, usw.).
AFAIR: Selbst der PIC (programmable Interrupt Controller) in den ersten PCs kannte schon eine Prioritaetsbehandlung von IRQs. Das Ding wurde dann zunaechst in typischer x86-manier erweitert, indem man quasi den gleichen Controller nochmal hinten dran geklatscht hat (toll: jetzt mit 16 IRQs!!) und inzwischen gibt es den in die CPU integrierten APIC.
IAR geht also nichts verloren, wenn das IF geloescht wird ... es sei denn, das bleibt ueber Sekunden so (daher auch meine Ermahnung, schnelle IRQ-handler zu schreiben).
Dennoch hast du recht: IRQs sollte man nur ausschalten, wenn unbedingt noetig, was bei x86ern mit ihren ganzen atomaren spezial-Befehlen im Prinzip relativ selten vorkommen duerfte.+fricky schrieb:
blitzmaster schrieb:
Aber nachdem das ja ein Sprung in den Kernel ist, könnte es sein, dass dann zwei Tasks gleichzeitig springen und im Kernel dann Datenstrukturen zerstört werden, weil das nicht synchron geschieht.
in einem multitasking-os sollten systemfunktionen sowieso immer reentrant-fähig sein. dass mehrere task gleichzeitig im kernel rumschwirren, oder gar die selbe systemfunktion nutzen, ist keine seltenheit.
Richtig. Da kann man entweder alle moeglichen Teile des Kerns einzeln in kritische Sektionen packen, oder man tuetet den ganzen Kern einfach in eben eine solche. Zu Demonstrationszwecken im Rahmen eines Tutorials waere das IMHO uebersichtlicher. Dabei kann man dann auch problemlos IRQs zulassen.
Int loescht uebrigens nicht das IF. AFAIR sysenter genau so wenig.
Die Entscheidung gegen sysenter und fuer int befuerworte ich uebrigens (wie ich schon sagte) : Kein neuer Spezial-Befehl, Gebastel mit AMD vs. Intel, einfache Handhabung, abwaertskompatibel. KISS halt.BTW ist die Benutzung eines eigenen Stacks fuer Kern-Aufrufe (auch IRQ- und Exception-Handler) wie gesagt dringend zu empfehlen. Praktisch fast wie ein TASK-Switch.
-
Nobuo T schrieb:
Int loescht uebrigens nicht das IF. AFAIR sysenter genau so wenig.
So weit ich weiß, wird das IF bei einem Sprung zu einem Interrupt Gate gelöscht.