Wir führen einen Echtzeitprozess auf einem Nicht-Echtzeit-Kernel (CentOS 6) aus, und das wird sich wahrscheinlich nicht ändern.
Wir haben eine Streaming-Video-Anwendung, die 1,5 Stunden lang kontinuierlich etwa 500 MB/s PCIe-Verkehr von einem benutzerdefinierten FPGA erfordert. Die Anwendung funktioniert ziemlich gut – meistens. Wir hatten jedoch Situationen, in denen es so aussah, als würde der Kernel einfach aufhören, auf PCIe- oder Speicheranforderungen zu reagieren, und zwar für bis zu 500 Millisekunden. Dies scheint während stoßweiser Datei-E/A von einem anderen Thread aus zu passieren. Ich habe festgestellt, dass es unmöglich ist, dieses Problem zu reproduzieren, indem ich einfach jede Menge Dummy-Datei-E/A aus dem Benutzerbereich ausführe, während die Hauptanwendung ausgeführt wird.
Gibt es eine Möglichkeit, ein globales „Einfrieren“ des Linux-Kernels zu erzwingen (simulieren) (insbesondere durch Stoppen von PCIe oder allen DDR3-Speicherzugriffen oder etwas in der Art), sodass wir dieses Problem reproduzieren können?
Wir haben derzeit eine Pufferung von bis zu 10 Millisekunden im internen FPGA-Speicher implementiert, aber das reicht nicht. Wir können auf FPGA DDR3 puffern und dann auf den Host übertragen, aber wir brauchen eine Methode, um diese neue Funktion unter Druck zu testen.
Wir möchten nicht, dass der Kernel dauerhaft einfriert oder blockiert. Wir möchten die Möglichkeit haben, das Zeitintervall festzulegen.
Ich suche nach etwas in der Art, magische Werte zu schreiben, /proc/sys/vm
die das System vorübergehend praktisch zum Kriechen bringen und dann nach ein paar hundert Millisekunden wieder in den Normalzustand zurückkehren. Aber wenn man sich die Anzahl der möglichen Wege ansieht, das zu unterbrechen, ist das nichts für einen Neuling wie mich (https://www.kernel.org/doc/Documentation/sysctl/vm.txt). Vielleicht ein bisschen numactl
Magie?
Antwort1
Eine Möglichkeit, einen schnellen Test durchzuführen, könnte sein, einen KGDB-fähigen Kernel zu verwenden und den Kernel manuell zu stoppen und zu testen.siehe diesen Link.
Noch etwas: Ich erinnere mich an Dinge, die den Grund für Ihr Zögern darstellen könnten:
- cpufreq
cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_transition_latency
, der Wert ist in ns (4000 in meinem AMD FX(tm)-8120 Achtkernprozessor) sollte kein Problem sein, aber überprüfen Sie - Thermische Drosselung entweder der CPU selbst oder des Spannungsreglermoduls.
- NAPI und/oder hoher Netzwerkverkehr
- PCIe ASPM (
cat /sys/module/pcie_aspm/parameters/policy
) - Konflikte in den Puffern Ihres Zielgeräts (Festplatte, Netzwerkkarte usw.)
- Fehler in der Firmware einiger Geräte im PCIe-Bus (auch wenn Sie diese nicht verwenden), können Sie versuchen, sie mit
/sys/bus/pci/devices/$DEVICE/power/control
Antwort2
Können wir mehr Details darüber erfahren, wie Ihre Anwendung mit dem FPGA kommuniziert? Ist es die Anwendung, die den Puffer vom FPGA liest, oder ist es das FPGA, das Interrupts an den Kernel sendet (wie Netzwerkkarten)?
Ich erwarte, dass es einen Block/Char in /dev öffnet und dann damit kommuniziert. Das heißt, es verwendet einen Treiber für die Kommunikation zwischen der Anwendung und der Datei /dev/XXX.
Ich hätte gerne folgende Ausgabe:
cat /proc/interrupts
; lsmod
;ls -al /dev/yourmod
Hier sind die Ideen:
- Wenn die Karte über Interrupts gesteuert wird, können Sie den PIC der CPU so einstellen, dass der entsprechende IRQ deaktiviert und dann wieder aktiviert wird. Dadurch wird jede Anfrage der Karte ignoriert (ohne dass die Karte davon Kenntnis erhält).
- Wenn es sich um einen Pufferlesevorgang handelt, können Sie:
- Versetzen Sie Ihre Anwendung in den Ruhezustand, damit die Daten nicht vom FPGA gelesen werden und Ihr Puffer gefüllt wird. Wecken Sie dann Ihre Anwendung auf und setzen Sie den Lesevorgang fort.
- Verwenden Sie „crash“ oder „kgdb“, um den „read“-Wert für einige Sekunden in „noop“ zu ändern, und setzen Sie ihn dann auf die Standardfunktion zurück.
Geben Sie bitte alle Informationen an, die für Sie nützlich sein könnten.
Antwort3
Ich bin nicht sicher, ob das hilft. Aber wenn Sie ein Kernelmodul schreiben können, das die suspend
Funktion des Kernelmoduls eines anderen Geräts aufruft, könnte das funktionieren.
Jedes PCI-Gerät kann gemäß der Header-Datei angehalten werdenhttp://www.cs.fsu.edu/~baker/devices/lxr/http/source/linux/include/linux/pci.h#L479
Hier ist beispielsweise die Suspend-Funktion der Intel e1000 NIChttp://www.cs.fsu.edu/~baker/devices/lxr/http/source/linux/drivers/net/e1000e/netdev.c#L4643
Soweit ich mich erinnern kann, wurde diese Funktion hauptsächlich verwendet, wenn das System in den Ruhezustand wechselte und der Gerätetreiber den aktuellen Betriebsstatus speichern und sich selbst ausschalten musste.
Antwort4
Ich glaube, Sie denken in die falsche Richtung. Ihr Ziel ist klar.
Der Weg besteht nicht darin, die restlichen Prozesse zu stoppen, sondern Ihren Hauptprozessen Priorität bei der Planung in nahezu Echtzeit zu geben. Verwenden SieHübschfür Ihre wichtigen User-Space-Prozesse.
Das schwierigere Problem ist die PCIe-Interrupt-Behandlung, die im Kernel-Speicher stattfindet.
Da es sich um Hardware handelt, sollten Sie sich zunächst die betroffene PCIe-Lane auf Ihrem Mainboard genauer ansehen und wie diese möglicherweise mit einem bestimmten CPU-Sockel verbunden ist.
Abonnierenleistet hier normalerweise gute Arbeit, aber Sie können sein Verhalten Ihren Anforderungen entsprechend konfigurieren.