Hi, ich versuche immer noch ein Gefühl dafür zu bekommen, wie die Entwicklung auf einem Linux-System funtioniert. Ich habe verstanden, dass ich als Applikation nur über Treiber auf die darunterliegende Hardware zugreifen kann. Und dass hierfür nur die File-IO-Funktionen und ioctl() zur Verfügung stehen. Wie mache ich das aber wenn ich meherer Schnittstellen überwachen möchte ohne zu pollen, für die ich auf einem µC Interrupthandler einrichten würde? Erzeuge ich für jedes Device einen Thread und lass ihn mit FileRead() auf Daten warten? Oder kann ich vom UserSpace IRQ-Handler registrieren? Gibt es außerhalb von Treibern die Möglichkeit auf Phsysikalische Adressen zuzugreifen z.B. Register? Unter Windows CE konnte ich mir einen Pointer auf Hardware-Adressen geben lassen. Wäre toll wenn einer von euch mir helfen könnte das Big-Picture zu verstehen. Gruß Tom
Ohne dein System im Einzelnen zu kennen, ein paar Linux/Unix-Grundlagen: - Everything is a file. D.h. auch Devices wie GPIOs werden vermutlich als virtuelle Datei angelegt. - Warten auf mehrere Ereignisse geht auch in einem einzelnen Thread (he, ich erinnere mich noch an die iX, die irgendwann Ende der Neunziger das mit den Threads erklärte - Warten auf mehrere Dateien konnten wir aber schon lange vorher). Dafür gibt es select(), das zwar reichlich unintuitiv, dafür aber mächtig ist. Wenn dich ioctl() nicht schreckt, ist select() kein Thema. - Was ist FileRead()? Hört sich verdächtig nach Windows an. fget() nimmt man da (beispielsweise). Max
:
Bearbeitet durch User
Tach, zum select() könnte man speziell bei Linux den poll() erwähnen. Schenkt sich nicht viel zwischen den Beiden, der eine ist POSIX compliant, der andere hat eine gewisse Limite (Anzahl Filedeskriptoren) nicht. Im Prinzip implementierst du auf Treiberseite die poll-Methode, die typischerweise die 'wait queue'-Mechanismen benutzt. Dabei weckt der IRQ-Handler (den man per Treiber registrieren muss) eine WaitQueue-Struktur auf. Das Kernel garantiert damit, dass der Prozess schläft, solange er im poll() verharrt und kein Interrupt auftritt. Die Möglichkeit, auf 'harte' Pointer zuzugreifen, gibt es ansich auch, z.B. im video4linux2-Treiber. Aber I/O-Pointerzugriffe sind schon mal extrem unsauber, sollte man nur für unike Puffer-Adressen machen. Die Adressen werden ebenfalls per ioctl() zwischen Kernel und Userspace kommuniziert. Gefährlich wird's da mit physikalischen Adressen, obiges ist leicht unter uClinux (ohne MMU) zu implementieren, bei virtual Memory wirds haariger. Mehrere Threads brauchst du nicht unbedingt, die poll()s oder select() kannst du auch in die Mainloop hängen. Ist dann eine Frage nach der Wahl des Timeouts, bzw was sonst alles in deiner Mainloop passiert, bzw. auf welches Interface du am schnellsten reagieren musst. Bei bestmöglicher Antwort-Performance würde man wohl auf verschiedene Threads oder gar Realtime-Erweiterungen setzen, wenn ein Prozess binnen garantierter Zeit auf ein Ereignis reagieren muss. Salute, - Strubi
Das ist vom Kernel alles gut gepuffert. Und das Handshaking greift ein wenn nötig ... Also alles recht problemlos
Thomas Burkhart schrieb: > Ich habe verstanden, dass ich als Applikation nur über Treiber auf die > darunterliegende Hardware zugreifen kann. genau. Der Treiber muss aber nicht unbedingt im Kernel laufen, der meiste Teil davon kann auch im Userspace laufen: http://free-electrons.com/kerneldoc/latest/DocBook/uio-howto/ Allerdings laufen die meisten Treiber die Du unter Linux so findest komplett im Kernel da das eine höhere Performance bringt. > Und dass hierfür nur die > File-IO-Funktionen und ioctl() zur Verfügung stehen. Das ist meist das bequemste, aber nicht das einzig mögliche. Du könntest Dir z.B. auch Zugriff auf shared memory geben lassen oder vieles andere mehr. > Wie mache ich das aber wenn ich meherer Schnittstellen überwachen möchte > ohne zu pollen, für die ich auf einem µC Interrupthandler einrichten > würde? wie schon geschrieben, über filedescriptoren und poll() oder select(). > Erzeuge ich für jedes Device einen Thread und lass ihn mit FileRead() > auf Daten warten? wäre auch ne Möglichkeit. Ob mehrere Tasks, ein Task mit asynchronem IO oder ein Task mit mehreren Threads günstiger sind, hängt von der Aufgabe, der threadsicherheit und async-Unterstützung Deiner Libs und Deiner Erfahrung mit diesen 3 Methoden ab. > Oder kann ich vom UserSpace IRQ-Handler registrieren? Gibt es außerhalb > von Treibern die Möglichkeit auf Phsysikalische Adressen zuzugreifen > z.B. Register? Unter Windows CE konnte ich mir einen Pointer auf > Hardware-Adressen geben lassen. Irgendwie könnte man das sicher hinbiegen. Das widerspricht aber so manchen sinnvollen Linux-Prinzipien. Über kurz oder lang wird das stabil zu bekommen vieeeel aufwendiger als es so zu machen wie unter Linux eigentlich vorgesehen (siehe oben).
Ich habe in einem Beagleboard Tutorial jetzt gesehen, dass sogar die einzelnen Register als Virtuelles File angelegt werden. Wie groß ist denn die Performance-Einbuße durch den Filezugriff? Wenn man vom µC kommt hört sich das ziemlich furchtbar an. Welche Controlle habe ich über das Buffering dieser Funktionen? Bei den GPIOs des Beaglebones muss man anscheinend jedesmal das Fileschließen, damit das Signal auch wirklich am IO-Pin anliegt. Wer kümmert sich um das entprellen von GPIOs? Macht das der Treiber?
Schau dir mal mmap() an. Damit mappst du eine Datei in deinen virtuellen Adressraum und kannst dann darauf zugreifen wie auf normalen Speicher. Wenn es dir um schnell und schmutzig geht, dann kannst du mit /dev/mem auch direkt auf den physischen Adressraum zugreifen. Die Performance-Einbußen durch das VFS kannst du getrost ignorieren, die geht im Linux unter. Für die Metadaten gibt es zudem Caches.
Dank euch, jetzt hab ich einen besseren Überblick!
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.