Προς το περιεχόμενο

signal handlers


Προτεινόμενες αναρτήσεις

Δημοσ.

Καλησπέρα,

έχω την εξής απορία για την εργασία:

Όταν καλείται κάποιος signal handler (σε γλώσσα C) και εκτελείται ο κώδικας της συνάρτησης που έχει υλοποιηθεί από τον προγραμματιστή ώστε να διαχειριστεί κατάλληλα ένα σήμα, αφού εκτελεστεί ο κώδικας αυτής της συνάρτησης, που συνεχίζεται η κανονική ροή του προγράμματος;

Ευχαριστώ.

  • Απαντ. 42
  • Δημ.
  • Τελ. απάντηση

Συχνή συμμετοχή στο θέμα

Δημοσ.

Ειναι πολυ γενικο αυτο που ρωτας... Και εξαρταται απ την υλοποιηση.

Αν εδεινες κωδικα. θα ηταν πολυ πιο ευκολα τα πραγματα

Δημοσ.

Από ακριβώς το σημείο που είχε σταματήσει, δηλαδή κυριολεκτικά από την επόμενη εντολή κώδικα μηχανής (το λέω έτσι γιατί "μία εντολή" σε high level γλώσσα τυπικά μεταφράζεται σε πολλά opcodes για τη CPU).

 

Αυτό σημαίνει πως μπορεί να έχει σταματήσει η εκτέλεση του "κανονικού" προγράμματος σε νευραλγικά σημεία, δηλαδή στη μέση οποιασδήποτε function δεν είναι reentrant -- και η οποία μάλιστα μπορεί να διαχειρίζεται συμπαθητικά πράγματα όπως το heap από το οποίο γίνεται καταχώρηση μνήμης στο process σου και άλλα τέτοια ωραία.

 

Το οποίο με τη σειρά του σημαίνει πως σαν γενικό κανόνα, γράφοντας κώδικα εντός signal handler πρέπει να είσαι πιο προσεκτικός σχετικά με το τι καλείς και ποιες μεταβλητές πειράζεις απ' ότι αν ήθελες να διασχίσεις ναρκοπέδιο βάσει γραπτών οδηγιών. Όπως λέει και στο παραπάνω link:

 

Any subroutine used by the ISR that could potentially have been executing when the interrupt was triggered should be reentrant. Often, subroutines accessible via the operating system kernel are not reentrant. Hence, interrupt service routines are limited in the actions they can perform; for instance, they are usually restricted from accessing the file system and sometimes even from allocating memory.

 

