Beiträge anzeigen

Diese Sektion erlaubt es dir alle Beiträge dieses Mitglieds zu sehen. Beachte, dass du nur solche Beiträge sehen kannst, zu denen du auch Zugriffsrechte hast.


Nachrichten - Svenska

Seiten: 1 ... 3 4 [5] 6 7 ... 90
81
Offtopic / Re: Rutsch ins 2016
« am: 31. December 2015, 22:56 »
Jo. :-)
82
Du kannst im Qemu-Monitor mit "info tlb" und "info mem" nachschauen, wie deine Page Tables interpretiert werden. Das ist sehr hilfreich, um sowas schnell nachzuprüfen.

Später wird das Thema VMM eher eine Politikfrage. Wenn deine Routinen stehen, kannst du dich mal mit den Vor- und Nachteilen eines "higher-half kernels" befassen und damit, wie man am besten mit Pagefaults umgeht, bzw. wie man sie sinnvoll einsetzt.
83
(a) Du kannst in deine Binaries reinschreiben, wieviel Speicher sie maximal belegen dürfen, und reservierst dann den entsprechenden Speicher beim Programmstart vor. Das ist der klassische UNIX-Ansatz, der die Speicherverwaltung auf den BRK/SBRK-Syscalls aufbaut. Wenn hinter dem Programm noch Platz ist, kannst du das Datensegment (und damit den Heap) auch dynamisch vergrößern. Nachteil: Die meisten Programme verschwenden Speicher, und Programme werden - je nach Input - sterben. (Der Stack nutzt übrigens zwingend diesen Ansatz.)

(b) Der Heap muss aber nicht an einem Stück vorliegen und darf damit auch über mehrere Segmente verteilt sein. Du reservierst einfach eine gewisse Menge an Speicher und wenn das Programm zusätzlichen Speicher mittels malloc() anfordert, dann beschaffst du einfach ein zusätzliches Segment mit mehr Speicher. Nachteil: Plötzlich sind deine Pointer nicht mehr linear, sondern bestehen aus Adresse und Segmentnummer. Damit kommt so gut wie kein moderner Compiler klar. (Vielleicht Watcom C/C++?)

(c) Wer braucht schon Speicherschutz für den Heap? Du legst ein globales Segment für den Heap an, und beantwortest alle Anfragen aller Prozesse aus diesem Segment (Memory Pool). Linux auf NOMMU-Architekturen (uClinux) macht das so, um möglichst wenig Speicher zu verschwenden. Nachteil: Wenn dein Heap zu sehr fragmentiert, kannst du nichts dagegen tun.

Dynamischer Speicher ist dynamisch, und damit anwendungs- und datenabhängig. Mit Segmentierung allein wirst du keine gute Lösung mit Speicherschutz bekommen können, solange du nichts über deine Anwendungen weißt.

Beispiel: Speicherfragmentierung auf eingebetteten Systemen ist meist kein Problem, weil Prozesse in der Regel nur beim Systemstart gestartet werden und der Speicherverbrauch relativ statisch ist (solche Systeme sind oft kritisch und dürfen daher keinen out-of-memory wichtiger Dienste erleben und sind daher entsprechend aufgebaut).
84
OS-Design / Re: Streamids
« am: 15. October 2015, 14:05 »
Windows NT ist ein POSIX-Betriebssystem. ;-)

Im Gegensatz zu Linux sind Windows NT 3.5, NT 3.51 und NT 4.0 selbst POSIX-zertifiziert. Spätere Versionen sind das meines Wissens dann, wenn die "Services For UNIX" (Interix) installiert sind. In den 80ern hat die US-Regierung POSIX in die IT-Anforderungsliste geschrieben, also wurde Windows dafür zertifiziert (Wikipedia).

