Ειδικά Θέµατα. Αντικείµενα Ιδιοτήτων. Ε-85: Ειδικά Θέµατα Λογισµικού. Αντικείµενα ιδιοτήτων (attributes objects)

Σχετικά έγγραφα
Ε-85: Ειδικά Θέµατα Λογισµικού

Προγραµµατισµός Νηµάτων. Αρχικοποίηση µιας Φοράς pthread_once_t once_block = PTHREAD_ONCE_INIT; pthread_mutex_t mutex;

Ε-85: Ειδικά Θέµατα Λογισµικού

Νήµατα. Πολύ σηµαντικό

Ε-85: Ειδικά Θέµατα Λογισµικού

Παράλληλη Επεξεργασία

Προγραμματισμός συστημάτων UNIX/POSIX. Σήματα (signals)

Προγραμματισμός Ι (ΗΥ120)

Παράλληλη Επεξεργασία

Ανάπτυξη και Σχεδίαση Λογισμικού

Εργαστήριο 14. Συγχρονισμός Νημάτων (χρήση pthread_mutex_t, pthread_cond_t)

ΝΗΜΑΤΑ - ΕΡΓΑΣΤΗΡΙΟ 1 - ΣΗΜΕΙΩΣΕΙΣ

Εισαγωγή εκτελέσιμου κώδικα σε διεργασίες

Λειτουργικά Συστήματα

26/3/2012 Προγραμματισμός συστημάτων κοινόχρηστης μνήμης (Ι) Β. Δημακόπουλος

Θέτοντας και επιστρέφοντας την τιµή της προτεραιότητας διεργασίας

Κατηγορίες Νηµάτων. Νήµατα Επιπέδου Πυρήνα. Νήµατα Επιπέδου Χρήστη. «Νήµατα Επιπέδου Χρήστη» Ε-85: Ειδικά Θέµατα Λογισµικού

Νήµαταστην Java. Συγχρονισµός νηµάτων Επικοινωνία νηµάτων Εκτελέσιµα αντικείµενα Νήµατα δαίµονες Οµάδες νηµάτων. Κατανεµηµένα Συστήµατα 11-1

Εισαγωγή στον Προγραμματισμό (με. τη C)

Δομημένος Προγραμματισμός

Εισαγωγή στον Προγραµµατισµό. Διάλεξη 3 η : Επίλυση Προβληµάτων Χειµερινό Εξάµηνο 2011

Προγραμματισμός με Κοινόχρηστο Χώρο Διευθύνσεων 4

#include <stdlib.h> Α. [-128,127] Β. [-127,128] Γ. [-128,128]

NIKOΛΑΟΣ ΝΤΙΡΛΗΣ 5ο ΦΡΟΝΤΙΣΤΗΡΙΟ ΑΙΘΟΥΣΑ Β4

Ιδιοκτησία Αντικειµένου

Εργαστήριο ΔΙΕΡΓΑΣΙΕΣ - ΔΙΑΧΕΙΡΙΣΗ

Διάλεξη 13η: Δυναμική Διαχείρηση Μνήμης, μέρος 1

Λειτουργικά Συστήματα

Λύβας Χρήστος Αρχική επιµέλεια Πιτροπάκης Νικόλαος και Υφαντόπουλος Νικόλαος

ΠΑΝΕΠΙΣΤΗΜΙΟ ΘΕΣΣΑΛΙΑΣ ΣΧΟΛΗ ΘΕΤΙΚΩΝ ΕΠΙΣΤΗΜΩΝ ΤΜΗΜΑ ΠΛΗΡΟΦΟΡΙΚΗΣ

Ανάπτυξη και Σχεδίαση Λογισμικού

Προγραμματισμός Υπολογιστών & Υπολογιστική Φυσική

Συστήματα Παράλληλης και Κατανεμημένης Επεξεργασίας

ΛΕΙΤΟΥΡΓΙΚΑ ΣΥΣΤΗΜΑΤΑ. Διεργασίες και Νήματα Εργαστηριακές Ασκήσεις

Παρουσίαση 5 ης Άσκησης:

Περιεχόμενα. Πρόλογος... 21

Δημιουργία & Τερματισμός Διεργασιών. Προγραμματισμός II 1

Προγραμματισμός συστημάτων UNIX/POSIX

