Autor Thema: Treiberinitialisirung - Variables Array oder verkettete Liste  (Gelesen 2388 mal)

Programm Noob

  • Gast
Gespeichert
Moin
Ich würde gerne beim initialisieren des Treiberinterfaces Zeiger auf alle Treiber_init sammeln, so das diese danach der Reihe nach abgearbeitet werden können.
Soll heiß der PCI-Treiber findet ein paar geräte und er trägt alle init Funktionen in ein Array oder eine verkettete Liste ein. Dort werden dann noch floppy, hdd und andere Treiber eingetragen. Danach initialisiert das Interface alle Treiber, die sich dann Ports registrieren und ihren IRQ handler eintragen können.
Nun aber zu meinem Problem. Ich weiß ja zur compile Zeit nicht wie viele Geräte gefunden  werden.daher kann ich das Array nicht mit einer festen größe initialisieren. Wenn ich statt einer Konstanten dort eine Variable eintrage meckert GCC. Weiß einer wie ich gcc überreden kann es einfach so hinzunehmen? Ja ich benutze -std=c99
Verkettete liste wäre auch ne möglichkeit. Eine struct mit 2 Zeigern. Eine auf die Funktion und die andere auf den nächsten eintrag.

Was ist eurer meinung nach besser? Gibt es bei einem der beidemLösungen Nachteile gegenüber der anderen?

Programm Noob

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 21. July 2010, 01:32 »
Felder mit variablen Größen werden in C nicht direkt unterstützt.

In klassischem C ist ein Feld mit einem Pointer identisch, daher kannst du malloc() bzw. realloc() verwenden, um dein Feld zur Laufzeit zu deklarieren.
while( found_device() )
{
  num_devices++;
  feld = realloc(feld, num_devices*sizeof(dev_struct));
  feld[num_devices] = get_dev_infos();
}
ähnlich so.

Listenstrukturen sind auch möglich, die Frage ist an der Stelle, wieviele Einträge das Teil haben wird. Wenn die Inhalte recht statisch bleiben, dann sind in jedem Fall Felder vorzuziehen (Speichereffizienz, Suchzeiten, keine komplizierte Pointerarithmetik). In Listen lässt sich dafür das Hinzufügen/Entfernen sehr effizient implementieren.

Abstrahiert ihr eigentlich verschiedene Bussysteme? Eventuell ist das sinnvoll, dann könnte man Treiber für eine Hardware nämlich für verschiedene Geräte verwenden (mir fällt die NE2000 ein - als ne2000 [ISA], ne2k [PCI], ne/2 [MCA] und in diversen PCMCIA-Karten...) Vergleiche dazu NetBSD.

Gruß,
Svenska

Programm Noob

  • Gast
Gespeichert
« Antwort #2 am: 21. July 2010, 17:42 »
Listenstrukturen sind auch möglich, die Frage ist an der Stelle, wieviele Einträge das Teil haben wird. Wenn die Inhalte recht statisch bleiben, dann sind in jedem Fall Felder vorzuziehen (Speichereffizienz, Suchzeiten, keine komplizierte Pointerarithmetik). In Listen lässt sich dafür das Hinzufügen/Entfernen sehr effizient implementieren.
Ich habe das ganze mal versucht in C zu implementieren und muss sagen, das mir die Listenart besser gefällt. Die Liste kann ich nämlich einfach um das eine oder andere Feld erweitern und somit
 diese Liste gleichzeitig für eine Art Gerätemanager im OS Benutzen um mir alle momentan angeschlossenen Geräte/Treiber anzuzeigen. Aber wie meinst du das mit Statisch?
Ich habe mir jetzt überlegt, die Liste nehme ich zuerst nur für die PCI und floppy und so weiter Treiber, und sobalt  USB initialisiert wurde und ich alle Geräte gestartet habe, sollen diese dort eingetragen werden. und wenn ein gerät abgezogen wird, soll s aus der  Liste gelöscht werden.

Abstrahiert ihr eigentlich verschiedene Bussysteme? Eventuell ist das sinnvoll, dann könnte man Treiber für eine Hardware nämlich für verschiedene Geräte verwenden (mir fällt die NE2000 ein - als ne2000 [ISA], ne2k [PCI], ne/2 [MCA] und in diversen PCMCIA-Karten...) Vergleiche dazu NetBSD.
Ist nicht geplant und wird auch mit großer warscheinlichkeit nicht umgesetzt.


Hat vieleicht jemand einen anderen Vorschlag, wie man das noch relisieren könnte? Falls jemand noch einen hat, bitte melden.

Programm Noob

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 21. July 2010, 18:09 »
Statisch heißt, dass die Inhalte sich nur selten ändern (z.B. nur, wenn neue Geräte angeschlossen/entfernt werden). Dann macht sich ein Feld besser, du musst aber auf die externen Referenzen (Indizes!) achten.

Mit einem Feld sparst du Speicher, da du pro Listenelement ja eine Struktur mit malloc() alloziierst und bei einer 4K-Granularität bei x86 eine gesamte Page belegst. In einem Feld liegen die Daten direkt hintereinander, dafür ist entfernen eine richtig teure Angelegenheit.

Auslesen kannst du sowohl ein Feld, als auch eine Liste recht einfach. Wenn du allerdings eine komplette Systemübersicht haben möchtest, kannst du auch über Baumstrukturen nachdenken - in denen bleibt die Hierarchie erhalten. Wäre praktisch, wenn du USB-Hubs und USB-Geräte mit mehreren Endpoints unterstützen möchtest oder z.B. wie in Linux die DDC-Unterstützung (Monitordaten auslesen) moderner Grafikkarten direkt als I²C-Bussystem ansprechen möchtest. Dann brauchst du nur einmal I²C implementieren (und kannst die I²C-Schnittstelle zweckentfremden :-D), das setzt dann aber wieder abstrahierte Busse voraus.

Da würde ich jedenfalls nochmal nachdenken; einige Hardware taucht auch in USB-Geräten wieder auf (und seien es die SoundBlaster-Karten in PCI/USB-Version). Das macht die Treiberentwicklung später einfacher.

Gruß,
Svenska

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 21. July 2010, 18:10 »
Du könntest noch Hash-Tabellen verwenden. Dann hast du eine statische Größe und musst dir nur noche ien geute Funktion überlegen, anhand derer du die Geräte einträgst.
Eine Möglichkeit wäre z.B. die ID des Gerätes als Grundlage für die Funktion verwenden.
Hash-Tabellen sind halt recht effektiv und du sparst dir die Liste und kannst dem Compiler die Organisiation des Speichers überlassen.

Mit einem Feld sparst du Speicher, da du pro Listenelement ja eine Struktur mit malloc() alloziierst und bei einer 4K-Granularität bei x86 eine gesamte Page belegst. In einem Feld liegen die Daten direkt hintereinander, dafür ist entfernen eine richtig teure Angelegenheit.
Falls schon ein gutes malloc geschrieben wurde, ist die Granularität recht gering und du brauchst unter Umständen keine 4k-Pages, da es noch genug freien Restspeicher gibt.
Das Malloc sollte sich ja nur 4k-Seiten holen, falls es nicht genug speicher zur Verfügung hat.
« Letzte Änderung: 21. July 2010, 18:12 von rizor »
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

 

Einloggen