Neben Win32 und POSIX implementiert Windows NT auch eine dritte Personality, nämlich OS/2 1.x (allerdings ohne den Presentation Manager, d.h. nur Text).
85
OS-Design / Re: Streamids
« am: 15. October 2015, 03:23 »
Die Frage war, ob das irgendwo definiert ist, dass das so sein müsse, weil alle hinreichend relevanten Betriebssysteme das tun. Die Antwort ist "ja, in POSIX".
86
OS-Design / Re: Streamids
« am: 14. October 2015, 12:53 »
Der POSIX-Standard verlangt, dass open() den niedrigsten freien File-Descriptor zurückgibt (Quelle).
87
Softwareentwicklung / Re: GCC für OS compilieren
« am: 26. July 2015, 01:09 »
Ist das Absicht, dass in deinem Script was von i386 und elf32 steht?
88
Da ich selbst mit dem System Raspbian sehr unzufrieden bin! Wegen der Bootdauer, der Initialisierung des Desktops und der rechen zeit einzelner Daten !
Normale Betriebssysteme sind eigentlich fast nie CPU-begrenzt, sondern I/O- und Speicher-begrenzt. Auf dem Prinzip basieren batteriebetriebene Geräte (die CPU braucht nahezu keinen Strom, weil sie fast nichts zu tun hat, also ergibt sich die Akkulaufzeit relativ genau aus dem Stromverbrauch von Display, RAM und Flash). Daher - wie Jidder schrieb - wirst du deine CPU auch mit einem extrem effizientem Betriebssystem nicht nennenswert effektiver ausnutzen können als mit Raspbian. Der Linux-Kernel ist schon ziemlich effizient.

Der Rest des Systems ist das aber nicht. Du kannst dir also auf Basis von Linux eine eigene Distribution schreiben, die z.B. weniger auf Kompatiblität achtet und dafür schneller ist. Gute Optimierungsziele wären "möglichst wenig Zugriffe auf die SD-Karte", "möglichst viel RAM für den Plattencache frei lassen", "möglichst effiziente Programme benutzen, oder Programme beschleunigen". Das Hauptproblem solcher Teile sind die SD-Karten.

Kleine Programme brauchen weniger Zugriffe, um vom Massenspeicher gelesen zu werden (z.B. Busybox statt GNU coreutils). Manche Programme murksen viel ohne Cache auf relativ wenigen Daten rum und bremsen sich dadurch selbst aus (z.B. Firefox und dessen Profil, weil das Datenbanken sind). Lagere mal das Firefox-Profil in eine Ramdisk aus und staune, wie schnell der Misthaufen plötzlich ist. Die meisten Flash-Speicher mögen auch keine verteilten Zugriffe (random access). Wenn man die Zugriffe vorher am Stück durchführt und erstmal in einen Cache liest, ist das schneller (probiere mal "readahead" aus, das beschleunigt den Bootvorgang). Und zu guter Letzt ist auch Paging/Swapping für Flash-Speicher unangenehm, weil (a) viele Zugriffe, (b) verteilte Zugriffe, (c) das System steht währenddessen. Das zu vermeiden sollte oberste Priorität haben, also solltest du immer die Speicherauslastung im Blick haben und gegensteuern (auch ein zram kann Wunder wirken).

Wenn es dir also am Herzen liegt, dein Raspberry zu beschleunigen, gibt es wesentlich bessere Ansätze als ein eigener Kernel: Ein eigenes Betriebssystem auf einem vorhandenen Kernel ist auch viel Arbeit, verspricht aber auch viel bessere Leistung.

Gruß,
Svenska
89
Offtopic / Re: 4Bit Rechner im Logisim
« am: 04. May 2015, 23:05 »
Hi,

ich hatte mal angefangen, einen Prozessor in KLogic zu entwerfen, aber bin recht schnell an die Grenzen der Software gestoßen (wurde langsam und instabil), und habs dann wieder sein lassen.

Das System wäre mir ein bisschen zu klein (16 Instruktionen/Programm, 16 Byte RAM und keine Möglichkeit für I/O ist arg beschränkt). In einem Simulator bist du nicht auf die Chipzahlen beschränkt, also kannst du ohne Probleme eine 8-Bit-CPU mit einem 12-Bit Bus bauen (also 4 Bit für den Opcode, 8 Bit für Immediates und Adressen, also 256 Byte RAM). Da wäre dann auch genug Platz, um eine 7-Segment-Anzeige (o.ä.) mit anzuknoten.