Προγραμματισμός Ι. Δυναμική Διαχείριση Μνήμης. Δημήτρης Μιχαήλ. Ακ. Έτος Τμήμα Πληροφορικής και Τηλεματικής Χαροκόπειο Πανεπιστήμιο

Λειτουργικά Συστήματα. Ενότητα # 10: Προγραμματισμός UNIX Διδάσκων: Γεώργιος Ξυλωμένος Τμήμα: Πληροφορικής

Δίκτυα Επικοινωνιών ΙΙ: Network Programming UDP Sockets, Signals

Παρουσίαση 5 ης Άσκησης:

Δείκτες (Pointers) Ένας δείκτης είναι μια μεταβλητή με τιμή μια διεύθυνση μνήμης. 9.8

Πληροφορική & Τηλεπικοινωνίες K18 - Υλοποίηση Συστηµάτων Βάσεων εδοµένων Εαρινό Εξάµηνο

Δυναμική δέσμευση και αποδέσμευση μνήμης. Προγραμματισμός II 1

Διάλεξη 3η: Τύποι Μεταβλητών, Τελεστές, Είσοδος/Έξοδος

Κατανεμημένα Συστήματα

Προγραμματισμός Ι. Εγγραφές. Δημήτρης Μιχαήλ. Τμήμα Πληροφορικής και Τηλεματικής Χαροκόπειο Πανεπιστήμιο

Εθνικό Μετσόβιο Πολυτεχνείο Σχολή Ηλεκτρολόγων Μηχ. και Μηχανικών Υπολογιστών Εργαστήριο Υπολογιστικών Συστημάτων. Συγχρονισμός

Εθνικό Μετσόβιο Πολυτεχνείο Σχολή Ηλεκτρολόγων Μηχ. και Μηχανικών Υπολογιστών Εργαστήριο Υπολογιστικών Συστημάτων. Συγχρονισμός

ΕΘΝΙΚΟ ΚΑΙ ΚΑΠΟΔΙΣΤΡΙΑΚΟ ΠΑΝΕΠΙΣΤΗΜΙΟ ΑΘΗΝΩΝ ΤΜΗΜΑ ΠΛΗΡΟΦΟΡΙΚΗΣ & ΤΗΛΕΠΙΚΟΙΝΩΝΙΩΝ ΧΕΙΜΕΡΙΝΟ ΕΞΑΜΗΝΟ ΜΑΘΗΜΑ: ΛΕΙΤΟΥΡΓΙΚΑ ΣΥΣΤΗΜΑΤΑ

Κλάσεις και Αντικείµενα

Α. unsigned int Β. double. Γ. int. unsigned char x = 1; x = x + x ; x = x * x ; x = x ^ x ; printf("%u\n", x); Β. unsigned char

Καρακασίδης Αλέξανδρος Καστίδου Γεωργία Παπαφώτη Μαρία Πέτσιος Κων/νος Στέφανος Σαλτέας Καλογεράς Παναγιώτης. Threads in Java ΝΗΜΑΤΑ ΣΤΗ JAVA

είκτες και Πίνακες (2)

Η γλώσσα προγραμματισμού C

Σχεδίαση Γλωσσών Προγραμματισμού. Εαρινό Εξάμηνο Lec03 18/02/2019

Προγραμματισμός Η/Υ (ΤΛ2007 )

ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ Η/Υ Ακαδημαϊκό έτος ΤΕΤΡΑΔΙΟ ΕΡΓΑΣΤΗΡΙΟΥ #4

Ανάπτυξη Μεγάλων Εφαρµογών στη Γλώσσα C (2)

Εισαγωγή στον Προγραµµατισµό. Διάλεξη 2 η : Βασικές Έννοιες της γλώσσας προγραµµατισµού C Χειµερινό Εξάµηνο 2011

Παράλληλη Επεξεργασία

Χρήση των POSIX Threads

Ορισµός Νήµα (thread) είναι µια ακολουθιακή ροή ελέγχου (δηλ. κάτι που έχει αρχή, ακολουθία εντολών και τέλος) σ ένα

ΕΠΛ232 Προγραμματιστικές Τεχνικές και Εργαλεία Δυναμική Δέσμευση Μνήμης και Δομές Δεδομένων (Φροντιστήριο)

Εισαγωγή στον Προγραμματισμό

Προγραμματισμός συστημάτων UNIX/POSIX

