Hinweis: Das Forum wird geschlossen! Neue Registrierungen sind nicht mehr möglich!

 Zurück zu Pro-Linux   Foren-Übersicht   FAQ     Suchen    Mitgliederliste
Threads und UDP-Sockets / Timingprobleme

 
Neuen Beitrag schreiben   Auf Beitrag antworten    Pro-Linux Foren-Übersicht -> Programmieren - C
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
Ikarisan



Anmeldungsdatum: 20.11.2006
Beiträge: 3

BeitragVerfasst am: 20. Nov 2006 13:32   Titel: Threads und UDP-Sockets / Timingprobleme

Hallo!!

Ich muss für ein Projekt eine Software realisieren, die eine gegebene Datei als UDP/RTP-Datenstrom in das Netz schickt. Alles kein Problem habe ich zuerst gesagt, aber leider muss das Senden unter bestimmten Bedingungen erfolgen.

1) Es müssen mehrere Threads / Prozesse gleichzeitig die Daten senden können (bis zu 40).
2) Die UDP-Pakete müssen in festen Zeitabständen (mind. alle 20ms) gesendet werden.

Ich habe das momentan dadurch realisiert das ich ein Hauptprogramm habe, welches je nach Anforderung bis zu 40 Threads startet. Das Hauptprogramm guckt jetzt in einer WHILE-Schleife immer welcher Thread wieder bedient werden muss. Sind die 20ms vorbei sage ich dem entsprechenden Thread mit Hilfe von pthread_cond das er was zu senden hat und dieser liest dann aus einem globalen Puffer (da steht die Datei drin) die nächsten 160Byte aus und versendet diese.

Leider funktioniert das so überhaupt nicht da ich nicht auf die 20ms komme. Die Werte schwanken zwischen 19.999ms und 180ms. Und je mehr Threads vorhanden sind desto schlechter werden die Werte.

Habe dann einmal die ganze Zeitroutine, die kontrolliert ob es was zu senden gibt, in die Threads ausgelagert. Aber selbst dann habe ich noch Schwankungen zwischen 20ms und 50ms.

Ich weiß momentan nicht mehr weiter. Momentan scheitert alles an diesen Timingproblemen. Hat eventuell jemand einen Tip für mich?

Gruß
Thorsten
 
Benutzer-Profile anzeigen Private Nachricht senden

Janka



Anmeldungsdatum: 11.02.2006
Beiträge: 3569

BeitragVerfasst am: 20. Nov 2006 15:11   Titel:

Ja. Für genaues Timing im Bereich <200ms benötigst du Echtzeitpriorität (SCHED_FIFO oder SCHED_RR). Ansonsten wertet der Prozess-Scheduler dein Programm mit der Zeit in der Priorität immer weiter runter, so dass auch mal andere Prozesse drankommen.

$ man sched_setscheduler

Du solltest dir beim Experimentieren immer auch eine Shell in eine noch höhere Echtzeitpriorität legen, damit du das System auf jeden Fall noch bedienen kannst. X ist beim Experimentieren mit Echtzeitpriorität deshalb auch tabu, also abschalten. Den X-Server mit Echtzeitpriorität zu betreiben erhöht meist die Latenz zu sehr.

Janka
_________________
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.
 
Benutzer-Profile anzeigen Private Nachricht senden

Ikarisan



Anmeldungsdatum: 20.11.2006
Beiträge: 3

BeitragVerfasst am: 20. Nov 2006 18:07   Titel:

Eventuell liegt ein Teil meines Problems schon darin wie ich auswerte ob der Thread was senden muss. Ich habe ein globales Array mit einem Struct für jeden Thread:

Code:

struct thread_data
{
   int   iThreadID;   /*!< ID des Threads um den es geht */
   int     iStatus;   /*!< Laeuft der Thread gerade? (0)Nein, (1)Ja */
   int    iPackageSize;   /*!< Paketgroesse die der Thread momentan versendet */
   int   iPackages;   /*!< Anzahl der Pakete - abhaengig von Dateigroesse */
   int   iPort;      /*!< Port an den der Thread die Daten sendet */
   char   *cIP;      /*!< IP/Rechnername an den die Daten gesendet werden */
   int   iInterval;   /*!< Intervall in dem der Thread neue Nachrichten sendet */
   long    lLastSend;   /*!< Zeitstempel der letzten gesendeten Nachricht */
   long   lOffset;   /*!< Startposition im Puffer bei der die Uebertragung beginnt */
   int     iLastPosition;   /*!< Letzte Position im Puffer nach dem Senden */
   char    *cMessage;   /*!< Die Nachricht (Payload) das RTP-Paketes */
};