Gruß,
Svenska
90
Softwareentwicklung / Re: GCC für OS compilieren
« am: 19. April 2015, 12:56 »
Wenn du deine eigene libc verwendest, dann hast du keine newlib. Und ja, das funktioniert natürlich auch.
91
OS-Design / Re: Konsolen
« am: 12. April 2015, 01:48 »
Programme schreiben auf "Terminals". Das können virtuelle Terminals (ttyX), Pseudo-Terminals (ptyX), serielle Terminals ("echte" Terminals), oder sogar an Telefonleitungen angeschlossene Modems sein, die man dann anrufen kann. Pseudo-Terminals werden ständig erzeugt und vernichtet, alle anderen Terminals bleiben dauerhaft erhalten. Diese werden von einem "getty"-Prozess verwaltet, der im Boot-Prozess gestartet (klassisch: in /etc/inittab definiert) und automatisch neu gestartet wird, wenn er endet.

Getty stellt die Schnittstelle ein: Baudrate, Flusskontrolle. Dazu für virtuelle Terminals (je nach Kernel) die Terminalemulation, für serielle Schnittstellen Datenformat und Parität, für Modems Modemtyp, Initialisierung, und so weiter. Danach startet das getty meist einen "login"-Prozess auf diesem Terminal, mit dem man sich auf diesem Terminal einloggen kann. Terminalmultiplexer oder -emulatoren erzeugen Pseudoterminals und starten darin das Programm selbst, meist eine Shell.

Der Linux-Kernel erzeugt beim Start keine virtuellen Terminals, sondern nur /dev/console. Die anderen virtuellen Terminals werden erst im Bootsystem erzeugt, wobei tty1 dann die console übernimmt.
92
Aber ein PCI Gerät kann in den BARs auch nach IO-Ports verlangen. Das wird durch eine 1 in Bit 0 im BAR angezeigt. ein Massenspeichercontroller für ATA oder SATA würde da z.B. die standard Ports 0x1F0 bis 0x1F7 haben.
Ja, bei solchen Geräten weißt du dann genau, dass an den betreffenden I/O-Ports ein Gerät hängt und brauchst nicht rumzuprobieren. ;-)
93
Zitat
Das weiß ich nicht. Ich kann mir aber gut vorstellen, dass manche BIOSse nur das initialisieren, was sie zum booten brauchen.
Soll ich also am besten alle Geräte neu initialisieren? Das stelle ich mir nur im Falle von I/O Ports schwer vor, da ich nicht weiß, welche Ports schon vom System benutzt werden...
Initialisiere einfach alles, was du brauchst, und ignoriere den Rest. Damit fährst du für den Anfang gut genug.

Was die I/O-Ports angeht: Das ist genau das, was ich weiter oben beschrieben habe. Einfache (ISA-)Geräte kannst du nicht identifizieren, sondern nur auf gut Glück ein paar Ports lesen/schreiben und schauen, ob das, was da passiert, ungefähr so aussieht wie das, was dein gesuchtes Gerät dort tun würde. Deswegen gibt es da nichts zu initialisieren.

Das Adressregister ist aufgeteilt in Bus, Gerät und Funktion. Damit habe ich doch schon mehrere Busse. Wofür dann noch Bridges?
Bridges sind ein Hardware-Feature. Die kriegst du, weil die Hardware so gebaut ist, und vermutlich kannst du sie auch erstmal ignorieren.

Ich wollte damit nur sagen, dass du manche Geräte erst sehen/ansprechen kannst, wenn du bestimmte andere Geräte funktionierend in deinen Kernel integriert hast.

In dem Falle hat der Treiber PCI einfach eine Methode "rescan", die erneut nach Geräten sucht, aber nur für neue Geräte die Treiber lädt.
Ja, klingt gut.
94
Zitat
oder jedes Dateisystem stellt sein eigenes VFS-Interface bereit ("Laufwerksbuchstaben").
Die Idee gefällt mir, weil ich sowieso auf Laufwerksbuchstaben hinaus wollte. Aber dise Buchstaben müssen ja auch verwaltet werden. (Damit es keine doppelten gibt) Also werde ich doch ein zentrales VFS benötigen...
Ja, aber das kann man auch einfacher haben: Ein Array aus 26 Einträgen, wo jeweils ein Handle auf eine Dateisystems-Instanz abgelegt wird, und zwei Funktionen GibMirLaufwerksbuchstaben() und IchGebLaufwerksbuchstabenZurueck().