Κεφάλαιο , 3.2: Συναρτήσεις II. (Διάλεξη 12)

Εικονική Μνήμη (Virtual Memory) Προγραμματισμός II 1

Σε γενικές γραμμές, είναι καλή πρακτική να γράϕουμε προγράμματα C που αποτελούνται από πολλές και μικρές συναρτήσεις, παρά από λίγες και μεγάλες.

Chapter 2. Εντολές : Η γλώσσα του υπολογιστή. (συνέχεια) Η διασύνδεση Υλικού και λογισμικού David A. Patterson και John L.

Η γλώσσα προγραμματισμού C

Εισαγωγή στον Προγραμματισμό

Δημιουργία & Τερματισμός Διεργασιών. Προγραμματισμός II 1

ΙΩΑΝΝΗΣ ΚΩΝΣΤΑΝΤΙΝΟΥ 2ο ΦΡΟΝΤΙΣΤΗΡΙΟ ΠΑΡΑΣΚΕΥΗ 26 ΟΚΤΩΒΡΙΟΥ 2012 ΑΙΘΟΥΣΑ Β4

lab13grades Άσκηση 2 -Σωστά απελευθερώνετε ολόκληρη τη λίστα και την κεφαλή

ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ ΜΑΘΗΜΑ 6 Ο. Συναρτήσεις Τοπικές, καθολικές, στατικές μεταβλητές Μεταβλητές τύπου extern και register Αναδρομή

Κεφάλαιο , 3.2: Συναρτήσεις II. ( ιάλεξη 12) ιδάσκων: ηµήτρης Ζεϊναλιπούρ

Προγραμματισμός Ι. Είσοδος/Έξοδος. Δημήτρης Μιχαήλ. Ακ. Έτος Τμήμα Πληροφορικής και Τηλεματικής Χαροκόπειο Πανεπιστήμιο

ιεργασίες και νήµατα Προγραµµατισµός ΙΙΙ 1 lalis@inf.uth.gr

Εικονική Μνήμη (Virtual Memory) Προγραμματισμός II 1

Εισαγωγή στην C. Μορφή Προγράµµατος σε γλώσσα C

Ανάπτυξη Μεγάλων Εφαρµογών στη Γλώσσα C (Programming in the large)

Δομημένος Προγραμματισμός (ΤΛ1006)

Μεθόδων Επίλυσης Προβλημάτων

Συναρτήσεις-Διαδικασίες

Περίληψη. Υπερυπολογιστές. Υπολογιστικά προβλήµατα. TOP 500 (Ιούνιος 2007) TOP 500 (Ιούνιος 2009) Ε-85: Ειδικά Θέµατα Λογισµικού

Διαδικαστικός Προγραμματισμός

Α Β Γ static; printf("%c\n", putchar( A +1)+2); B DB BD. int i = 0; while (++i); printf("*");

Διαδικασιακός Προγραμματισμός

Περιεχόμενα. Πρόλογος... 17

Ανάπτυξη και Σχεδίαση Λογισμικού

Η βασική συνάρτηση προγράμματος main()

Προγραμματισμός Ι. Κλάσεις και Αντικείμενα. Δημήτρης Μιχαήλ. Τμήμα Πληροφορικής και Τηλεματικής Χαροκόπειο Πανεπιστήμιο

Εγχειρίδιο Συναρτήσεων. Socket *sopen(const int type, const int protocol, const char *host, const char *service)

2η Προγραµµατιστική Εργασία

Υ07 Παράλληλα Συστήματα & 29/3/2016 Προγραμματισμός συστημάτων κοινόχρηστης μνήμης (Ι)

Λειτουργικά Συστήματα

Dr. Garmpis Aristogiannis - EPDO TEI Messolonghi

ΕΡΓΑΣΤΗΡΙΟ 9: Συμβολοσειρές και Ορίσματα Γραμμής Εντολής

Transcript:

