2010-03-28 6 views
11

In einer Linux-Anwendung verwende ich Pipes, um Informationen zwischen Threads weiterzuleiten.sind Posix-Rohre leicht?

Die Idee hinter der Verwendung von Pipes ist, dass ich mit poll (2) auf mehrere Pipes gleichzeitig warten kann. Das funktioniert in der Praxis gut und meine Fäden schlafen die meiste Zeit. Sie wachen nur auf, wenn es etwas zu tun gibt.

Im User-Space sehen die Pipes genau wie zwei Dateigriffe aus. Jetzt frage ich mich, wie viel Ressourcen solche Rohre auf der OS-Seite verwenden.

Btw: In meiner Anwendung sende ich immer nur einzelne Bytes. Stellen Sie sich meine Pipes als einfache Nachrichtenwarteschlangen vor, die es mir ermöglichen, empfangene Threads zu wecken, ihnen mitzuteilen, dass sie Statusdaten senden oder beenden sollen.

+6

Posix gibt die Rohrschnittstelle an, nicht die Implementierung, wo das "Gewicht" herkommt. –

+0

Wie viele Kanäle? Wie viele Nachrichten pro Sekunde? Hunderte? Millionen? Erstellen Sie einen einfachen Prototyp mit verschiedenen Technologien (von IPC-Nachrichtenwarteschlangen über Pipes bis hin zu UNIX-Sockets usw.) und vergleichen Sie diese. –

Antwort

4

Da Sie Linux verwenden, können Sie pipe Leistung mit eventfd untersuchen und vergleichen. Sie sind technisch schneller und leichter, aber Sie werden sehr glücklich sein, die Gewinne in der Praxis zu sehen.

http://www.kernel.org/doc/man-pages/online/pages/man2/eventfd.2.html

+0

WOW! Danke, dass du darauf hingewiesen hast. Ich benutze Pipes für diese Art von Dingen, und ich bin mir sicher, dass ich mindestens die Hälfte davon mit eventfds ersetzen kann. Meistens will ich nur einen Zustand einem Thread signalisieren, der in der Umfrage blockiert ist. Wenn eventfd leichter ist, benutze ich es. –

7

Nein, ich würde Rohre nicht als "leicht" bezeichnen, aber das bedeutet nicht unbedingt, dass sie auch die falsche Antwort für Ihre Anwendung sind.

Das Senden eines Bytes über eine Pipe erfordert mindestens 3 Systemaufrufe (Schreiben, Abfragen, Lesen). Die Verwendung einer speicherinternen Warteschlange und von pthread-Operationen (mutex_lock, cond_signal) erfordert viel weniger Overhead. Offene Dateideskriptoren verbrauchen definitiv Kernel-Ressourcen; Aus diesem Grund sind Prozesse standardmäßig auf 256 offene Dateien beschränkt (nicht, dass das Limit gegebenenfalls nicht erweitert werden kann).

Dennoch hat die Pipe/Poll-Lösung für Inter-Thread-Kommunikation auch Vorteile: Insbesondere wenn Sie auf Eingaben von einer Kombination von Quellen (Netzwerk + andere Threads) warten müssen.

+0

Warum würde es 3 Systemaufrufe dauern? Ein blind '' write() '- Aufruf blockiert, wenn die Puffer der Pipe voll sind. Wenn jeder Thread nur auf seine eigene Pipe hören muss, können Sie die 'poll()' ebenfalls ablegen, einfach warten, bis 'read() 'erfolgreich ist – Hasturkun

+2

OP hat ausdrücklich gesagt, dass er poll() verwendet, um auf mehrere Pipes zu warten ein Verbraucher-Thread. –

+0

Ich muss lesen und schreiben in eine Datei (/ dev/ttySxx seriell) * und * in der Lage sein, auf Befehle von einem anderen Thread zu antworten. Blockieren kommt nicht in Frage. Wenn ich zum Beispiel einen 10 Megabyte Schreibzugriff auf die serielle Schnittstelle habe, kann ich nicht warten bis es fertig ist, wenn die Anwendung mir sagt, dass sie die Übertragung abbrechen möchte. Daher zwei nicht blockierende Dateien, die ich abfragen: Eine für die serielle Schnittstelle und eine für den Empfang von Befehlen. –

1

Messen Sie und Sie werden es wissen. Volle Prozesse mit Rohren sind für viele Anwendungen ausreichend leicht. Andere Anwendungen erfordern etwas leichteres wie OS-Threads (Pthreads sind die beliebte Wahl für viele Unix-Anwendungen) oder Superlightweight, wie ein Threads-Paket auf Benutzerebene, das niemals in den Kernel-Modus geht, außer um I/O zu handhaben. Während der einzige Weg, um sicher zu wissen, ist zu messen, sind Pipes wahrscheinlich gut genug für bis zu ein paar Dutzend Threads, während Sie wahrscheinlich User-Level-Threads, wenn Sie zu ein paar Zehntausenden von Threads. Wo genau die Grenzen mit den heutigen Codes gezogen werden sollen, weiß ich nicht. Wenn ich es wissen wollte, würde ich es messen :-)

+0

Ich denke ich bin verwirrt. Ich denke, Linux NPTL-Implementierung ist Kernel-Level. Bietet glibc darüber hinaus eine Implementierung auf Benutzerebene? –

+0

@Wei: Mein Fehler. Bearbeitet. –

0

könnten Sie auch socket, die mehr tragbar als eventfd ist, weil es POSIX ist.