Zitat
dass du die Treiber in einer gewissen Reihenfolge laden musst, und dass du gewisse Treiber u.U. auch mehrfach laden musst (z.B. PCI-PCI-Bridges).
Das mit den PCI-PCI-Bridges verstehe ich noch nicht so ganz. Ich weiß, dass sie 2 Busse miteinander verbinden, aber sind die nicht schon vom BIOS initialisiert?
Eine PCI-PCI-Bridge schenkt dir einen neuen PCI-Bus, nachdem du sie initialisiert hast. Aber was ich meinte, war allgemeiner. Wenn du z.B. ein Notebook mit CardBus-Schnittstelle hast, dann ist diese Schnittstelle ein "PCI-Gerät". Und wenn du den Treiber für dieses Gerät lädst, dann taucht ein neuer PCI-Bus auf, mit der evtl. eingesteckten Karte drin. Entweder, dein Kernel erzeugt dann ein Event "neue Hardware gefunden", oder du musst alle deine PCI-Treiber neu laden, damit sie vielleicht jetzt etwas finden, was sie vorher nicht gefunden haben.

Gut, das sind alles ziemliche Spezialfälle, die du nicht unterstützen musst, aber vorher drüber nachdenken schadet sicherlich nicht. ;-)

Ist nicht alles vom BIOS initialisiert was PCI betrifft?
Das weiß ich nicht. Ich kann mir aber gut vorstellen, dass manche BIOSse nur das initialisieren, was sie zum booten brauchen.

Edit: Vielleicht sollte ich einfach alle Treiber in den Kernel integrieren. Das ist ja nur ein Hobbyprojekt und so groß wird das sicher auch nicht.
Dann brauchst du dir über meine Hinweise auch keine großen Gedanken machen. ;-)
95
Wer und wie erkennt wann, welcher Treiber benötigt wird? Um bei den Dateisystemen zu bleiben: Der ATA Treiber erkennt eine Festplatte, wie erkenne ich, ob ich eine Instanz von FAT, EFS, oder sonstwas brauche? Soll einfach jeder Treiber mal geladen und getestet werden?
Im Falle einer Festplatte brauchst du vermutlich erstmal einen Partitions-Layer, der erstmal MBR (ggf. GPT) zerpflückt. Wenn der durchgelaufen ist, dann hast du statt einer Festplatte mehrere voneinander streng zu trennende Blöcke (Partitionen), und du kennst von jeder Partition den Typen (= Dateisystem). Da die Typen nicht immer eindeutig sind (Linux-Partitionen haben alle die MBR-ID 0x83), kannst du dafür einfach eine feste Liste von Dateisystemen nacheinander ausprobieren.

Wenn diese Heuristik fehlschlägt, dann muss der Benutzer eingreifen. Einfach mal alle Dateisystemtreiber auf ein Block Device loszulassen, ist jedenfalls unelegant, weil nicht alle Dateisysteme eindeutige Headerfelder haben. Wenn ein solcher Treiber fälschlicherweise glaubt, er versteht einen Garbage-Header, zerstörst du dir u.U. Partitionen, die du nie hättest anfassen sollen. (Windows ist bekannt dafür, gewissen Linux-Partitionen einen Laufwerksbuchstaben zuzuweisen und bei einem Zugriff zu fragen, ob das komische Ding da formatiert werden soll. Passiert aber nur selten.)

Ich wollte erstmal einfach alle Treiber aus dem Verzeichnis Driver laden. Wahrscheinlich erstelle ich eine Liste pro Interface mit den zugehörigen Treibern.
Je nachdem, was du für Hardware unterstützen möchtest, musst du unterscheiden zwischen erkennbaren und nicht erkennbaren Geräten.

Erkennbare Geräte sind einfacher: Wenn du einen PCI-Bustreiber lädst, dann kann er dir sagen, welche Geräte an ihm angeschlossen sind. Diese Information (und die eindeutige ID) könntest du z.B. in eine Art "Event" verpacken und an den Kernel schicken, damit der dann den entsprechenden Treiber lädt - und zwar auch zur Laufzeit. Die meisten für dich wichtigen PC-Geräte funktionieren so, also PCI, USB, SATA, ISAPnP, Firewire usw. Wenn du das ordentlich hinbekommst, dann hast du auch die Grundlage für Hot-Plugging gelegt.