Ε-85: Ειδικά Θέµατα Λογισµικού Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων Χειµερινό Εξάµηνο 2009-10 «Ειδικά Θέµατα Προγραµµατισµού Νηµάτων» Παναγιώτης Χατζηδούκας (Π.Δ. 407/80) Ειδικά Θέµατα Αντικείµενα ιδιοτήτων (attributes objects) Ιδιότητες νηµάτων Ιδιότητες των mutexes Ιδιότητες µεταβλητών συνθήκης Αρχικοποίηση µιας φοράς (one-time initialization) Ιδιωτικά δεδοµένα νήµατος Ακύρωση νηµάτων (cancellation) Χειριστές καθαρισµού Σήµατα Σηµαφόροι E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 1 E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 2 Αντικείµενα Ιδιοτήτων ηµιουργίανηµάτων και δυναµική αρχικοποίηση mutexesκαι µεταβλητών συνθήκης µε το δεύτερο όρισµα στην αντίστοιχη ρουτίνα ίσο µε NULL Το όρισµα είναι δείκτης σε ένα αντικείµενο ιδιοτήτων Τιµή NULL σηµαίνει την εξ ορισµού τιµή των ιδιοτήτων (όπως στην στατική αρχικοποίηση) Ένα αντικείµενο ιδιοτήτων µπορεί να θεωρηθεί ως µια ιδιωτική δοµή δεδοµένων. Η προσπέλαση των πεδίων της (για ανάγνωση και εγγραφή) δεν πραγµατοποιείται άµεσα αλλά πάντα µέσω κατάλληλων ρουτινών pthread_attr_getstacksize, pthread_attr_setstacksize pthread_attr_t attr; int pthread_attr_init(&attr); int pthread_attr_destroy(&attr); ιδιοτήτων νηµάτων int pthread_attr_getdetachstate(&attr, (int *) &ds); int pthread_attr_setdetachstate(&attr, (int) ds); Καθορισµός αν ένα νήµα είναι αποδεσµευµένο ή όχι PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_DETACHED E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 3 E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 4 int pthread_attr_getstacksize(&attr, (size_t *) &ss); int pthread_attr_setstacksize(&attr, (size_t) ss); Καθορισµός του µεγέθους της στοίβας ενός νήµατος Ελάχιστο µέγεθος στοίβας: PTHREAD_STACK_MIN int pthread_attr_getstackaddr(&attr, (void **) &sa); int pthread_attr_setstacksize(&attr, (void *) sa); Καθορισµός της στοίβας ενός νήµατος Η µνήµη για τη στοίβα δεσµεύεται ρητά (π.χ. malloc) Πρέπει να είναι τουλάχιστον PTHREAD_STACK_MIN εν παρέχει πλήρη µεταφερσιµότητα int pthread_attr_getscope(&attr, (int *) &cs); int pthread_attr_setscope(&attr, (int_t) cs); Καθορισµός του χώρου όπου δροµολογείται ένα νήµα (διεργασία ή λειτουργικό σύστηµα) υνατές επιλογές: PTHREAD_SCOPE_PROCESS, PTHREAD_SCOPE_SYSTEM int pthread_attr_getschedpolicy(&attr, (int *) &sp); int pthread_attr_setschedpolicy(&attr, (int) sp); Καθορισµός της πολιτικής δροµολόγησης µε την οποία θα εκτελεστούν τα νήµατα υνατές επιλογές: SCHED_FIFO,SCHED_RR,SCHED_OTHER Η προκαθορισµένη πολιτική εξαρτάται από την υλοποίηση E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 5 E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 6 1

