PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : multithreaded App für ttyS-Schnittstelle



zelur_em
27-03-2008, 14:05
Hallo allerseits.

Ich habe ein großes Problem bei der Programmierung einer

pthread-basierten Anwendung die auf die serielle Schnittstelle

zugreift.
Das Problem tritt immer dann auf, wenn ich in einer der

Threadfunktionen die Funktion nanosleep(timespec&, NULL),

usleep(unsigned long) oder sleep(unsigned int) für eine gewisse

Zeit schlafen legen will.

Hier ein kurzes Beispiel:



#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>

#include <iostream>

using namespace std;

int main () {
//int fd = open ("/dev/ttyS0", O_RDWR | O_NOCTTY);
//int fd = open ("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NONBLOCK);
int fd = open ("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1) {
perror ("error open");
return (1);
}
int rc;
char buf[5];
struct timespec t1;
t1.tv_sec = 0;
t1.tv_nsec = 300;
while (1) {
rc = read (fd, buf, 1);
if (rc > 1) {
cerr << endl << "read > 1" << endl;
} else if (rc == 1) {
//putchar (buf[0]);
cerr << buf[0];
} else {
/// Kommt nur vor wenn der Filedescriptor
/// auf nonblocking gestellt ist.
cerr << "i";
}
/// Der Knackpunkt
nanosleep (&t1, NULL);
}
return (0);
}


Das Codebeispiel geht davon aus, dass während des Programmstarts kontinuierlich Zeichen auf dem /dev/ttyS0 Device ankommen. Wenn jedoch die Gegenstelle, während des Programm läuft, mit dem Senden aufhört, so werden trotzdem weiterere eingehende Zeichen gemeldet. Kommentiert man jedoch die Zeile mit dem nanosleep aus, so funktioniert es einwandfrei. Ich versuche jetzt schon seit 2 Tagen den Fehler zu finden. Ohne Erfolg. Dabei ist dieses Beispiel schon eine stark vereinfachte Version bei der der Fehler auch ohne Multithreading auftritt. Ohne das nanosleep verursacht dieses kurze Beispiel 100% CPU-Last, da ja der Filedeskriptor entsprechend schnell abgefragt wird. Das Benutzen der blockierenden Version ist jedoch keine Alternative, da die Anwendung mit Hilfe von Interprozesskomunikation mit anderen Programmen in Verbindung steht.

Das Ganze ist mit dem g++ kompiliert. Das System ist ein Debian Etch.


Wäre über ein paar Ratschläge dankbar.
Falls ihr noch Infos braucht.... immer raus damit.

undefined
27-03-2008, 14:09
Klassicher Multithread fehler.
Der Compiler übernimmt innerhalb der while selbst das Kommando. das heißt Adressierung und Reihenfolge übernimmt der Compiler.
Du kannst so etwas seit gcc 4 mit den OpenMp Bibliotheken unterbinden und Sortierungen /Prioritäten in der Schleife beibehalten.
Hier gibt es einen guten Artikel zu dem Thema und seine fallen http://ulm.ccc.de/
Edit: Link http://de.wikipedia.org/wiki/OpenMP

ContainerDriver
27-03-2008, 17:24
Klassicher Multithread fehler.
Der Compiler übernimmt innerhalb der while selbst das Kommando. das heißt Adressierung und Reihenfolge übernimmt der Compiler.
Du kannst so etwas seit gcc 4 mit den OpenMp Bibliotheken unterbinden und Sortierungen /Prioritäten in der Schleife beibehalten.
Hier gibt es einen guten Artikel zu dem Thema und seine fallen http://ulm.ccc.de/
Edit: Link http://de.wikipedia.org/wiki/OpenMP

Naja, das jetzige Problem hat ja gar nichts mehr mit Multihreading zu tun. Was genau meinst du eigentlich mit deinen ersten beiden Sätzen?

@zelur_em: kann es vielleicht sein, dass du mit auskommentierten nanosleep die Ausgabe von buff[0] vielleicht einfach nur übersiehst?

zelur_em
27-03-2008, 21:35
undefined: Vielen Dank für den Link. Ich habe mir vorhin den entsprechenden Vortrag angesehen. Hat mich bestimmt preventiv vor Dummheiten bewahrt. OpenMP werde ich mir auch noch mal genauer ansehen. Als ich dann gehoert habe, dass der Compiler in ungünstigen Fällen auch die lock() und unlock() Funktionen der Semaphoren wegoptimiert war ich baff.
Das mit dem eventuellen Umsortieren der while Schleife im Beispiel halte ich jedoch für unkritisch. Wenn ich da den Vortrag richtig verstanden habe ist das nur von Bedeutung wenn 2 oder mehr Threads sich die Recourcen teilen. Das oben gepostete Beispiel jedoch besitzt ja keine Threads. Und selbst bei dieser vereinfachten Version tritt der Fehler auf.

Hat eventuell einer von euch versucht das zu kompilieren und zu testen? Bei mir hängt auf der Gegenseite ein ATMEL-Microcontroller.

Eventuell ist es noch hilfreich meine Compile-Optionen zu nennen: g++ -Wall -W -pedantic -O0 $CPP-DATEI