Nicht erkennbare Geräte kannst du nicht erkennen. Du kannst nur auf gut Glück einen Treiber auf eine bestimmte Hardware-Adresse laden und schauen, ob der Treiber dort seine Hardware findet. Das heißt, du brauchst irgendwo eine Liste von bekannten Standardadressen, wo du die dafür vorgesehenen Treiber einfach mal lädst und guckst, was passiert. Das betrifft alle Geräte, die entweder historisch gewachsen oder extrem simpel sind, also per ISA, I²C, SPI oder ähnlich beschränkten Bussystemen angeschlossen sind. Manche modernen Geräte kannst du wegen Kompatiblität auch so behandeln (USB-Tastatur, PCI-VGA). Beispiele sind die PS/2-, COM- und LPT-Schnittstellen, IDE-Festplatten (aber nicht unbedingt der dazugehörige IDE-Controller), viele Mainboardgeräte (z.B. Flashbausteine, Temperatursensoren), oder der DDC/EDID-Baustein in Bildschirmen.

Wenn du alle Geräte als "nicht erkennbar" behandelst - was auch gut funktioniert, zumindest für statische Geräte - dann musst du aber bedenken, dass du die Treiber in einer gewissen Reihenfolge laden musst, und dass du gewisse Treiber u.U. auch mehrfach laden musst (z.B. PCI-PCI-Bridges).

PCI Treiber durchsucht alle PCI Geräte, für jeden gefundenen DiskController erstellt er eine Instanz des zugehörigen Treibers, dieser erstellt pro angeschlossenem ATA/ATAPI Device wieder eine Instanz, diese wiederum pro Dateisystem ebenfalls eine Instanz. Aber am Ende muss es genau eine Instanz des VFS Treibers geben, der dann alle Instanzen der Dateisysteme zusammenführt.
Exakt. Entweder, alle aktiven Dateisysteme müssen sich im einzigen VFS-Treiber anmelden ("Mounten"), oder jedes Dateisystem stellt sein eigenes VFS-Interface bereit ("Laufwerksbuchstaben").
96
Offtopic / Re: Ratschläge um sich auf s Studium vorzubereiten
« am: 26. January 2015, 01:14 »
Ja und nein. Je nach Kurs, Dozent und Hochschule ist der Nutzen der Mathevorlesung mehr oder weniger begrenzt. Es kann sein, dass man da viele wunder- und sinnvolle Dinge lernt, es kann aber auch gut sein, dass es nur Definitionen und Schema-F-Herangehensweisen an Probleme sind, die der Prof jedes Jahr in der Klausur sehen will. Und nur wenig ist peinlicher, als nach drei Jahren Studium endgültig an der Mathe-Eins-Vorlesung zu scheitern. Daher: Nimm die Klausuren ernst, und wenn Test- oder Vorklausuren angeboten werden, dann nutze die Angebote. Mathe ist (je nach Hochschule) ein Siebfach!

Das heißt nicht, dass man alles wegwerfen kann, was dort Thema war. Denn die Schwierigkeit ergibt sich aus der Anwendung von dem, was dort behandelt wurde. Es hängt von der Freundlichkeit der Fachprofessoren ab, ob sie solche Grundlagen verständlich wiederholen oder es als "wird vorausgesetzt und ist laut Lehrplan abgehakt" abtun. Zumindest bei uns wurde der wichtigste Teil der Differentialrechnung in Physik und Elektrotechnik kurz, aber ordentlich wiederholt - weil man es da brauchte. Matritzen sind in der Informatik wichtiger, bei uns konnte man sich größtenteils drum rum mogeln.

Ansonsten gibt's von mir einen Tipp zu den Vorlesungen und Übungen: Hingehen und zuhören. (Exceptions apply.)

(Anekdote 1: Unser E-Technik-Prof war eine extreme Schlafmütze kurz vor der Rente, aber er hat in aller Ruhe den gesamten Stoff durchgekaut und an Beispielen durchexerziert. Auch die kleineren Leuchten, die sich da durchgequält haben, kamen meist durch die Klausuren - im Gegensatz zu einem Großteil derjenigen, die dachten, mit dem Script und zwei Wochen Vorbereitung schafft man das schon alleine. Und je später man die Klausuren schreibt, desto schwieriger werden sie, weil man ständig Neues lernt und Altes vergisst.)

