Wie kann ich in Linux feststellen, ob ein Programm (vorzugsweise ein Terminalprogramm wie putty oder picocom) gerade eine serielle Schnittstelle belegt ?
Grundsätzlich wäre hier ein Pascalprogramm perfekt, aber auch eine Lösung in C / C++ oder schlicht auf der Konsole wäre hilfreich.
dmesg | grep ttyUSB0
sagt mir beispielsweie nur, dass eine USB2UART Bridge eingestöppselt ist, aber nicht, ob sie gerade in Benutzung ist.
Man könnte herausfinden, wo lsof diese Info her nimmt. Vermutlich liest es irgendeine Datei (oder Verzeichnis) unter /proc aus. Darauf könnte man auch selbst direkt zugreifen, anstatt lsof als Unterprogramm aufzurufen.
Grundsätzlich wäre hier ein Pascalprogramm perfekt, aber auch eine
Lösung in C / C++ [...]
Du willst Dich also sogar schon auf eine Programmiersprache festlegen... bist Du sicher, daß Linux das Richtige für Dich ist? Davon abgesehen, bieten Linux und andere UNIXoide dafür den Standardbefehl fuser(1), der natürlich aufgrund höherer Portabilität, besserer Performance und geringeren Ressourcenverbrauchs dem linux-spezifischen lsof(8) vorzuziehen ist.
Du willst Dich also sogar schon auf eine Programmiersprache festlegen...
bist Du sicher, daß Linux das Richtige für Dich ist?
Ich glaube nicht, dass Linux das Richtige für mich ist (meine Güte ich liebe diese Unterstellungen wirklich), ich weiß es (denn Linux mache ich jetzt schon seit fast 20 Jahren)!
Du willst Dich also sogar schon auf eine Programmiersprache festlegen...
Ich habe mich auf genau 3 Sprachen festgelegt: C, C++ und Pascal/Delphi (und noch etwas JavaScript für Webseiten).
Pascal/Delphi mache ich aus historisch gewachsenen Gründen und bestimmte Programme erweitere ich in dieser Sprache, weil ich schlichtweg keine Lust habe, bestimmte Programme komplet neu zu schreiben. Allen voran meinen Konsoleneditor mit FreeVison und nicht mit NCURSES und (wie im aktuellen Falle) mit einem Hostprogramm, welche eben ein zu flashendes Firmware programmieren soll.
Aber egal wie lange man Linux schon macht, irgendwelche Parameter zu irgendwelchen Programmen fallen einem immer mal nicht ein.
Das dachte ich zuerst auch, aber: Bspw. picocom hinterläßt bei Benutzung eines CH340 unter /var/lock mit Slackware-Linux leider nichts (zig mal nachgesehen)
Davon abgesehen,
bieten Linux und andere UNIXoide dafür den Standardbefehl fuser(1), der
natürlich aufgrund höherer Portabilität, besserer Performance und
geringeren Ressourcenverbrauchs dem linux-spezifischen lsof(8)
vorzuziehen ist.
war gut, ein
1
fuser /dev/ttyUSB0
gibt ein
1
/dev/ttyUSB0: 12680
zurück. Jetzt muß ich nur noch testen, ob es das unter Ubuntu auch macht.
Bspw. picocom hinterläßt bei Benutzung
eines CH340 unter /var/lock mit Slackware-Linux leider nichts (zig mal
nachgesehen)
Picocom lockt das Device mittels flock() (wenn man dies nicht mit -l
verhindert). Eine Lock-Datei wird dabei nicht angelegt, du kannst aber
den Lock-Status abfragen, indem du in deinem Programm versucht,
ebenfalls einen Lock anzuklegen:
du kannst aber
den Lock-Status abfragen, indem du in deinem Programm versucht,
ebenfalls einen Lock anzuklegen:
fd = open("/dev/ttyACM0", O_RDWR);
err = flock(fd, LOCK_EX | LOCK_NB));
Vielen Dank Yalu, so etwas ähnliches habe ich jetzt knapp vor deinem Posting ausprobiert und funktioniert.
Jetzt ... versuche ich das auch in Pascal (fuser von "Ein T." ist der "Notbehelf" weil ich das ganze auch noch unter Pascal haben möchte. Ich habe halt noch beide Programmiersprachen im Einsatz und möchte für mich das einmal grundsätzlich geklärt haben.
Grundproblem hierbei ist: Ich schreibe gerade am Host für einen Bootloader und speziell der Bootloader jetzt für den CH32 mag es nicht, wenn ein Terminalprogramm gerade aktiv ist. Schlimmer noch als dass der Chip nicht geflasht werden kann (habe ich jetzt per TimeOut eliminiert) ist, dass wenn ein UART-Programm im Chip läuft und dieses Ausgaben tätigt, das Programm des Bootloaders sich derart aufhängt, dass es nur durch ein Neuflashens des Bootloaders wieder läuft) ==> ergo: Feststellen, ob ein Terminalprogramm aktiv ist (muß ja nicht PicoCom sein, putty macht dasselbe Problem).
Grundproblem hierbei ist: Ich schreibe gerade am Host für einen
Bootloader und speziell der Bootloader jetzt für den CH32 mag es nicht,
wenn ein Terminalprogramm gerade aktiv ist.
Da wird wohl das Terminalprogramm einen Teil der Ausgaben des µC
wegsaugen.
ergo: Feststellen, ob ein Terminalprogramm aktiv ist (muß ja nicht
PicoCom sein, putty macht dasselbe Problem).
Wie du bereits festgestellt hast, sind es zwei verschiedene Dinge, ob
ein Prozess ein Device geöffnet hat, oder ob es einen Lock dafür
angelegt hat.
Für deinen Anwendungsfall würde ich deswegen die Abfrage mit fuser oder
lsof bevorzugen.
Wenn du den Aufruf von Kommandozeilentools vermeiden möchtest, kannst du
dasselbe auch erreichen, indem du für alle Prozesse in /proc/<pid>/fd/*
nachschaust, ob das abzufragende Device mit dabei ist. Etwas anders tun
lsof und fuser auch nicht.
Für deinen Anwendungsfall würde ich deswegen die Abfrage mit fuser oder
lsof bevorzugen.
da bin ich gerade dabei ... fuser erscheint mir die "bessere Wahl", weil um Längen schneller als "lsof" (hier möchte ich nicht so arg lange warten bis der Upload beginnt).
( natürlich könnte man das auch im Makefile lösen, in dem man vor dem Start des Flasherprogramms "fuser /dev/ttyUSB0 > ~/.config/v003/tmp.run" erzeugt und dann von einer eventuell erstellten Datei (und deren Inhalt) den Start des Uploadprogramms abhängig macht.... aber irgendwie ist das unschön.
Ein /bin/bash - Aufruf mit fuser aus Pascal heraus hat ein veraltetes Filehandle (und gibt mir eine Fehlermeldung aus, jedoch mit dem erzeugten Prozess von /dev/ttyUSB0 ... und funktioniert auch: Aber eine Fehlermeldung ist immer unschön)
So, was lange dauert... haut irgendwann dann eben doch noch hin!
Ich habe mich (sehr) lange nicht mehr mit denn Methoden von FreePascals "tprocess" auseinandergesetzt und von daher ist schon fast zum Schämen (okay nicht nur fast) dass das so lange gedauert hat.
Aber wie dem auch sei, im Anhang der Code in Pascal um Festzustellen, ob ein serieller Port in Benutzung ist oder nicht.
du kannst aber
den Lock-Status abfragen, indem du in deinem Programm versucht,
ebenfalls einen Lock anzuklegen:
fd = open("/dev/ttyACM0", O_RDWR);
err = flock(fd, LOCK_EX | LOCK_NB));
Vielen Dank Yalu, so etwas ähnliches habe ich jetzt knapp vor deinem
Posting ausprobiert und funktioniert.
In diesem Fall und für dieses Terminalprogramm funktioniert das womöglich, aber, kurz gesagt: Dateilocking unter Linux ist fundamental kaputt. Es gibt zwei inkompatible Implementierungen, die beide nur "advisory" sind -- also nicht vom Kernel durchgesetzt werden, und unter bestimmten Umständen wie bei den Systembefehlen der fork(2)-Familie sowie auf Netzwerkdateisystemen nicht zuverlässig funktionieren -- und von der vom Kernel durchgesetzten Variante raten die betreffenden Dokumentationen (wie fcntl(2)) ausdrücklich ab.
Das ist allerdings ein historisch gewachsenes Problem, und andererseits kann man natürlich mal fragen, ob es nicht prinzipiell widersinnig ist, exklusive Locks auf Ressourcen eines Multiuser- und Multitaskingsystems zuzulassen.
Jetzt ... versuche ich das auch in Pascal (fuser von "Ein T." ist der
"Notbehelf" weil ich das ganze auch noch unter Pascal haben möchte. Ich
habe halt noch beide Programmiersprachen im Einsatz und möchte für mich
das einmal grundsätzlich geklärt haben.
Siehe fuser(1), das klappert "/proc/<pid>/fd/" ab [1].
So, was lange dauert... haut irgendwann dann eben doch noch hin!
Ist aber immer noch Murks. Nimm Lockfiles, ist das Standardvorgehen von 0815 scripten bis kiloeuro teurer kommerzieller Soft, nicht ohne Grund wird das immer noch so gemacht, auch wenn es auf den ersten Blick Krückenmässig aussieht.
Ist aber immer noch Murks. Nimm Lockfiles, ist das Standardvorgehen von
0815 scripten bis kiloeuro teurer kommerzieller Soft, nicht ohne Grund
wird das immer noch so gemacht, auch wenn es auf den ersten Blick
Krückenmässig aussieht.
Das dachte ich zuerst auch, aber: Bspw. picocom hinterläßt bei Benutzung
eines CH340 unter /var/lock mit Slackware-Linux leider nichts (zig mal
nachgesehen)
ob ein Programm (vorzugsweise ein Terminalprogramm wie putty oder
picocom) gerade eine serielle Schnittstelle belegt
und nicht, ob ein Programm für die Schnittstelle ein Lockfile angelegt
hat.
Die Existenz eines Lockfiles ist weder eine notwendige noch eine
hinreichende Bedingung dafür, dass die Schnittstelle bereits von einem
anderen Programm geöffnet ist, das Resultat von fuser hingegen schon.
In Pascal habe ich das ja jetzt mit "fuser" gemacht (siehe Anhang im vorherigen Post)... und ich werde das, einfach damit ich das auch für C / C++ dann zur Verfügung habe ebenfalls mit "fuser" machen!
:-) auf github war ich schon gewesen und habe mir fuser angesehen ... und beim nächsten ansehen verstehe ich dann vllt. die nächsten 10% (and so on).
Wenn ich mir etwas genauer ansehe wie etwas funktioniert, kopiere ich mir nach und nach die entsprechenden Stellen heraus (wie jetzt hier bei fuser.c) damit ich von anderen Dingen im Code (bspw. Argumentenauswertung) nicht abgelenkt bin.
:-) ich denke nicht, dass die Programmierer von bspw. putty "Scriptkiddies" sind und putty legt (natürlich) auch kein Lockfile an.
Mein Problem habe ich ja bereits zu meiner Zufriedenheit gelöst. Es ist gut, sich immer wieder einmal mit dem System zu beschäftigen (habe ich lange nicht mehr gemacht) und man merkt, wie viel man immer wieder vergessen kann.
Ich bin immer wieder (positiv) darüber erstaunt, wie manche aus dem Handgelenk wirklich sofort wissen, wo man ansetzen muß (ich glaube ich bin zu alt geworden.
wo man ansetzen muß (ich glaube ich bin zu alt geworden.
Es ist eher umgekehrt. Je aelter man wird umso mehr weiss man. :)
Wenn man mal so drueber nachdenkt ist aber die Sache mit den Lockfiles eigentlich erstaunlich. Gerade weil das ja simulierte Files sind. Man wuerde denken das der Kernel weiss wer ein File aufmacht und sagen wir mal zwei gleichzeitige "w" Oeffnungen verhindert.
Problem bei Linux/Unix ist aber das da auch viel Tradition ist und irgendwie auf irgendwelche ollen Kisten aus den 70ern zurueckgeht. Sowas wie uucp/kermit hat ja schon lockfiles angelegt und wer weiss was uucp ist, hat bald Rentenanspruch. :-D