Σκέψου πόσο δύσκολο είναι να αποδείξεις ότι π.χ. η malloc (ή οποιαδήποτε άλλη function την καλεί, χωρίς να περιορίζομαι σ' αυτές που έχεις γράψει εσύ) αποκλείεται να ήταν executing τη στιγμή που χτύπησε το signal. Και αν δε μπορείς να το αποδείξεις, δε μπορείς να καλέσεις ούτε malloc ούτε και καμία άλλη function που potentially καλεί τη malloc. Γενικά εκτός κι αν έχεις λάβει συγκεκριμένα μέτρα αυτή η μεταδοτική ασθένεια καταλήγει στο να μη μπορείς να καλέσεις "τίποτα" μέσα από το signal handler.

 

Update (πολύ σημαντικό): πολλές υλοποιήσεις της malloc, ιδιαίτερα σε μοντέρνες standard libraries, είναι thread-safe. Έχε υπόψη ότι thread safe δεν είναι το ίδιο πράγμα με reentrant!

  • Like 1
Δημοσ.

σε ποιο λειτουργικό? ποιο signal interrupt?

 

υπάρχουν πίνακες που μπορείς να τα κοιταξεις πχ για λειτουργικά POSIX

 

κάνε

 

>
kill -l

 

για να δεις τι παίζει στο συστημά σου ...

 

όλες οι processes εχουν προκαθορισμένες αντιδρασεις για το καθένα

όμως μπορεις αν θες να παγιδεύσεις κάποιο απ'αυτα

και ίσως να το αγνοήσεις ή να τρέξεις κάποια ρουτινά μολις το πιάσεις

 

βρες ενα πινακα που τα εξηγεί όλα για το λειτουργικό σου.

 

καλές εξηγήσεις: http://www.gnu.org/s...fining-Handlers

Δημοσ.

Ειναι πολυ γενικο αυτο που ρωτας... Και εξαρταται απ την υλοποιηση.

Αν εδεινες κωδικα. θα ηταν πολυ πιο ευκολα τα πραγματα

 

πες για παράδειγμα ότι υλοποιείς ένα shell... δηλαδή έχεις στη main έναν ατέρμον βρόχο που διαβάζει εντολές και τις εκτελεί.

Και πες πως έχεις και έναν signal handler για να ελέγχεις τι κάνει το ctrl+C.

Αν πατήσεις ctrl+C οποιαδήποτε στιγμή η ροή του προγράμματος μεταφέρεται στη συνάρτηση που διαχειρίζεται αυτό το signal.

Αφού επιστρέψει η συνάρτηση, από ποιο σημείο συνεχίζει να εκτελείται το κυρίως πρόγραμμα στη main ?

Δημοσ.
[..]Αφού επιστρέψει η συνάρτηση, από ποιο σημείο συνεχίζει να εκτελείται το κυρίως πρόγραμμα στη main ?

Τουλάχιστον σε Windows και C++ Builder όταν το signal μας είναι τύπου SIGINT, SIGTERM ή SIGBREAK τότε έχουμε προσωρινή αναστολή (suspend) του κεντρικού Thread του προγράμματος, δημιουργία μιας νέας Thread που διαχειρίζεται το signal μας και ύστερα επανέναρξη (resume) του κεντρικού Thread από το σημείο που έγινε suspend.

  • Like 1
Δημοσ.

Σε Windows με τις runtime libraries της Microsoft τα POSIX signals είναι χειρότερα από άχρηστα, θα συνιστούσα αν δεν μιλάμε για *nix είτε να τα ξεχάσεις τελείως είτε διαφορετικά να κάνεις compile με Cygwin.

Δημοσ.

Σε Windows με τις runtime libraries της Microsoft τα POSIX signals είναι χειρότερα από άχρηστα, θα συνιστούσα αν δεν μιλάμε για *nix είτε να τα ξεχάσεις τελείως είτε διαφορετικά να κάνεις compile με Cygwin.

τα νιξ δεν ειναι event based; Δεν εχουν κατι αντιστοιχο του dispacher των win;

Δημοσ.

 

 

πες για παράδειγμα ότι υλοποιείς ένα shell... δηλαδή έχεις στη main έναν ατέρμον βρόχο που διαβάζει εντολές και τις εκτελεί.

Και πες πως έχεις και έναν signal handler για να ελέγχεις τι κάνει το ctrl+C.

Αν πατήσεις ctrl+C οποιαδήποτε στιγμή η ροή του προγράμματος μεταφέρεται στη συνάρτηση που διαχειρίζεται αυτό το signal.

Αφού επιστρέψει η συνάρτηση, από ποιο σημείο συνεχίζει να εκτελείται το κυρίως πρόγραμμα στη main ?

 

>
void myhandler(int signum);

int main(void)
{
int i = 0;
struct sigaction newac, oldac;

newac.sa_handler = myhandler;
sigemptyset(&newac.sa_mask);
newac.sa_flags = 0;

sigaction(SIGINT, NULL, &oldac);
sigaction(SIGINT, &newac, NULL);

for (i = 0; i < 20; i++) {
	printf("main i = %d\n",  i);
	sleep(2);
}

return 0;
}

void myhandler(int signum)
{
printf("Handler\n");
}

 

>
Έξοδος:
main i = 0
main i = 1
^CHandler
main i = 2
^CHandler
main i = 3
^CHandler
main i = 4
main i = 5
main i = 6

 

Πολύ χαζό πρόγραμμα σε *nix χωρίς χρησιμότητα και χωρίς τους απαραίτητους ελέγχους. Σε πραγματικά προγράμματα πρέπει όπως είπε ο defacer να προσέξεις τι πειράζεις και τι καλείς γιατί μπορεί να γίνει χαμός. Θυμάμαι παλαιότερα στο DOS σε ένα TSR (Terminate and Stay Resident) πρόγραμμα δεν μπορούσες να χρησιμοποιήσεις καμμία interrupt οπότε πχ για να γράψεις στην οθόνη έπρεπε να γράψεις στην περιοχή που ήταν το "buffer" της οθόνης.

  • Like 1
Δημοσ.

παιδιά υπάρχουν πίνακες που περιγράφουν το κάθε signal interrupt σε καθε λειτουργικό

 

ο pbp νομίζω ότι ενδιαφέρεται για linux ...

 

μόλις μιλάγαμε σε ένα άλλο θέμα-νήμα

 

και επίσης νομίζω ότι κατάλαβα γιατι ρωτά για signal handlers ... :-)

Δημοσ.

τα νιξ δεν ειναι event based; Δεν εχουν κατι αντιστοιχο του dispacher των win;

 

Ούτε τα Windows (σαν λειτουργικό) είναι event based. Αυτό το event based που λες είναι ο τρόπος με τον οποίο θέλει η πλατφόρμα να λειτουργήσει η εφαρμογή σου, όπου πλατφόρμα != kernel του λειτουργικού (αυτός πολύ σκοτίστηκε για το τι κάνεις εσύ στη userland). Εσύ είσαι αυτός που γράφει κώδικα που μπαίνει σε loop και έτσι γίνεσαι "event based". Κανείς δε σου απαγορεύει να μην το κάνεις έτσι -- το πρόγραμμα θα τρέχει κανονικότατα, απλά το UI δε θα ανταποκρίνεται.

 

