PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [C++] Interprozess-Kommunikation mit FIFOs und Qt 3



KL47
28-01-2005, 22:47
Wenn ihr von außen (also mit irgendwelchen anderen Programmen) auf ein bereits laufendes Programm zugreifen wollt, bietet es sich an, dies unter Linux über "Named Pipes" zu machen (siehe dazu "man fifo" oder den entsprechenden Eintrag in der Wikipedia (http://de.wikipedia.org/wiki/Pipe)).

Hier soll nun erläutert werden, wie ihr in euer Programm mit QT 3 (Produkt von Trolltech (http://www.trolltech.com/)) einen Thread einbaut, der Eingaben von einer bestimmten Pipe empfängt (die Bearbeitung der Eingaben bleibt euch selbst überlassen ;)). Einige Kenntnisse in C++ und QT werden vorausgesetzt.

Wir brauchen zunächst einen Namen für das Programm, wir nennen es ThreadApp (:D). Anschließend legen wir einen Ordner "/var/run/threadapp/" an und erstellen in diesem Ordner eine Pipe:
mkdir /var/run/threadapp
cd /var/run/threadapp
mkfifo input.fifo Wir erstellen jetzt die Quellcode-Dateien für unser Projekt. Erstellt mit $EDITOR die beiden folgenden Dateien:

ThreadApp.h

#include <iostream>
#include <string>

#include <qfile.h>
#include <qtextstream.h>
#include <qstring.h>

#include <qthread.h>

class ThreadApp : public QThread
{
public:
ThreadApp();

void run();
void stop();

private:
bool stopped;
};ThreadApp.cpp
#include "ThreadApp.h"

ThreadApp::ThreadApp()
{
this->stopped = false;
}


void ThreadApp::run()
{
QFile file("/var/run/threadapp/input.fifo");

if (!file.open(IO_ReadOnly | IO_Translate)) return;

while (!this->stopped)
{
QTextStream stream(&file);

QString s;

while ((s = stream.readLine()) != NULL)
{
// Mit dem String könnt ihr jetzt tun, was immer ihr wollt,
// mit std::string(s) könnt ihr ihn auch in einen STL-String
// umwandeln
// Denkt bei der Ausgabe an das "std::endl", da ansonsten der
// Buffer nicht geleert wird und nichts ausgegeben wird.
// Achtung: "\n" != std::endl
std::cout << s << std::endl;
}
}
}


void ThreadApp::stop()
{
this->stopped = true;
}


int main()
{
ThreadApp t;

t.start(QThread::HighestPriority);

// Verhindert, dass das Programm zu früh beendet wird
while (t.running())
{
}

return 0;
} Das Projekt wird kompiliert, indem zunächst mit "qmake" ein Makefile erzeugt und anschließend mit "make" das Programm erzeugt wird, vorher müssen wir noch eine Projektdatei erstellen und diese ein wenig modifizieren (es wird davon ausgegangen, dass die Quellcode-Dateien in dem Ordner "ThreadApp" sind, ansonsten heißt die Projektdatei anders, *.pro müsste es genauso tun):
qmake -project
echo "CONFIG += thread" >> ThreadApp.pro
qmake
make Nun könnt ihr euer Programm testen:
./ThreadApp &
echo "Test" > /var/run/threadapp/input.fifo
Viel Spaß noch. Wenn ihr Fehler findet, postet einfach mal, mal schaun was sich machen lässt... ;)

anda_skoa
29-01-2005, 13:44
Man müsste das jetzt austesten, aber vermutlich kann man das in Programmen mit Eventloop auch ohne Thread machen, wenn man den Filedescriptor des FIFOs mit einem QSocketNotifier überwacht.

Ciao,
_

KL47
29-01-2005, 15:33
Das ganze Programm geht natürlich auch ganz ohne Threads, das ist klar, wenn man z.B. die äußere Schleife in ThreadApp::run() nach Main() packt, aber es kann ja sein, dass das Programm zusätzlich noch was anderes machen soll, außer nur Befehle aus der Pipe auslesen. ;)

Die Methode mit QSocketNotifier kenn ich noch nicht, werd mich direkt mal schlau machen...

Ein Nachteil von QSocketNotifier ist auf jeden Fall, dass er nur mit GUI-Threads verwendet werden kann, das könnte dann wahrscheinlich Probleme geben, wenn kein X läuft.

anda_skoa
29-01-2005, 16:30
Das ganze Programm geht natürlich auch ganz ohne Threads, das ist klar, wenn man z.B. die äußere Schleife in ThreadApp::run() nach Main() packt, aber es kann ja sein, dass das Programm zusätzlich noch was anderes machen soll, außer nur Befehle aus der Pipe auslesen. ;)

Schon klar, darum hab ich ja geschrieben "in Programmen mit Eventloop"



Die Methode mit QSocketNotifier kenn ich noch nicht, werd mich direkt mal schlau machen...

Falls es funktioniert wäre es cool, wenn du diese Variante auch posten könntest.



Ein Nachteil von QSocketNotifier ist auf jeden Fall, dass er nur mit GUI-Threads verwendet werden kann, das könnte dann wahrscheinlich Probleme geben, wenn kein X läuft.

Die Qt Eventloop ist nicht von GUI oder X abhängig. Man braucht nur eine QApplication Instanz und Loop mit QApplication::exec() zu starten.

Da das in einer Qt Applikation einfach sehr wahrscheinlich der Fall ist, wäre ein Lösung, die ohne Threads auskommt, noch schöner, denn Threads haben bekanntlich nicht nur Vorteile :D

Ciao,
_