Oder ich mache doch erst morgens, übungen, NE555. Damit fange ich an. Ich mache heute eine Mesh - ich mache ein wenig Übungen, lerne. Ich fange mit dem NE555 an und lerne dann Minix. Dann schaue ich weiter.
Ich kann ihnen das erklären, zu Minix, nächster Beitrag, und was ich gedenke zu tun, achten sie auf die nächsten Beiträge.
Jetzt mache ich noch einen Vorschlag - ich mache Mathematik - das vorher war keine Kritik - das war auch kein mathematischer Vorschlag - weil, das ist keine Mathematik
Aber, ich schreibe halt jetzt Artikel. Jetzt gerade. Jetzt geht es um Minix. Es war keine Kritik. Das war nur ein Artikel was ich um Geld mache. Jetzt geht es um Minix
Der witz ist der - so einfach die automaten, FSM und Zustandsgraphen sind, so einfach ist am Ende auch Minix.
Also, wir haben, das müssen wir uns merken. Ein Prozess, also ein Programm - in Ausführung hat halt einen Kontext
Das heisst, beim 8086er gibt es halt Register - ax, bx, cx, dx, sp, bp, si, di
Und so weiter. Und die müssen gesichert werden. Deswegen - der Witz ist, dass man halt Variablen in der Mathematik hat und die heissen gerne
Code: Alles auswählen
x, y, z, x0, x1, x2, ...
Gut - und das bedeutet, wir habe in der Mathematik Variablen, die heissen
Code: Alles auswählen
x, y, z, x0, x1, x2, ..
auf der Rechten Seite, steht die Variable und auf der Linken steht der Funktionsausdruck. Der Funktionsausdruck ist ist ein Schaltnetz und die Variable ein Register
Und was macht das Steuerwerk. Das Leitwerk? Das ist ein Automat. Wir haben in der Mathematik die natürlichen zahlen
das sind
Code: Alles auswählen
1, 2, 3, 4, 5, ....
Ein Graph unterscheidet sich, der ja Automat ist - dass er mehr nachbarn haben kann, als eine natürliche Zahl und die nicht "fest vorgeschrieben sind"
Die Natürlichen Zahlen bilden eigentlich einen graphen, der geht so
Code: Alles auswählen
(1) -> (2) -> (3) -> ...
Code: Alles auswählen
{{1,2},{2,3}, ...}
Nur, was bei dem graphen eine Rolle spielt sind die nachbarn, es geht auch
Code: Alles auswählen
{{1,2},{1,8}..}
Steuerwerk ^= Graph
Rechenwerk ^= Natürliche Zahlen
Und vollständige Induktion gehört zu den natürlichen Zahlen
Jetzt haben natürlich alle Register namen. Die gehen üblicherweise so
Code: Alles auswählen
ax, bx, cx, dx, ...
a, b, c, d, ...
r0, r1, r2, r3
Das haben nicht die Computerhersteller erfunden - das ist so üblich
Und - jetzt der Witz, der 8086er hat halt Register, die heissen
Code: Alles auswählen
ax, bx, cx, dx, ...
Code: Alles auswählen
00000 -> 0
00001 -> 1
00010 -> 2
00011 -> 3
00100 -> 4
Code: Alles auswählen
ax, bx, cx, dx 4
si, di, sp, bp 4
ss, ds, es, cs 4
und so weiter. Und deswegen machen sie ein Array
Und bei Minix haben sie - zwei wesen, jetzt erst Mal, am Ende drei
1.) Den Kernel - der heisst kernel
2.) Den Speicherverwalter - der heisst mm
3.) Das Dateisystem - fs
So, und jetzt ist das entscheidende. Dass der 8086er basierte Computer, also zum Beispiel IBM 5160 - mit 8088er hat einen Baustein, der heist 8253 - es gibt den PIC8259A, das ist der Interrrupt Controller. Und der PIT8253, der ist ein Timer baustein. Das Ziel ist, dass er im abstand von gewissen Ticks ein Tick abgibt.
Und das geht so - der besteht aus drei Zählern. So weit ich weiss und ich es vermute, hat der IBM PC nur zwei Zähler in Benutzung und das hat einen Grund - dass wir die Uhr brauchen. Also ich denke, das vernächlässigt man gerne
Und es gibt Atmega8 und MIPS32, ihren eigenen. Da haben sie kein Dateisystem, zunächst mal. Dann ist ihnen das egal, um wie viel uhr die Datei gespeichert wurde. Das ist nicht egal, ob sie die Uhrzeit im Griff haben. Wir brauchen einen Timer für die Uhr
Und trotzdem brauchen wir den anderen Timer. Weil der Task Switch findet mit der Uhr statt. Das geht nicht anders, weil sie müssen ja die Ticks zählen. Wenn sie bei jedem Tick ein Interrupt machen, wie sollen sie die zählen, dann werden sie nicht weit kommen
Deswegen gibt es drei Zähler am PIT8253 - und davon werden zwei benutzt. einer für die Uhr und einer für den Kontext Wechsel. Und diese Zähler werden mit einer Zahl gefüllt. Entsprechend der Anzahl der Takte, wird der Zähler gezählt und löst danach über den PIC8259A, der Interrupt Controller, ein Interrupt aus
Die Interrupts sind eine einfache Sache. Es gibt drei Möglichkeiten. Code Methode, Vektormethode und Abfragemethode. Die Vektormethode wird hier genommen
Und das geht so. Sie haben ein Interrupt und es ist einfach, beim 8086er den Interrupt Verktor zu füllen
Man muss aufpassen, es gibt das Code Segment und den Offset. Der Ist glaube ich Little Endian gespeichert beim 8086er. und sie müssen - halt das multiplizieren mit ihrer Interrupt Nummer. Und da speichern. Und das sind 32 Bit, weil 16 bit Offset, 16 Bit Segment. Und da schreiben sie ein Interrupt für ihren Kontextwechsel
Und das machen sie, sie füllen den Interrupt Vektor, dann am Ende ihrer Interrupt Routine kommt ein IRET
Gut, das ist das.
Jetzt ist das gar nicht unwichtig - dass wir die Datenstruktur haben. Die geht so - dass wir den Kompletten Kontext des Prozesses Speichern.
Dazu gehören die Register. Und die werden eben durchnummeriert. Und so werden sie in dem Kontext gespeichert
Sie haben eine Struktur
Code: Alles auswählen
struct proc {}
Code: Alles auswählen
struct mproc {}
m steht für memory Manager. Die Strukturen sind relativ identisch.
gut - und proc steht für Prozess
Jetzt lauten die Elemente darin
Code: Alles auswählen
mp_pid
p_pid
mp - das heisst, Memory Manager. P - Proc
gut und da ist typisch
Code: Alles auswählen
mp_pid
mp_effgid
mp_effuid
mp_realuid
Und für die Segment
Code: Alles auswählen
mp_reg [NUM]
NR_REGS steht für die Anzahl er Register.
und dann haben sie den speicher, weil sie haben 3 Segmente
Code: Alles auswählen
CS, DS, ES, SS
Und das heisst, sie haben
Code: Alles auswählen
mem_map [NR_SEGS]
Und - ja - dieses Speicherabbild, liefert den Anfang und die Länge des Segments
Gut - das alles muss beim Kontextswitch stattfinden, dass die Tabelle bleibt erhalten es gibt davon
Code: Alles auswählen
NR_PROC
Code: Alles auswählen
NR_PROC + NR_TASK
und
Code: Alles auswählen
NR_PROC
Das ist die Anzahl der Prozesse
Gut - und der witz ist - dass damit der Kontextwechsel vollzogen wird. Gut - und der andere Witz ist , dass wir im Speichermanager, Funktionen haben, wie
Code: Alles auswählen
alloc_mem ()
free_mem ()
Es gibt die üblichen Systemaufrufe
Code: Alles auswählen
fork (), exit (), exec (), alloc (), free (), break (), signal ()
Und in der alloc.c gibt es halt die
alloc () schlecht hin, was in C nachher malloc () ist und realloc() und calloc ()
Und natürlich braucht es - hilfsfunktionen - es heisst nicht free (), sondern free_mem () und es ist wichtig, dass diese funktionen nicht für C Programme selber sind, das betriebsyssystem braucht sie
was macht exec () speziell. Der Witz ist, wir haben das Programm auf der Platte - das hat aber weitere Infos. Einen Kopf und so weiter.
Und wir müssen das laden. Deswegen ist fs nicht ohne Sinn. Das bedeutet - wir müssen so zu sagen - das Programm einlesen. Dabei gibt es natürlich Kopfdaten. Die sind auf der Platte notwendig. Aber die sind nicht im Prozess. Wenn man sich
./a.out
Oder bei DOS exe anschaut. Und die müssen geladen werden. Im zweiten Schritt gehen sie in den Speicher. Dafür brauche ich alloc. Und ich muss es kopieren
Ich bin gerade beim Speicherverwalter.
Ich weiss, über die Strukturen bescheid, aber ich bin gerade beim Speichervewalter.
Der Witz ist ich fange jetzt an. Ich mache kurz einen Tagesüberblick
1.) Ich lerne auswendig, von der Tätigkeit
2.) Ich schreibe Minix ab, von der Tätigkeit
3.) Ich schreibe Algorithmische Mathematik
4.) Ich mache das NE555, Schaltung
5.) Ich mache Algorithmische Mathematik Aufgaben
Also, auswendig lernen, tue ich
1.) Die Bausteine, aber da bin ich gerade nicht, das geht ja im Kreis. Ich bin gerade an einer anderen stele
2.) Ich lerne Minix
3.) Ich lerne Algorithmische Mathematik
Dann kommt schreiben
1.) Algo Mathematik
2.) Minix, damit fange ich an - ich erläutere das
Dann kommt
1.) Bauen - NE555
Dann kommt
1.) Aufgabe: Algorithmische Mathematik, die von der Uni gestellten
2.) Vollständige Induktion, Übung
Dann habe ich das. Und wenn ich das habe - dann halt die üblichen. Aber erst Mal nicht
Und - jetzt geht das so - ich fange jetzt an, mit Minix
Dazu kommt
1.) Das was ich bisher habe,
2.) Die Funktionen für den Speicherverwalter, aber nur alloc.c
3.) Die klib88.s schaue ich mir genau an und die mpx88.s
4.) Wenn ich das habe noch die tty irgendwas
Und ich möchte mir einen Blick vom exec () und so machen
5.) Ich möchte folgendes als erstes haben, die PROC Strukturen müssen da sein. Also die müssen so am Stück da sein
OK, damit fange ich jetzt an.
Ich wollte ja was erzählen. Der Speicherverwalter bei Minix ist einfach. Es werden halt Prozesse geladen und ausgeladen. Und - dabei enstehen Löcher. Minix macht das einfach. Es nimmt das nächste freie passende Loch und geht dafür die Liste von Anfang bis Ende durch.
So, jetzt mache ich weiter.
Also, das erste, was mir auffällt, wir zum Beispiel eine kernel/floppy.c datei. Das hat ja mit Dateisystem auch nichts zu tun. Trotzdem eher Dateisystem. Das sind unsere Geräte
Und - ja, das sind Geräte, die gehören zum Kernel
Und was mir auffällt, wir haben bei kernel/tty.c
so funktionen, wie
Code: Alles auswählen
do_write ()
do_read ()
...
Aber ich würde gar nicht so sehr in die Funktion rein gucken
Ich würde nicht gucken, was
Code: Alles auswählen
do_read ()
Also, mache ich noch mehr dazu. Ich schreibe jede Funktion ausserhalb der fs auf
wo sie sind.
Und - noch mehr - programmieren heisst, ja logisch denken. Das heisst, wir entwickeln den Binomialkoeffizient im Kopf
Ich denke, dass namen sehr wichtig sind. Und ich würde die
Code: Alles auswählen
const.h
Ich probiere jetzt eine gescheihte aufstellung zu machen.
Also, was ich beim Betriebssystem nicht verstehe, was sind Botschaften
Ich hatte mal den Kurs Betriebssysteme und Rechnernetze belegt. Ich fand ihn sehr einfach
Da wurde aber extrem auf Botschaften rumgearbeitet. Ich finde ihn sehr einfach. Aber da kam, Semaphore und da ging es sehr darum, wie man ein Signal sendet, ohne, dass es zur Kollesion kommt. Ich weiss nicht, wie ich mir Botschaften in der Realität beim OS vorstellen muss.
Das lohnt sich vielleicht dieses MINIX hier an zu gucken. Es gibt ja die signal.c, ich habe keine Ahnung, ob das da hingehört
Und - ich weiss nicht, vielleicht sind die Botschaften in der Realität so kompliziert oder vielleicht nicht
Und jetzt sehe ich hier - mpx88.s die Prozess und Botschaftsverwaltung findet von hier aus statt
Der Kurs hat mir mehr oder weniger erklärt, dass Prozesse kommunizieren. Was ich davon in Linux weiss, ist dass wir Umleitungen haben oder so
Ich habe keine Ahnung. Jetzt steht hier Interrupts. Und - ehrlich gesagt - ich vermute, wenn ich das so sehe, dass die von aussen ausgelösten Interrupts zu den Botschaften gehören
wir haben ja, die maskierbaren Interrupts. Und die NMI - Non Maskable Interrupts
Und - ich denke, wenn diese Interrupts auftreten, dann müssen die ja unter Umständen nacheinander abgearbeitet. Wenn Prozesse miteinander kommuniezieren, tun sie das über die E/A
Und ich vermute, da liegt das Geheimnis
Ich sage, erst lernen, was lernbar ist, ich mache erst das andere. Und lerne den Spruch mpx88.s ohne zu gucken
ist für Botschaften und Prozesse unterhalt der proc.c zuständig.
Da stehen tatsächlich gewisse Interrupts, fällt mir jetzt auf. Da steht
_s_call erst Mal, das sagt so nichts - aber da steht - hier laufen Systemaufrufe zusammen
Dann steht da
Code: Alles auswählen
_tty_int
_lpr_int
_disk_int
_wini_int
_clock_int
Und lustig ist, dass ich in Computersysteme I/II zu letzt gelernt haben, dass Interrupt Handler, nicht das Gleiche ist, wie Device Handler
Das heisst, der Interrupt Handler, ist das ganze Ding und der Device Handler, für das einzelne Gerät.
Und da muss man sehr genau lernen, auch, Vektormethode und Codemethode
Und ich würde nicht sagen, das ist der der Device Handler. Weil hier werden die Device Handler aufgerufen. Der Device Handler, ist die Interrupt Routine die folgt
Und was ich hier sehe, ist etwas, wie
Code: Alles auswählen
mov ax, *WINI
push ax
call _interrupt
Und dann sehe ich
Code: Alles auswählen
call _keyboard
call *CLOCK
call *WINI
call *FLOPPY
call _interrupt
Code: Alles auswählen
MINIX:
Das beste wäre. Ich verzichte auf das zu genaue auswendig lernen, sondern
ich merke mir
Code: Alles auswählen
MINIX:
lpr_int:
wini_int:
tty_int:
clock_int:
Code: Alles auswählen
_divide:
und surprise - bei nicht erkannten Interrupts. Gut .
klib88.s sind einfach Hilfsroutinen. Für Byte auf Port ausgeben und Byte von Port einlesen und so weiter.
Code: Alles auswählen
/* -- ich finde das kann man sich gut merken -- */
h/const.h
#define EXTERN extern
#define PRIVATE static
#define PUBLIC
#define FORWARD
#define TRUE 1
#define FALSE 0
...
#define BLOCK_SIZE 1024
#define SUPER_USER (uid) 0
#define MAJOR 8
#define MINOR 0
#define NR_TASKS 8
#define NR_PROCS 16
#define NR_SEGS 3
Dann mache ich das so - dass ich die Dateien aufliste
Alle. Und dann mache ich das so, wo ich will, schreibe ich die Funktionen rein, die da sind und nur bei mpx88.s weil das so einfach ist, mache ich noch von denen Routinen, den Code
Dann mache ich - von der alloc.c mache ich die Funktionen, dass sie wirklich sind
Und halt die Definitionen und wichtig die Strukturen. weniger die Funktionen, mehr die Struktur.
Ich vermute, nachdem ich jetzt das hier habe - das Botschaften einfach so etwas, wie IN und OUT sind, Assembler Technisch, das heisst, die Kommunikation mit einem Gerät, mit IN und OUT, das schliesst, die Interprozesskommunikation mit ein
Und was die Dame so kompliziert an Semaphoren erklärte, das scheint bei Linux auf zu tauchen, scheint aber, ein Problem auch auf der Seite der Hardware zu sein, etwa, wenn sich beide gleichzeitig melden. Gerät und Prozessor
Und - ich denke, das ist nichts anderes, als IN und OUT, Befehle zur Kommunikation mit Hardware.
h/com.h
Wichtig, Definitionen f"ur Systemaufrufe
Botschaften
Code: Alles auswählen
SEND /* Code fuer Botschaften verschicken */
RECEIVE /*
BOTH
ANY
Das heisst, Command Data. Das heisst, entweder ich sende einen Befehl oder ich sende ein Datum. Und ich habe mal gesagt, dass das LCD am Ende von dem PATA nicht so unterschiedlich ist. Wir müssen ja, an die Festplatte senden, wollen wir lesen oder schreiben.
gut, das klingt easy. Blos - Bei dem LCD ist das klar. Nur, bei der Festplatte, wir haben ja die Nutzdaten, einfach Daten die Drauf stehen. Die Festplatte muss ja auch wissen, wird von ihr gelesen oder geschrieben, wie das LCD - Command oder Data. Und daneben, halt, es gibt Befehle an das LCD
Ich vermute, Botschaft, wenn ich das so lese, bei Minix, bedeutet, DISK_READ, DISK_WRITE, das sind nicht die Daten, sondern es geht die Botschaft, lesen, schreiben
Und - da reicht das IN OUT nicht einfach. als befehl. Weil das ist ja nur, dass nicht MOV, was sonst LD, SD oder MOV ist, in den RAM schreibt oder liesst, sondern an die EA. Die Memory Mapped ist. Dass heisst, Addressen verwenet, für PORTS. Damit habe ich nicht erreicht, dass ich der Festplatte sage, lesen oder schreiben.