Ιδιότητες Μutexes pthread_mutexattr_t attr; int pthread_mutexattr_init(&attr); int pthread_mutexattr_destroy(&attr); ιδιοτήτων mutexes #ifdef _POSIX_THREAD_PROCESS_SHARED int pthread_mutexattr_getpshared(&attr, (int *) &ps); int pthread_mutexattr_setpshared(&attr, (int) ps); ιαµοίραση ή µη ενός mutex µεταξύ διαφορετικών διεργασίων ps: PTHREAD_PROCESS_{PRIVATE, SHARED To mutexπρέπει να έχει δεσµευτεί σε περιοχή µνήµης που είναι κοινή µεταξύ των διεργασιών Ιδιότητες Mutexes int pthread_mutexattr_gettype(&attr, (int *) &type); int pthread_mutexattr_settype(&attr, (int ) type); Καθορισµός ορισµός του τύπου ενός mutexπου δηµιουργείται µε το αντικείµενο ιδιοτήτων attr υνατές επιλογές PTHREAD_MUTEX_NORMAL: ταχύτερη υλοποίηση χωρίς έλεγχο σφαλµάτων PTHREAD_MUTEX_RECURSIVE: ένα mutexµπορεί να κλειδωθεί πολλές φορές από το ίδιο νήµα PTHREAD_MUTEX_ERRORCHECK: για debugging κατά την ανάπτυξη εφαρµογών PTHREAD_MUTEX_DEFAULT: αντιστοιχίζεται από την εκάστοτε πλατφόρµα σε κάποια από τις παραπάνω επιλογές (συνήθως στην πρώτη) E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 7 E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 8 Ιδιότητες Μεταβλητών Συνθήκης pthread_condattr_t attr; int pthread_condattr_init(&attr); int pthread_condattr_destroy(&attr); ιδιοτήτων mutexes #ifdef _POSIX_THREAD_PROCESS_SHARED int pthread_condattr_getpshared(&attr, (int *) &ps); int pthread_condattr_setpshared(&attr, (int) ps); ιαµοίραση ή µη µιας µεταβλητής συνθήκηςµεταξύ διαφορετικών διεργασίων ps: PTHREAD_PROCESS_{PRIVATE, SHARED Η µεταβλητή συνθήκηςπρέπει να έχει δεσµευτεί σε περιοχή µνήµης που είναι κοινή µεταξύ των διεργασιών Αρχικοποίηση µιας Φοράς Αρχικοποίηση δεδοµένων (π.χ. mutexes) από την main Στην ανάπτυξη βιβλιοθηκών δεν υπάρχει αυτή η πολυτέλεια Σε εφαρµογές µε ένα νήµα µια κατάλληλη booleanµεταβλητή αρκεί για να δηλώσει ότι έγινε η αρχικοποίηση Ένα στατικά αρχικοποιηµένο mutexαρκεί µα αν απαιτείται δυναµική αρχικοποίηση τότε χρησιµοποιείται η pthread_once pthread_once_t once_control = PTHREAD_ONCE_INIT; int pthread_once(pthread_once_t *once_control, void (*init_routine)(void)); Οποιοδήποτε νήµα µπορεί να καλέσει την συνάρτηση Ελέγχεται αυτόµατα η αντίστοιχη µεταβλητή και καλείται η ρουτίνα αρχικοποίησης Αν ένα άλλο νήµα καλέσει την συνάρτηση, θα µπλοκάρει µέχρι να ολοκληρωθεί η αρχικοποίηση E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 9 E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 10 Αρχικοποίηση µιας Φοράς pthread_once_t once_block = PTHREAD_ONCE_INIT; pthread_mutex_t mutex; /* Initialization routine */ void once_init_routine(void) { pthread_mutex_init(&mutex, NULL); /* Thread start routine that calls pthread_once */ void *thread_routine(void *arg) { pthread_once(&once_block, once_init_routine); int main() { pthread_create(&t, NULL, thread_routine, NULL); pthread_once(&once_block, once_init_routine); Ιδιωτικά εδοµένα Νηµάτων ιατήρησητης τιµής µιας µεταβλητής µεταξύ κλήσεων διαφορετικών ρουτινών σε ένα συγκεκριµένο νήµα Μεταβλητές που ορίζονται ως static σε µια ρουτίνα / αρχείο µπορούν να προσπελαστούν από όλα τα νήµατα Μόνο το περιεχόµενο των καταχωρητών είναι πραγµατικό ιδιωτικό σεένα νήµα. Ακόµα και η στοίβα που θα µπορούσε να προσπελαστεί από έναάλλο νήµα pthread_key_t key; int pthread_key_create(pthread_key_t *key, void (*destructor)(void *)); int pthread_key_delete(pthread_key_t key); ηµιουργία και διαγραφή κλειδιού για αποθήκευση ιδιωτικών δεδοµένων int pthread_setspecific(pthread_key_t key, const void *value); void *pthread_getspecific(pthread_key_t key); Ανάθεση και ανάκτηση τιµής κλειδιού E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 11 E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 12 2