(Anekdote 2: Wir hatten die erste Matheklausur nach dem 2. Semester, aber eine Zulassungsklausur nach der Hälfte. Da sind 50% durchgefallen und konnten die Klausur nicht mitschreiben, und haben sich tierisch aufgeregt. Die "anderen" Ingeneure hatten keine Vorklausur, sind dann zu 2/3 durch die richtige Klausur gefallen und hatten dann einen der drei Versuche verbraucht. Btw: Bei uns sind dann über 80% durch die normale Matheklausur gekommen, weil schon vorher schadensfrei gesiebt.)
97
Offtopic / Re: Obskure DDR OS/SYSTEME
« am: 23. January 2015, 01:22 »
Hi,

ja, da war schon einiges interessantes dabei, wobei die richtigen Betriebssysteme eher Kopien waren: DCP (DOS), oder auch MUTOS (ein UNIX). Allerdings sind diese Betriebssysteme sowieso eher in der 16-Bit-Welt zuhause, und da gab es im Ostblock nicht viel. Gab zwar eine 8086-Kopie aus der SU, aber genutzt wurden wohl hauptsächlich Importe. Das höchste der Gefühle war KWS als "Windows 3.0 for robotron A7150", aber mit dem Ende des Ostblocks starben diese Systeme alle schnell aus. Im Großrechner-Bereich gab es auch IBM- oder DEC-Klone, aber vorherrschend war die 8-Bit-Welt (dank U880 = Z80), und da gab's nen Wildwuchs an CP/M-Klonen, z.B. SCP oder ZSDOS, und eigene Systeme (z.B. CAOS auf dem KC85).

Ich hab auf nem KC85 erstmals programmiert. ;-)

Gruß,
Svenska
98
tyndur / Re: CDI: AHCI-Treiber
« am: 10. January 2015, 13:43 »
Du kannst da im Prinzip jede Bedingung eintragen, die der Compiler zur Compilezeit auflösen kann. Einen Teil kannst du auch mit dem Präprozessor erschlagen (#ifdef usw.), aber bestimmte Dinge wie sizeof() oder offsetof() kann man dort nicht zuverlässig verwenden. Dafür gibt es dann solche BUILD_BUG-Makros.

Ich benutze eins z.B., um sicherzustellen, dass ein Array nicht mehr Speicher benutzt, als da ist: "BUILD_BUG(SIZE_X * SIZE_Y * sizeof(node_t) > 24*1024)", wobei SIZE_X, SIZE_Y und node_t einstellbar sind. Die kann man im Prinzip beliebig einstellen, aber wenn das Ergebnis größer als 24 KB wird, funktioniert es halt nicht. Das fange ich damit ab.
99
Softwareentwicklung / Re: Einstieg in OS Programmierung
« am: 09. January 2015, 00:18 »
Hi,

ich bin ja kein Freund von Youtube-Tutorials, sondern bevorzuge es, wenn man die echten Dokumente (d.h. Datenblätter) oder zumindest Sekundärliteratur (d.h. aufbereitete Beschreibungen) lesen kann. Mit solchen Tutorials kommt man nämlich nie weiter, als einen die Autoren der Tutorials haben wollen. Aber das ist nur meine Meinung, wenn es dir hilft, nutze es. ;-)

Ich kenne an Büchern nur "Modern Operating Systems" und die MINIX-Bücher vom Tanenbaum, die ich durchaus empfehlen kann. Ansonsten gibt es Unmengen an Informationen im Internet, allerdings meistens auf englisch (wie auch meine Ausgaben der Bücher). Das ist übrigens auch so eine Sache: Hinter den Anfängen wird es mit deutsch allein extrem dünn.

Gruß,
Svenska
100
Softwareentwicklung / Re: Einstieg in OS Programmierung
« am: 08. January 2015, 00:43 »
Wir können dir das Wiki empfehlen, da stehen Unmengen an nützlichen Dingen drin, inklusive eines Tutorials für Anfänger. Einfach oben im Menü auf "Wiki" gehen. ;-)

Als Programmiersprachen kannst du eigentlich alles nehmen, was hinreichend systemnah ist und dir genug Möglichkeiten gibt. Oft wird C benutzt, aber auch andere Sprachen wurden schon mehr oder minder erfolgreich verwendet. In jedem Fall solltest du C (und einen Teil Assembler) zumindest lesen können, selbst, wenn du etwas anderes verwenden möchtest.
Seiten: 1 ... 3 4 [5] 6 7 ... 90

Einloggen