struct thread_data thread_data_array[MAX_THREADS]; /*!< Struktur fuer die Threaddaten */



Und momentan schreibe ich halt ganz am Anfang in thread_data_array[i].lLastSend einen mit gettimeofday(&acct_time,NULL); ermittelten Wert. Dann wird im Thread selber in einer while(1) Schleife

1) Die Summe erzeugt aus LastSend und Intervall:
Code:
lTimeSum = thread_data_array[i].lLastSend + (long)thread_data_array[i].iInterval;
curtime = get_real_time(acct_time.tv_sec , acct_time.tv_usec); /* eigene Funktion */


2) In einer IF-Schleife geguckt ob die Zeit erreicht ist:
Code:
if ( curtime >= (lTimeSum-10) )
{
....Setzen des RTP-headers....
thread_data_array[i].lLastSend = curtime;
....Versenden des Pakets mit sendto(...);.....
}


Nehme ich die Zeitabfrage raus, also z.B. mit if(1), dann liegt laut Wireshark der Abstand zwischen den Paketen bei 3.987ms bis 4.055ms. Mit 0,07ms Schwankungen kann ich leben.

Ich habe das dumme Gefühl das meine "muss ich was senden?"-Lösung nicht wirklich optimal funktioniert. Habe aber leider keine Ahnung ob das jetzt an dem Struct-Array liegt oder eher an der gettimeofday Funktion. Oder an beiden. Sad

Gruß
Thorsten
 
Benutzer-Profile anzeigen Private Nachricht senden

Janka



Anmeldungsdatum: 11.02.2006
Beiträge: 3569

BeitragVerfasst am: 20. Nov 2006 18:55   Titel:

Oder anders gesagt, du hast eine Busy-Loop gebaut. Das ist in einem Multiprozess-/Multithreadsystem ganz schlecht, dadurch wird alles langsam. In der Zeit, in der der eine Thread sich im Kreise dreht kann der andere schlißlich nicht arbeiten

Frag nicht selbst die Zeittakte ab, lass das auf jeden Fall den Kernel machen. Evtl. hilft dir da pthread_cond_timedwait.

Janka
_________________
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.
 
Benutzer-Profile anzeigen Private Nachricht senden

Ikarisan



Anmeldungsdatum: 20.11.2006
Beiträge: 3

BeitragVerfasst am: 30. Nov 2006 14:26   Titel:

Danke!

Mit pthread_cond_timedwait() scheint es jetzt viel besser zu funktionieren. Habe jetzt Zeiten zwischen 19.992ms und 20.008ms. Allerdings sind ca. alle 30 Sekunden auch bestimmt 10 Pakete dabei, die einen Abstand von 30ms und mehr haben Sad
 
Benutzer-Profile anzeigen Private Nachricht senden

Janka



Anmeldungsdatum: 11.02.2006
Beiträge: 3569

BeitragVerfasst am: 30. Nov 2006 19:27   Titel:

Dieses letzte Problem kriegst du weg, indem du dem Prozess eine statische Priorität gibst, wie ich das oben schon angedeutet habe. Trau dich, es reißt dir deswegen keiner den Kopf ab.

Nachteil ist natürlich, dass der Prozess dann root-Rechte (echte, SUID oder sudo) braucht. Ist beim CD-Brennen ohne Burnfree ja aber auch nicht anders.

Janka
_________________
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.
 
Benutzer-Profile anzeigen Private Nachricht senden

Beiträge vom vorherigen Thema anzeigen:   
     Pro-Linux Foren-Übersicht -> Programmieren - C Alle Zeiten sind GMT + 1 Stunde
Seite 1 von 1

 
Gehen Sie zu:  

Powered by phpBB © phpBB Group
pro_linux Theme © 2004 by Mandaxy