dein Einwand trifft hier nicht zu, denn wegen (höchstwahrscheinlich) kernel Zugriffen funktioniert hier keine UART Kommunikation über Stunden hinweg stabil in einer main loop (es hatte sich ja immer aufgehängt nach mehreren Minuten, wenn du dich recht erinnerst) , und wenn mal eine main loop hängen sollte, ist dann komplett Hopfen und Malz verloren.
Außerdem ist aber ja doch das gesamte Prgrommdesign eh auf MT ausgelegt (SCHED_RR mit verschiedenen prios).
Die Threadüberwachug aber läuft zwar in einem high prio Thread, aber später mit langen yields/delays von mindestens 100ms pro loop (oder noch viel länger), die auf einem quadcore überhaupt nicht ins Gewicht fallen, zumal die yield Zeiten in vollem Umfang vom Scheduler den anderen time slices zur Verfügung gestellt werden.
- - - Aktualisiert - - -
PS
oder habe ich deinen Bezug falsch intepretiert?
meintest du mit Tasks die Prozesse und Sub-Prozesse mit dem pipe Ding von schorsch?
@HaWe: Genau: Er meint man sollte die Aufgaben in einzelne Prozesse verlagern. Auch die Prozesse werden vom Scheduler des Betriebsystems richtig priorisiert.
So einfach hab ich das nicht gesagt. Ich hab gesagt, daß man sich die Entscheidung ob Task oder Thread (oder auch beides) nicht zu leicht machen sollte. Ein Designfehler an dieser Stelle kann zum völligen Fehlschlag des Projektes führen.
"Auch" halte ich hier für eine unglückliche Formulierung. Unix, und das gilt auch für seine seine Clones, ist ein Multitasking System mit gekapselten Prozessen, die in eigenen Adressräumen laufen. Erst später sind Threads dazu gekommen. Der Scheduler kümmert sich also primär um Tasks und erst in zweiter Linie um die Threads der Tasks. Er arbeitet auch, wenn, wie früher. kein einziger Thread aufgesetzt wird.Auch die Prozesse werden vom Scheduler des Betriebsystems richtig priorisiert.
MfG Klebwax
Strom fließt auch durch krumme Drähte !
ist es nicht so, dass seit den POSIX C Definitionen insb. zu pthread (irgendwann schon in den 90ern) das MT per pthread eingeführt wurde?
Ich arbeite ja mit pthread, und seit C99 spätestens ist das ja Standard.
Übrigens, ich habe jetzt erfolgreich eine Methode getestet, die ich von einem netten Forumsmember des Raspi Forums bekommen habe (Paeryn).
Ist zwar auch nicht gerade leichte Kost, aber fügt sich prima in meine pthread MT Architektur ein!
Und: Es klappt jetzt damit mit dem Abbrechen eines einzelnen Threads!
Jetzt will ich sehen, ob ich ihn auch wieder starten kann und dann ob das auch auf die UART Kommunikation ausgeweitet werden kann...
Code:// Quelle. https://www.raspberrypi.org/forums/posting.php?mode=quote&f=33&p=1481807 #include <stdio.h> #include <pthread.h> #include <stdbool.h> #include <unistd.h> #include <stdlib.h> volatile bool TASKS_ACTIVE = false; volatile bool HEARTBEAT = false; // This is the cleanup function for UART_thr, it will be called if the // thread is cancelled or exits via pthread_exit(). Use it to release any // resources the thread has. void UART_thr_cleanup(void* data) { printf("UART_thr cleanup.\n"); } void* UART_thr(void* data) // UART comm (now just stalling) { int old; if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &old)) { printf("UART: Error setting async cancel state.\n"); pthread_exit(NULL); } pthread_cleanup_push(UART_thr_cleanup, NULL); HEARTBEAT = true; for(int i = 0; i < 5; i++) { printf("UART: i = %d\n", i); sleep(1); } printf("UART: simulating stall\n"); HEARTBEAT = false; while(1) ; // mimics stalling forever pthread_cleanup_pop(true); return NULL; } // We pass in a pointer to the thread id which we may need to cancel void* WATCHER_thr(void* heartbeat_id) // thread watcher { pthread_t heartbeat_thread_id = *(pthread_t*)heartbeat_id; bool THREAD_ACTIVE = true; printf("WATCHER: Checking heartbeat.\n"); while(THREAD_ACTIVE) { // // cancel UART thread if no heart beat detected if(!HEARTBEAT) { // cancel UART thread // <~~~~~~~~~ ???? pthread_kill ? pthread_cancel ? printf("WATCHER: Lost heartbeat, cancelling UART thread.\n"); pthread_cancel(heartbeat_thread_id); THREAD_ACTIVE = false; } } TASKS_ACTIVE = false; return NULL; // } // int main() { // threads pthread_t thread0, thread1, thread2; pthread_attr_t thread_attr; struct sched_param param; // start multithreading pthread_attr_init(&thread_attr); // Initialise the attributes pthread_attr_setschedpolicy(&thread_attr, SCHED_RR); // Set attributes to RR policy param.sched_priority = 40; pthread_attr_setschedparam(&thread_attr, ¶m); // Set attributes to priority 40 (policy is already RR) pthread_create(&thread2, &thread_attr, UART_thr, NULL); // medium priority: UART param.sched_priority = 80; pthread_attr_setschedparam(&thread_attr, ¶m); // Set attributes to priority 80 pthread_create(&thread0, &thread_attr, WATCHER_thr, &thread2); // high priority: heartbeat monitor pthread_attr_destroy(&thread_attr); // We've done with the attributes TASKS_ACTIVE = true; while(TASKS_ACTIVE) { printf("MAIN: tasks active, waiting\n"); sleep(1); } printf("MAIN: threads ended, goodbye.\n"); // wait for threads to join before exiting pthread_join(thread0, NULL); //pthread_join(thread1, NULL); pthread_join(thread2, NULL); exit(0); }
Nein.
Das wäre ja ein Schritt zurück zu Windows 3.11 mit darunter liegendem DOS ohne Speicherschutz. Ich zitiere mal hier (Prozess und Task sind Synonyme)
Ein Thread kann also den anderen Threads den Code überschreiben, in den Speicher schreiben oder auch einen File schließen. Das macht einem im positiven Fall das Leben leichter (keine Interprozesskommunikation nötig) bringt aber im negativen Fall alle Threads gemeinsam zum Absturz.What is a Thread?
A thread is a single sequence stream within in a process. Because threads have some of the properties of processes, they are sometimes called lightweight processes.
What are the differences between process and thread?
Threads are not independent of one other like processes as a result threads shares with other threads their code section, data section and OS resources like open files and signals. But, like process, a thread has its own program counter (PC), a register set, and a stack space.
MfG Klebwax
Strom fließt auch durch krumme Drähte !
wieso schreibst du jetzt was zu Windows? Windows ist a-priori nicht POSIX-kompatibel.
Tatsächlich (habe nachgeguckt) is threads eine Standard POSIX Extension seit 1995:
https://en.wikipedia.org/wiki/POSIX_ThreadsThreads is an API defined by the standard POSIX.1c, Threads extensions (IEEE Std 1003.1c-1995).
Aber lassen wir das mit der Historie und den Grundsatzdiskussionen:
pthread ist ANSI C99 Standard, pthread ist relativ einfach anzuwenden (sogar einfacher als std::thread finde ich), und es ist seit langem erprobt, bewährt und ohne Bugs.
Ich bn ja selber kein ausgebildeter Programmierer sondern Laie und Hobby-Anwender, und als Laie kann ich sagen, dass man sich zwar schon einarbeiten und etliche Fragen klären muss, aber wenn man das tut, dann ist es auch für Laien anwendbar (das ist mit den ganzen Fuses und Interrupts in avrstudio sicher nicht anders).
Immerhin ist pthread zur Implementierung deutlich weniger komplex als Subprozesse, daher würde ich pthread in jedem Falle den Vorzug geben.
Geändert von HaWe (20.06.2019 um 09:34 Uhr) Grund: typo
Danke für so ne Quellenangabe. Für mich sind "joinable", "detached", Thread, Prozess, Task etc im Kontext zu Programmen bzw. Programmierung eher Fremdwörter in denen ich nur sehr bescheidene Inhalte sehe, von irgendeinem Wissen zu Systemdesign mal ganz abgesehen. Das ist sehr persönlich - leider. Aber genau deswegen lese ich so etwas intensiv mit in der Hoffnung dass mal ein Schimmer aufleuchtet. Dein Link hilft da (ungemein?), danke. Und jetzt schweige ich hier wieder und lese nur noch.
Ciao sagt der JoeamBerg
PS, back to topic:
ein wenig klarer ist es mir ja jetzt geworden, was "pthread_join" macht, nach meinem begrenzten Verständnis, in einfachen Worten (nicht Expertenmode-sicher ):
- es wird im eigentlichen Wortsinn nichts von den ursprünglichen Thread-Funktionen (Thread-Code) gejoint, d.h., der Thread selber "tritt main() nicht bei" bzw. "hängt sich main() nicht an".
- es wird auch kein Thread sicher beendet, sondern nur darauf gewartet, dass der Thread endet
- dennoch müssen hnterher noch Speicher und Pointer etc. aufgeräumt werden, z.B. existiert immer noch ein thread-Handle über die thread-ID, und auch die wird erst durch pthread_join gelöscht.
- auch wenn der Thread sich nicht selber beendet, sondern er über pthread_cancel beendet wurde, ist der Thread handle noch nicht geschlossen, auch das muss noch durch ein zusätzliches pthread_join erledigt werden.
Lesezeichen