Ο dispatcher που λες είναι απλά το όνομα για το αφηρημένο μοντέλο του message loop που χρησιμοποιείται στη λογοτεχνία του WPF, δεν είναι κάτι ιδιαίτερο σαν έννοια.

Δημοσ.

και μιας και λέμε για signal handlers ...

Μπορεί να είναι και βλακεία.

Υπάρχει περίπτωση να μπορώ να περάσω ορίσματα σε μία συνάρτηση που διαχειρίζεται ένα signal ?

Δημοσ.

Ούτε τα Windows (σαν λειτουργικό) είναι event based. Αυτό το event based που λες είναι ο τρόπος με τον οποίο θέλει η πλατφόρμα να λειτουργήσει η εφαρμογή σου, όπου πλατφόρμα != kernel του λειτουργικού (αυτός πολύ σκοτίστηκε για το τι κάνεις εσύ στη userland). Εσύ είσαι αυτός που γράφει κώδικα που μπαίνει σε loop και έτσι γίνεσαι "event based". Κανείς δε σου απαγορεύει να μην το κάνεις έτσι -- το πρόγραμμα θα τρέχει κανονικότατα, απλά το UI δε θα ανταποκρίνεται.

 

Ο dispatcher που λες είναι απλά το όνομα για το αφηρημένο μοντέλο του message loop που χρησιμοποιείται στη λογοτεχνία του WPF, δεν είναι κάτι ιδιαίτερο σαν έννοια.

Εννοω το message queueey. Πχ η getmessage θα ξεκολλησει οταν συμβει κατι. Εχει κατι τετοιο το nix;

Δημοσ.

και μιας και λέμε για signal handlers ...

Μπορεί να είναι και βλακεία.

Υπάρχει περίπτωση να μπορώ να περάσω ορίσματα σε μία συνάρτηση που διαχειρίζεται ένα signal ?

 

Γιατί να μην μπορείς; Βασικά τι εννοείς ακριβώς;

 

Ούτε τα Windows (σαν λειτουργικό) είναι event based. Αυτό το event based που λες είναι ο τρόπος με τον οποίο θέλει η πλατφόρμα να λειτουργήσει η εφαρμογή σου, όπου πλατφόρμα != kernel του λειτουργικού (αυτός πολύ σκοτίστηκε για το τι κάνεις εσύ στη userland).

...

 

Δεν είμαι σίγουρος τι ακριβώς εννοείς, αλλά η φιλοσοφία, η λογική και η λειτουργικότητα των interrupt-handlers είναι πολύ παραπλήσια με το high-level event handling. Βασικά είναι ασφαλές να τα χαρακτηρίσουμε ως το low-level αντίστοιχο των high-level events (και vice versa).

 

Εννοω το message queueey. Πχ η getmessage θα ξεκολλησει οταν συμβει κατι. Εχει κατι τετοιο το nix;

 

Στο Unix kernel υπάρχουν βασικά 2 κατηγορίες "events": συγχρονισμένα (system calls) κι ασύγχρονα (signals).

 

Υποθέτοντας πως αναφέρεσαι στα ασύγχρονα (signals) αντί για queue υπάρχει ένα bit-field ανά process (που γενικώς αναφέρεται ως mask) , με το κάθε bit να αντιστοιχεί σε ένα signal. Επί της ουσίας τα bits αυτού του bit-field είναι τα pending signals που στέλνει το kernel στο (εκάστοτε) process.

 

Το κάθε process μπορεί να καθορίσει από πριν ποια signals θα αγνοεί πλήρως, ποια θα κάνει catch (είτε με δικές της ρουτίνες, είτε με τις default του kernel ... για κάθε signal το kernel παρέχει default signal handlers), ποια θέλει να μπλοκάρει για κάποιο διάστημα, κλπ.

Δημοσ.

Εννοω το message queueey. Πχ η getmessage θα ξεκολλησει οταν συμβει κατι. Εχει κατι τετοιο το nix;

 

Φυσικά, αλλά ανήκουν στον εκάστοτε window manager: π.χ. http://developer.gnome.org/gtk3/stable/gtk3-General.html#gtk-main-iteration και http://tronche.com/gui/x/xlib/event-handling/manipulating-event-queue/XNextEvent.html.

 

Στα Windows ο window manager θεωρείται "μέρος του λειτουργικού" παρόλο που δεν υπαρχει τεχνικά λόγος γι' αυτό (τρέχει φυσικά στη userland: user32.dll), οπότε δεν έχεις τέτοιες "επιλογές".

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα

  • Δημιουργία νέου...