Ιδιωτικά εδοµένα Νηµάτων pthread_key_t key; pthread_once_t key_once = PTHREAD_ONCE_INIT; void once_routine(void) { pthread_key_create(&key, NULL); void routine() { long *value; value = pthread_setspecific(key); void *thread_routine(void *) { long *value; pthread_once(&key_once, once_routine); value = malloc(sizeof(long)); *value = (long)pthread_self(); pthread_setspecific(key, value); routine(); E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 13 Χειρισµός σφαλµάτων Στιςπαραδοσιακές διεργασίες η errnoείναι µια καθολική µεταβλητή ακέραιου (int) τύπου Μια τέτοια µεταβλητή θα ήταν άχρηστη σε ένα πολυνηµατικό πρόγραµµα Στην πραγµατικότητα, η errnoείναι ένα macroπου ορίζεται στο αρχείο <errno.h> και επιστρέφει πληροφορία ανά νήµα Κάθε νήµα έχει ένα ιδιωτικό αντίγραφο της errno #if (defined(_reentrant) extern int * errno(); #define errno (*( errno())) #else extern int errno; E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 14 Ακύρωση Νηµάτων int pthread_cancel(pthread_t thread); Ακυρώνει την εκτέλεση ενός νήµατος int pthread_setcancelstate(int state, int *ostate); Ένα νήµα επιτρέπει την ακύρωση του ή όχι PTHREAD_CANCEL_ENABLE, PTHREAD_CANCEL_DISABLE int pthread_setcanceltype(int type, int *otype); Καθορισµός του τύπου ακύρωσης Με αναβολή (deferred): PTHREAD_CANCEL_DEFERRED Ασύγχρονος (asynchronous): PTHREAD_CANCEL_ASYNCHRONOUS int pthread_testcanceltype(); Ένα νήµα ελέγχει αν έχει πάρει εντολή για να ακυρωθεί Περιπτώσεις Ακύρωσης Νήµατος Πρώτη περίπτωση Κατάσταση: απενεργοποιηµένη Είδος ακύρωσης: Και τα δύο (µε αναβολή ή ασύγχρονη) Η ακύρωση παραµένει σε εκκρεµότητα µέχρι να ενεργοποιηθεί εύτερη περίπτωση Κατάσταση: ενεργοποιηµένη Είδος ακύρωσης: Με αναβολή Η ακύρωση θα πραγµατοποιηθεί όταν το νήµα φτάσει σε ένα σηµείο ακύρωσης (π.χ. pthread_testcancel) Τρίτη περίπτωση Κατάσταση: ενεργοποιηµένη Είδος ακύρωσης: Ασύγχρονη Η ακύρωση θα πραγµατοποιηθεί οποιαδήποτε χρονική στιγµή E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 15 E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 16 Ακύρωση Νηµάτων pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; void *test_wait(void *arg){ pthread_setcancelstate(pthread_cancel_enable, NULL); pthread_setcanceltype(pthread_cancel_asynchronous, NULL); pthread_mutex_lock(&mut); /* already locked */ return NULL; int main() { pthread_mutex_lock(&mut); pthread_create(&pth, NULL, test_wait, NULL); sleep(5); pthread_cancel(pth); /* cancel blocked thread */ pthread_mutex_unlock(&mut); pthread_join(pth, NULL); /* join cancelled thread */ E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 17 Χειριστές καθαρισµού void pthread_cleanup_push(void (*routine) (void *), void *arg); void pthread_cleanup_pop(int execute); Οι χειριστές καθαρισµού είναι ρουτίνες που καλούνται όταν ένα νήµα τερµατίζει, είτε καλώντας pthread_exit είτε λόγω ακύρωσης. Εγκαθίστανται και αφαιρούνται ακολουθώντας µια µορφή στοίβας Σκοπός τους είναι η απελευθέρωση πόρων που ένα νήµα µπορεί να κρατά ενώ τερµατίζει : Ένα νήµα τερµατίζει ή ακυρώνεται ενώ κρατά κλειδωµένο ένα mutex. Η καλύτερη λύση είναι η χρήση ενός χειριστή καθαρισµού που θα ξεκλειδώνει το mutex Παρόµοιες χρήσεις: απελευθέρωση δυναµικής µνήµης (malloc/free), κλείσιµο περιγραφέων αρχείων E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 18 3

Χειριστές καθαρισµού void pthread_cleanup_push(void (*routine) (void *), void *arg); void pthread_cleanup_pop(int execute); Η pthread_cleanup_pushεγκαθιστά έναν χειριστή καθαρισµού. Από το σηµείο αυτό µέχρι την αντίστοιχη pthread_cleanup_pop, η ρουτίνα καθαρισµού routine θα κληθεί µε όρισµα arg όταν το νήµα τερµατίσει ή ακυρωθεί Αν αρκετοί χειριστές καθαρισµού είναι ενεργοί, θα κληθούν όλοι µε σειρά LIFO: ο πιο πρόσφατα εγκαταστηµένος χειριστής θα κληθεί πρώτος Η pthread_cleanup_pop αφαιρεί τον πιο πρόσφατα εγκαταστηµένο χειριστή Αν το όρισµα execute δεν είναι 0, εκτελεί επίσης τον χειριστή Αν το όρισµα execute είναι 0, ο χειριστής αφαιρείται µα δεν εκτελείται Τα ζευγάρια pthread_cleanup_pushκαι pthread_cleanup_popπρέπει να εµφανίζονται µέσα στην ίδια ρουτίνα, στο ίδιο επίπεδο κώδικα. Στην πραγµατικότητα είναι macros που εισάγουν ένα ζευγάρι αγκυλών στο κώδικα του χρήστη, δηλαδή { και αντίστοιχα pthread_cleanup_push(pthread_mutex_unlock, (void *)&mut); pthread_mutex_lock(&mut); /* do some work */ pthread_mutex_unlock(&mut); pthread_cleanup_pop(0); Οι τελευταίες δύο γραµµές µπορούν να αντικατασταθούν µε: pthread_cleanup_pop(1); Ο παραπάνω κώδικας δεν είναι ασφαλής στην περίπτωση ασύγχρονης ακύρωσης: το νήµα µπορεί να προσπαθήσει να ξεκλειδώσει ένα mutex που δεν έχει κλειδώσει E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 19 E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 20 Οπαρακάτω κώδικας επιλύει το προηγούµενο πρόβληµα της ασύγχρονης ακύρωσης pthread_setcanceltype(pthread_cancel_deferred, &oldtype); pthread_cleanup_push(pthread_mutex_unlock, (void *) &mut); pthread_mutex_lock(&mut); /* do some work */ pthread_cleanup_pop(1); pthread_setcanceltype(oldtype, NULL); void cleaner (void *data) { printf ("Clean %d\n", *(int *)data); void *thread (void *param) { int data1 = 1, data2 = 2; pthread_cleanup_push (cleaner, &data1); pthread_cleanup_push (cleaner, &data2); pthread_cleanup_pop (1); pthread_exit (param); pthread_cleanup_pop (0); /* not reached */ return NULL; E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 21 E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 22 Σήµατα #include <signal.h> int pthread kill(pthread t thread, int signo); Επιστρέφει 0 για επιτυχία, µη µηδενική τιµή σε περίπτωση σφάλµατος Τιµές σφαλµάτων ESRCH: εν αντιστοιχεί νήµα στο συγκεκριµένο αναγνωριστικό EINVAL: µη αποδεκτός αριθµός σήµατος Αποστολή σήµατος σε νήµα Τα νήµατα δεν χρησιµοποιούνται για τερµατισµό νηµάτων Η pthread_kill χρησιµοποιείται όπως η kill Το σήµα αποστέλλεται σε ένα συγκεκριµένο νήµα µα ο χειρισµός του µπορεί να επηρεάσει όλη τη διεργασία Το SIGKILL θα τερµατίσει όλη τη διεργασία Το SIGSTOP θα µπλοκάρει όλη τη διεργασία (νήµατα) Ένα νήµα µπορεί να στείλει ένα σήµα στον εαυτό του (παρόµοια µε την κλήση raise): pthread_kill(pthread_self(), signo); E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 23 E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 24 4

Όλατα νήµατα µοιράζονται τους χειριστές σηµάτων της διεργασίας Κάθε νήµα έχει την δική του µάσκα σηµάτων που αυτό µπλοκάρει Υπάρχουν τρεις τύποι σηµάτων µε διαφορετικές µεθόδους παράδοσης Ασύγχρονα:Σήµατα που δεν παραδίδονται κάποια καθορισµένη χρονική στιγµή ούτε σχετίζονται µε κάποιο συγκεκριµένο νήµα (π.χ. SIGINT). Παραδίδονται σε κάποιο νήµα που δεν έχει µπλοκάρει το σήµα Σύγχρονα: Σήµατα που παράγονται στο ίδιο σηµείο κατά την εκτέλεση ενός νήµατος (π.χ. SIGFPE, για αριθµητικό σφάλµα όπως διαίρεση µε το µηδέν). Παραδίδονται στο νήµα που προκάλεσε το σήµα. Κατευθυνόµενα: Σήµατα που αποστέλλονται σε ένα συγκεκριµένο νήµα µε την κλήση pthread_kill. Παραδίδονται στο νήµα που καθορίζεται. Όλατα νήµατα υιοθετούν τη µάσκα σηµάτων (ποια σήµατα είναι µπλοκαρισµένα) από το νήµα που τα δηµιουργεί Η µάσκα σηµάτων µπορεί να τεθεί µε την κλήση pthread_sigmask Οι ενέργειες σηµάτων έχουν εµβέλεια διεργασίας. εν µπορεί να υπάρχει για το ίδιο σήµα ένα χειριστής σε κάποιο νήµα και ένας διαφορετικός χειριστής σε κάποιο άλλο νήµα Ένα σήµα παραδίδεται σε ένα νήµα. Αν ένα δεύτερο σήµα φτάσει ενώ το πρώτο σήµα βρίσκεται υπό επεξεργασία, το σήµα παραδίδεται σε κάποιο άλλο νήµα, εφόσον υπάρχει κάποιο που δεν το έχει µπλοκαρισµένο (ισχύει για ασύγχρονα σήµατα µόνο) Πρακτικά, η µάσκα σηµάτων και οι χειριστές σηµάτων τίθενται στο κύριο νήµα, µια φορά E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 25 E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 26 Τασήµατα πάντα παραδίδονται αρκεί να υπάρχουν νήµατα που δεν τα µπλοκάρουν, ακόµα κι αν ένα άλλο νήµα εκτελεί έναν χειριστή σήµατος Συνηθισµένη τακτική είναι ένα συγκεκριµένο νήµα να χειρίζεται όλα τα ασύγχρονα σήµατα Το κύριο νήµα µπλοκάρει όλα τα εισερχόµενα σήµα. Αφού τα νήµα που δηµιουργούνται υιοθετούν τη µάσκα σηµάτων, όλα τα νήµατα θα έχουν τα σήµατα µπλοκαρισµένα ηµιουργείται ένα ξεχωριστό νήµα για χειρισµό σηµάτων, το οποίο καλεί την sigwait. Τα σήµατα για τα οποία έχουν οριστεί χειριστές ξεµπλοκάρονται για το συγκεκριµένο νήµα. Το νήµα καλεί την sigwaitµέσα σε ένα βρόχο, αφού η συνάρτηση επιστρέφει όταν ο χειριστής σήµατος καλείται Μιασυνάρτηση των νηµάτων POSIX δεν πρέπει να καλείται µέσα από έναν χειριστή σήµατος Μια συνάρτηση είναι async-signal safe εφόσον µπορεί να διακοπεί µε ασφάλεια από ένα σήµα και να ξεκινήσει αφού ο χειριστής σήµατος επιστρέψει, ακόµα κι αν ο χειριστής σήµατος καλέσει την ίδια την ρουτίνα Συναρτήσεις που χρησιµοποιούν εσωτερικά στατικές δοµές δεν είναι async-safeεκτός κι αν µπλοκάρουν τα σήµατα ώστε να µη διακοπεί η εκτέλεσή τους Καµία συνάρτηση των νηµάτων POSIX δεν είναι ασφαλής. Το µπλοκάρισµα των σηµάτων έχει υψηλό κόστος αφού πρόκειται για κλήση συστήµατος Οι συναρτήσεις των νηµάτων POSIX έχουν σχεδιαστεί για ταχύτητα παρά για ασφάλεια E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 27 E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 28 Σηµαφόροι Πρέπει να αρχικοποιούνται δυναµικά sem_t sem; sem_init( &sem, 0, 5 ); sem_destroy( &sem ); Βασικές λειτουργίες sem_post( &sem ); // + sem_wait( &sem ); // - (block if <= 0) sem_trywait( &sem ); sem_getvalue( &sem ); Μπορούν να χρησιµοποιηθούν µε ασφάλεια µέσα από χειριστές σηµάτων Η κλήση sem_wait() µπορεί να διακοπεί: do { err = sem_wait(&sem); while ( err=eintr ); THREAD 1 sem_wait (&mutex); a = data; a++; data = a; sem_post (&mutex); Σηµαφόροι sem_t mutex; sem_init(&mutex, 0, 1); THREAD 2 sem_wait (&mutex); b = data; b--; data = b; sem_post (&mutex); E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 29 E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 30 5