Γιατί πολλά προγράμματα Unix χρησιμοποιούν σήματα όπως το USR1; Αξιόπιστα σήματα

Τα σήματα είναι διακοπές λογισμικού. Χρησιμοποιούνται για επικοινωνία μεταξύ διεργασιών σε UNIX και τύπου UNIX λειτουργικά συστήματαόπως Linux, Mac OS.

Τα σήματα χρησιμοποιούνται από την Bell Labs UNIX το 1970 και πλέον ορίζονται επίσημα από το πρότυπο POSIX. Όταν ένα σήμα λαμβάνεται από μια διεργασία, το λειτουργικό σύστημα διακόπτει την κανονική ροή εκτέλεσης της διαδικασίας και παρέχει ειδοποίηση.

Δεν έχει σημασία τι λειτουργικό σύστημα χρησιμοποιείτε, αναμφίβολα θα βιώσετε τις εφαρμογές σας να μπλοκάρονται και να αρνούνται να λειτουργήσουν σωστά. Στο Unix, στο Linux, υπάρχει μια εντολή "kill" που μπορείτε να χρησιμοποιήσετε για να σκοτώσετε τη διαδικασία αμέσως, αλλά όχι μόνο αυτό, αλλά θα μιλήσω για αυτό λίγο αργότερα. Σε αυτό το άρθρο "Kill Command in Unix/Linux" θα σας εξηγήσω και θα σας δείξω πώς να το κάνετε έτοιμα παραδείγματαδιάφορες εντολές του βοηθητικού προγράμματος kill.

Εντολές και σήματα Kill

Όταν εκδίδετε την εντολή kill, στην πραγματικότητα στέλνετε ένα σήμα στο σύστημα και του δίνετε εντολή να τερματίσει τη χαλασμένη εφαρμογή. Υπάρχουν συνολικά 60 σήματα που μπορούν να χρησιμοποιηθούν, αλλά το μόνο που πραγματικά χρειάζεται να γνωρίζετε είναι το SIGTERM (15) και το SIGKILL (9).

Μπορείτε να δείτε όλα τα σήματα χρησιμοποιώντας την εντολή:

# kill -l

Στο MacOS μου:

Θα προσπαθήσω να μιλήσω για όλα τα σήματα, αλλά πρώτα θα μιλήσουμε μόνο για τα πιο σημαντικά και συχνά χρησιμοποιούμενα.

Βασικά σήματα

Τα ακόλουθα σήματα αποτελούν μέρος του προτύπου POSIX. Κάθε σήμα είναι μια μακροεντολή που ορίζεται στο Αρχείο κεφαλίδας συστήματος. Συνήθως συντομεύονται χωρίς το πρόθεμά τους SIG. για παράδειγμα το SIGHUP συχνά αναφέρεται απλώς ως HUP.

SIGTERM– Αυτό το σήμα ζητά να σταματήσει μια διαδικασία που εκτελείται. Αυτό το σήμα μπορεί να αγνοηθεί. Δίνεται χρόνος για να κλείσει καλά. Όταν ένα πρόγραμμα κλείνει καλά, σημαίνει ότι του δόθηκε χρόνος για να σώσει την πρόοδό του και να απελευθερώσει πόρους. Δεν «ανάγκασε» δηλαδή να τερματιστεί η διαδικασία.

ΣΙΓΚΙΛ– Το σήμα SIGKILL αναγκάζει τη διαδικασία να σταματήσει αμέσως τη δουλειά της. Το πρόγραμμα δεν μπορεί να αγνοήσει αυτό το σήμα. Η μη αποθηκευμένη πρόοδος θα χαθεί.

Σύνταξη για το "σκότωσε".

Η σύνταξη της εντολής είναι:

# σκοτώστε τα PID

# kill [-s] [-l] %pid

Το προεπιλεγμένο σήμα (αν δεν έχει καθοριστεί) είναι SIGTERM. Όταν αυτό το σήμα δεν βοηθά και δεν λειτουργεί, μπορείτε να χρησιμοποιήσετε τις ακόλουθες επιλογές για "kill" για να τερματίσετε αναγκαστικά τη διαδικασία:

# kill SIGKILL PID

# kill -9 PID

όπου "-9" είναι η σημαία που αναφέρεται στο σήμα SIGKILL.

Εάν δεν ξέρετε ποιο PID να χρησιμοποιήσετε για την εφαρμογή από την οποία θέλετε να απαλλαγείτε, τότε εκτελέστε την εντολή:

$ps -aux

Και αν ξέρεις συγκεκριμένη εφαρμογή(για παράδειγμα, apache), τότε μπορείτε να εξαλείψετε τα περιττά και να εμφανίσετε όλες τις διαδικασίες για αυτήν την υπηρεσία:

$ ps -aux | grep apache

Και θα εμφανίσει τα πάντα εκτελούμενες εφαρμογέςμαζί με τα PID του.

Για παράδειγμα, για να σκοτώσω μια εφαρμογή, εκτελώ την ακόλουθη εντολή:

# kill -9 3629

Αξίζει επίσης να σημειωθεί ότι μπορείτε να έχετε πολλές διεργασίες που εκτελούνται ταυτόχρονα, ώστε να μπορούν να "σκοτωθούν":

# kill -9 PID1 PID2 PID 3

Γεμίζω πάλι αρχεία ρυθμίσεωνή επανεκκινήστε τα βοηθητικά προγράμματα:

# kill -1 αριθμός_of_PID

Τα ιδιαίτερα χρήσιμα σήματα περιλαμβάνουν HUP, INT, kill, STOP, CONT και 0.

Οι επιλογές είναι:

-s signal_name
Ένα συμβολικό όνομα σήματος που καθορίζει το σήμα για την αποστολή ενός μη προεπιλεγμένου σήματος.

-μεγάλο
Εάν ο τελεστής δεν έχει καθοριστεί, τότε εμφανίστε τα ονόματα των σημάτων. Διαφορετικά, γράψτε το όνομα του σήματος που αντιστοιχεί στο exit_status.

-signal_name
Συμβολικό όνομα σήματος που καθορίζει το σήμα που θα σταλεί στον TERM από προεπιλογή.

-signal_number
Ένας μη αρνητικός δεκαδικός ακέραιος που καθορίζει το προεπιλεγμένο σήμα προς αποστολή στο TERM.

Τα ακόλουθα PID έχουν ειδική σημασία:
-1 Εάν ο υπερχρήστης, τότε εκπέμπει το σήμα σε όλες τις διεργασίες. διαφορετικά μεταδίδεται σε όλες τις διεργασίες που ανήκουν-
για τον χρήστη.

Μερικά από τα πιο συχνά χρησιμοποιούμενα σήματα είναι:

  • 1 HUP (κλείνω) - κλείνω.
  • 2 INT (διακοπή) - διακοπή.
  • 3 QUIT (έξοδος) - έξοδος.
  • 6 ABRT (ακύρωση) - διακοπές.
  • 9 KILL (μη συλλήψιμο, μη αγνόητο φόνο)
  • 14 ALRM (ξυπνητήρι) - ξυπνητήρι.
  • 15 TERM (σήμα τερματισμού λογισμικού) — Λογισμικόνα σταματήσει το σήμα.

PKill

Η εντολή "pkill" σάς επιτρέπει να χρησιμοποιείτε προηγμένα μοτίβα κανονικών εκφράσεων και άλλα κριτήρια αντιστοίχισης. Αντί να χρησιμοποιήσετε το PID, μπορείτε τώρα να σκοτώσετε την εφαρμογή εισάγοντας το όνομα της διαδικασίας. Για παράδειγμα, για να σκοτώσετε το πρόγραμμα περιήγησης Firefox, απλώς εκτελέστε την εντολή:

#pkill Firefox

Γιατί ταιριάζει με το μοτίβο κοινή έκφραση, μπορείτε επίσης να εισαγάγετε μέρος του ονόματος της διαδικασίας, όπως αυτό:

#pkillfire

Για να αποφύγετε να "σκοτώσετε" τις λανθασμένες διεργασίες, μπορείτε να κάνετε "pgrep -l [όνομα_διαδικασίας]" για να παραθέσετε τις κατάλληλες διεργασίες.

Η εντολή pkill έχει πολλές περισσότερες επιλογές, για παράδειγμα αν ορίσετε την επιλογή "-u", θα σας επιτρέψει να καθορίσετε ένα όνομα χρήστη ή ένα αναγνωριστικό. Σε αυτό το παράδειγμα, στέλνουμε το σήμα TERM σε όλες τις διεργασίες που ανήκουν στον χρήστη "κανένας":

# pkill -u κανένας

Killall

Το Killall χρησιμοποιεί το όνομα διεργασίας αντί για το PID και "σκοτώνει" όλες τις παρουσίες της διαδικασίας με το ίδιο όνομα. Για παράδειγμα, εάν εκτελείτε πολλές παρουσίες του προγράμματος περιήγησης Firefox, μπορείτε να τις σκοτώσετε όλες με την εντολή:

#killallfirefox

Στο Gnome, μπορείτε να επανεκκινήσετε το Nautilus με την εντολή:

#killallnautilus

xkill

Ο Xkill είναι γραφικά"σκοτώστε" την εφαρμογή. Όταν εισάγετε "XKill" στο τερματικό, ο δρομέας του ποντικιού θα γίνει αμέσως "σταυρός". Το μόνο που έχετε να κάνετε είναι να πατήσετε "σταυρός" στην προσβλητική εφαρμογή και θα σκοτώσει την εφαρμογή αμέσως. Εάν σας ενδιαφέρει, μπορείτε να προσθέσετε μια συντόμευση πληκτρολογίου για να ενεργοποιήσετε τη λειτουργία XKill.

Άλλα σήματα που χρησιμοποιούνται

SIGABRT

Αυτό το σήμα στέλνει ένα σήμα στη διαδικασία για να ματαιώσει τη λειτουργία. Το ABRT κατευθύνεται συνήθως στην ίδια τη διεργασία όταν καλεί τη συνάρτηση abort() της γλώσσας προγραμματισμού C για να σηματοδοτήσει έναν μη φυσιολογικό τερματισμό, αλλά μπορεί να κατευθυνθεί από οποιαδήποτε διεργασία όπως και κάθε άλλο σήμα.

SIGALRM, SIGVTALRM και SIGPROF

Το σήμα ALRM, VTALRM ή/και PROF αποστέλλεται σε μια διεργασία όταν έχει λήξει ένα χρονικό όριο που καθορίζεται από μια κλήση σε μια λειτουργία συναγερμού (όπως ο ρυθμιστής).

ALRM

Στάλθηκε όταν περνάει η παρούσα ώρα ή ρολόι.

VTALRM

Αποστέλλεται όταν ο χρόνος CPU που χρησιμοποιείται από μια διεργασία έχει λήξει.

ΠΡΟΦ

Αποστέλλεται όταν λήξει ο χρόνος CPU που χρησιμοποιείται από μια διεργασία και το σύστημα για λογαριασμό της διεργασίας.

SIGBUS

Ένα σήμα BUS αποστέλλεται σε μια διεργασία όταν οδηγεί σε σφάλμα διαύλου. Συνθήκες που οδηγούν σε αυτό το σήμα, όπως κακή ευθυγράμμιση πρόσβασης στη μνήμη ή έλλειψη φυσικής διεύθυνσης.

SIGCHLD

Το σήμα CHLD αποστέλλεται σε μια διεργασία όταν μια θυγατρική διαδικασία τερματίζεται, διακόπτεται ή συνεχίζεται μετά τη διακοπή. Μια κοινή χρήση ενός σήματος είναι να δίνει σήμα στο λειτουργικό σύστημα για να καθαρίσει τους πόρους που χρησιμοποιούνται από μια θυγατρική διεργασία μετά τον τερματισμό της, χωρίς ρητή κλήση συστήματος.

SIGCONT

Το σήμα CONT δίνει εντολή στο λειτουργικό σύστημα να επανεκκινήσει μια διαδικασία που είχε προηγουμένως ανασταλεί από ένα σήμα STOP ή TSTP. Ένα από τα σημαντικά χαρακτηριστικά αυτού του σήματος είναι ο έλεγχος της λειτουργίας στο κέλυφος του Unix.

ΣΙΓΦΠΕ

Το σήμα FPE αποστέλλεται σε μια διεργασία όταν εκτελεί λανθασμένες αριθμητικές πράξεις, όπως η διαίρεση με το μηδέν.

ΣΙΓΧΟΥΠ

Το σήμα HUP αποστέλλεται σε μια διεργασία όταν το τερματικό ελέγχου είναι κλειστό. Αρχικά σχεδιάστηκε για να ειδοποιεί μια διαδικασία μετά από διαδοχικές πτώσεις γραμμής (HUP υπεύθυνο για κολλήματα). ΣΕ σύγχρονα συστήματα, αυτό το σήμα συνήθως σημαίνει ότι ο ψευδο ή εικονικός έλεγχος τερματικού έχει κλείσει.

ΣΙΓΙΛ

Το σήμα ILL αποστέλλεται σε μια διεργασία όταν επιχειρεί να εκτελέσει κακόβουλες, άγνωστες ή προνομιακές εντολές (εντολές).

ΣΗΜΕΙΩΣΗ

Το σήμα INT αποστέλλεται σε μια διεργασία από το τερματικό ελέγχου όταν ο χρήστης επιθυμεί να τερματίσει τη διαδικασία. Αυτό συνήθως ξεκινά με το πάτημα του Control-C, αλλά σε ορισμένα συστήματα, "διαγραφή" ή "διακοπή".

ΣΙΓΚΙΛ

Το σήμα KILL αποστέλλεται σε μια διεργασία για να σταματήσει να εκτελείται αμέσως. Σε αντίθεση με το SIGTERM και το SIGINT, αυτό το σήμα δεν μπορεί να καταγραφεί ή να αγνοηθεί και η διαδικασία λήψης δεν μπορεί να εκτελέσει καμία εκκαθάριση μετά τη λήψη αυτού του σήματος.

SIGPIPE

Το σήμα PIPE αποστέλλεται σε μια διεργασία όταν επιχειρεί να γράψει σε έναν σωλήνα χωρίς διεργασία συνδεδεμένη στο άλλο άκρο.

SIGQUIT

Το σήμα QUIT αποστέλλεται σε μια διεργασία από το τερματικό ελέγχου της, όταν ο χρήστης ζητήσει από τη διαδικασία να εκτελέσει μια απόρριψη.

SIGSEGV

Το σήμα SEGV αποστέλλεται σε μια διεργασία όταν κάνει μια μη έγκυρη αναφορά εικονική μνήμηή σφάλμα τμηματοποίησης, δηλαδή όταν εκτελεί παραβίαση τμηματοποίησης.

SIGSTOP

Το σήμα STOP λέει στο λειτουργικό σύστημα να σταματήσει τη διαδικασία, ώστε να μπορεί να συνεχιστεί αργότερα.

SIGTERM

Το σήμα TERM αποστέλλεται σε μια διεργασία για να ζητήσει τον τερματισμό της. Σε αντίθεση με το σήμα «θανάτωσης», μπορεί να ερμηνευτεί ή να αγνοηθεί κατά τη διάρκεια της διαδικασίας. Αυτό επιτρέπει στη διαδικασία να εκτελέσει "ωραία" εκτέλεση για να σταματήσει την απελευθέρωση πόρων και να αποθηκεύσει κατάσταση εάν είναι απαραίτητο. Πρέπει να σημειωθεί ότι το SIGINT είναι σχεδόν πανομοιότυπο με το SIGTERM.

SIGTSTP

Το σήμα TSTP αποστέλλεται στη διαδικασία τερματικού ελέγχου και του λέει να αναστείλει προσωρινά. Αυτό συνήθως ξεκινά με το πάτημα του Control-Z από τον χρήστη. Σε αντίθεση με το SIGSTOP, αυτή η διαδικασία μπορεί να καταχωρήσει έναν χειριστή σήματος ή να αγνοήσει το σήμα.

SIGTTIN και SIGTTOU

Τα σήματα TTIN και TTOU αποστέλλονται σε μια διεργασία όταν επιχειρεί να διαβάσει ή να γράψει, αντίστοιχα, από ένα τερματικό (tty) στο παρασκήνιο. Κατά κανόνα, αυτό το σήμα μπορεί να ληφθεί μόνο χρησιμοποιώντας διαδικασίες υπό έλεγχο πίνακας εργασίας; Οι δαίμονες δεν έχουν τερματικά ελέγχου και δεν πρέπει ποτέ να λαμβάνουν αυτό το σήμα.

SIGUSR1 και SIGUSR2

Τα σήματα USR1 και USR2 αποστέλλονται στη διεργασία και υποδεικνύουν συνθήκες που καθορίζονται από το χρήστη.

SIGPOLL

Το σήμα POLL αποστέλλεται σε μια διεργασία όταν συμβαίνει ένα ασύγχρονο συμβάν εισόδου/εξόδου.

ΣΙΓΣΥΣ

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

SIGTRAP

Ένα σήμα TRAP αποστέλλεται σε μια διεργασία όταν παρουσιάζεται μια συνθήκη για την οποία ο εντοπιστής σφαλμάτων έχει ζητήσει να ενημερωθεί - για παράδειγμα, όταν εκτελείται μια συγκεκριμένη συνάρτηση ή όταν αλλάζει μια συγκεκριμένη τιμή μιας μεταβλητής.

SIGURG

Το σήμα URG αποστέλλεται σε μια διεργασία όταν η πρίζα έχει επείγοντα ή εκτός εμβέλειας δεδομένα διαθέσιμα για ανάγνωση.

SIGXCPU

Το σήμα XCPU αποστέλλεται σε μια διεργασία όταν χρησιμοποιεί την CPU για χρονικό διάστημα που υπερβαίνει ένα ορισμένο σημείο ρύθμισης που έχει ορίσει ο χρήστης. Η άφιξη του σήματος XCPU διασφαλίζει ότι η διαδικασία αποθηκεύει γρήγορα όλα τα ενδιάμεσα αποτελέσματα και εξέρχεται πολύ πριν σκοτωθεί από το λειτουργικό σύστημα με ένα σήμα SIGKILL.

SIGXFSZ

Το σήμα XFSZ αποστέλλεται στη διαδικασία όταν ένα αρχείο μεγαλώσει (υπερβαίνει μια καθορισμένη τιμή) από τη μέγιστη επιτρεπόμενη τιμή.

SIGRTMIN προς SIGRTMAX

Τα σήματα RTMIN - RTMAX προορίζονται για χρήση για προσαρμοσμένους σκοπούς. Είναι σήματα πραγματικού χρόνου.

Διαφορετικά σήματα

Τα ακόλουθα σήματα δεν είναι τυποποιημένα από το POSIX, αλλά μερικές φορές χρησιμοποιούνται σε ορισμένα συστήματα.

SIGEMT

Το σήμα EMT αποστέλλεται κατά τη διάρκεια της διαδικασίας όταν παρουσιαστεί μια διακοπή του εξομοιωτή.

SIGINFO

Το σήμα INFO αποστέλλεται σε εξέλιξη όταν λαμβάνεται ένα αίτημα κατάστασης από το τερματικό ελέγχου.

SIGPWR

Το σήμα PWR αποστέλλεται σε διαδικασία όταν το σύστημα αντιμετωπίζει διακοπή ρεύματος.

SIGLOST

Το σήμα LOST αποστέλλεται σε μια διεργασία όταν χαθεί ένα "κλείδωμα αρχείου".

SIGWINCH

Το σήμα WINCH αποστέλλεται σε μια διεργασία όταν το τερματικό ελέγχου του αλλάξει το μέγεθός του.

Αποστολή σημάτων από το πληκτρολόγιο

Τα σήματα μπορούν να σταλούν από το πληκτρολόγιο. Πολλές τυπικές προεπιλεγμένες τιμές παρατίθενται παρακάτω. Από προεπιλογή, οι συντομεύσεις πληκτρολογίου για την αποστολή σημάτων διακοπής μπορούν να οριστούν χρησιμοποιώντας την εντολή stty.

CTRL-C

Αποστολή SIGINT (διακοπή). Από προεπιλογή, αυτό προκαλεί τον τερματισμό της διαδικασίας.

CTRL-Z

Αποστολή SIGTSTP (Αναστολή). Από προεπιλογή, αυτό αναγκάζει τη διαδικασία να αναστείλει όλες τις λειτουργίες.

CTRL-\

Αποστολή SIGQUIT (Έξοδος). Από προεπιλογή, αυτό προκαλεί τον τερματισμό της διαδικασίας αμέσως και την επαναφορά του πυρήνα.

CTRL-T

Αποστολή SIGINFO (ΠΛΗΡΟΦΟΡΙΕΣ). Από προεπιλογή, αυτό προκαλεί το λειτουργικό σύστημα να εμφανίζει πληροφορίες σχετικά με την εντολή. Δεν υποστηρίζεται σε όλα τα συστήματα.

συμπέρασμα

Όταν οι εφαρμογές δεν συμπεριφέρονται σωστά και προκαλούν το πάγωμα του συστήματος, είναι πολύ δελεαστικό να επανεκκινήσετε τον υπολογιστή σας και να ξεκινήσετε ξανά τη συνεδρία. Με αυτές τις εντολές "kill", μπορείτε να διαχειριστείτε καλύτερα την κακή συμπεριφορά των εφαρμογών που προκαλούν ή μπορεί να προκαλέσουν σφάλμα συστήματος. Με αυτό, ολοκληρώνω αυτό το θέμα "Η εντολή kill στο Unix/Linux".

Αξιόπιστα σήματα

Πρότυπο POSIX. 1 ορίζεται νέο σετλειτουργίες διαχείρισης σήματος. βασίζεται στη διεπαφή UNIX 4.2BSD και στερείται των μειονεκτημάτων που αναφέρθηκαν παραπάνω.

Το μοντέλο σηματοδότησης POSIX βασίζεται στην ιδέα σύνολο σημάτων(σύνολο σήματος) που περιγράφεται μεταβλητού τύπου sigset_t . Κάθε bit αυτής της μεταβλητής αντιπροσωπεύει ένα σήμα. Σε πολλά συστήματα, ο τύπος sigset_t έχει μήκος 32 bit, περιορίζοντας τον αριθμό των πιθανών σημάτων σε 32.

Οι ακόλουθες λειτουργίες σάς επιτρέπουν να διαχειρίζεστε σύνολα σημάτων:

#περιλαμβάνω

int sigempyset(sigset_t *set);

int siufillset(sigset_t *set);

int sigaddset(sigset_t *set, int signo);

int sigdelset(sigset_t *set, int signo);

int sigismember(sigset_t *set, int signo);

Σε αντίθεση με τη συνάρτηση σήμα (3C), αλλάζοντας τη διάταξη των σημάτων, αυτές οι λειτουργίες σάς επιτρέπουν να τροποποιήσετε τη δομή δεδομένων sigset_t που ορίζεται από τη διαδικασία. Για τον απευθείας έλεγχο των σημάτων, χρησιμοποιούνται πρόσθετες λειτουργίες, το οποίο θα εξετάσουμε αργότερα.

Λειτουργία sigemptyset(3C)αρχικοποιεί το σύνολο διαγράφοντας όλα τα bit. Εάν ζητήσει μια διαδικασία sigfillset (3C), τότε το σετ θα περιλαμβάνει όλα τα σήματα που είναι γνωστά στο σύστημα. Λειτουργίες sigaddset(3C)Και sigdelset(3C)Σας επιτρέπει να προσθέτετε ή να αφαιρείτε ήχους κλήσης. Λειτουργία sigismember(3C)σας επιτρέπει να ελέγξετε αν καθορίζεται από την παράμετροσήμα για ρύθμιση.

Αντί για συνάρτηση σήμα (3C)Πρότυπο POSIX. 1 ορίζει μια συνάρτηση sigaction (2), το οποίο σας επιτρέπει να ρυθμίσετε τη διάταξη των σημάτων, να μάθετε την τρέχουσα τιμή του ή να κάνετε και τα δύο ταυτόχρονα. Η συνάρτηση έχει τον ακόλουθο ορισμό:

#περιλαμβάνω

int sigaction (int sig, const struct sigaction *act,

struct sigaction *oact);

Όλες οι απαραίτητες πληροφορίες για τη διαχείριση του σήματος περνούν μέσω ενός δείκτη στη δομή sigaction, η οποία έχει τα ακόλουθα πεδία:

Το πεδίο sa_handler καθορίζει την ενέργεια που πρέπει να γίνει όταν λαμβάνονται σήματα και μπορεί να λάβει τις τιμές SIG_IGN, SIG_DFL ή τη διεύθυνση της συνάρτησης χειριστή. Εάν το sa_handler ή το sa_sigaction δεν είναι NULL, τότε στο πεδίο sa_mask μεταβιβάζεται ένα σύνολο σημάτων που θα προστεθούν στη μάσκα σήματος πριν καλέσετε τον χειριστή. Κάθε διεργασία έχει εγκατεστημένη μια μάσκα σήματος που καθορίζει τα σήματα των οποίων η παράδοση θα πρέπει να αποκλειστεί. Εάν έχει οριστεί ένα συγκεκριμένο bit μάσκας, το αντίστοιχο σήμα θα απενεργοποιηθεί. Μετά την επιστροφή της συνάρτησης χειριστή, η τιμή μάσκας επιστρέφει στην αρχική της τιμή. Σημειώστε ότι το σήμα για το οποίο έχει ρυθμιστεί η λειτουργία χειριστή θα αποκλειστεί επίσης πριν την κλήση. Αυτή η προσέγγιση διασφαλίζει ότι κατά τη διάρκεια της επεξεργασίας, οι επόμενες αφίξεις ορισμένων σημάτων θα ανασταλούν μέχρι να ολοκληρωθεί η λειτουργία. Συνήθως, το UNIX δεν υποστηρίζει ουρές σήματος, πράγμα που σημαίνει ότι ο αποκλεισμός πολλαπλών σημάτων του ίδιου τύπου θα προκαλέσει τελικά την παράδοση μόνο ενός.

Το πεδίο sa_flags ορίζει σημαίες που τροποποιούν την παράδοση του σήματος. Μπορεί να λάβει τις ακόλουθες τιμές:

SA_ONSTACK Εάν έχει οριστεί μια λειτουργία χειριστή σήματος και χρησιμοποιείται η συνάρτηση sigaltstack(2)Εάν έχει καθοριστεί μια εναλλακτική στοίβα για τη λειτουργία χειριστή, τότε αυτή η στοίβα θα χρησιμοποιηθεί κατά την επεξεργασία του σήματος. Εάν η σημαία δεν έχει οριστεί, θα χρησιμοποιηθεί η κανονική στοίβα της διαδικασίας.
SA_RESETHAND * Εάν οριστεί μια λειτουργία χειριστή, η διάταξη του σήματος θα αλλάξει σε SIG_DFL και το σήμα δεν θα μπλοκάρει όταν εκτελείται ο χειριστής. Εάν η σημαία δεν έχει οριστεί, η διάταξη του σήματος παραμένει αμετάβλητη.
SA_NODEFER * Εάν έχει οριστεί μια συνάρτηση χειριστή, το σήμα μπλοκάρεται για τη διάρκεια της επεξεργασίας μόνο εάν ορίζεται ρητά στο πεδίο sa_mask. Εάν η σημαία δεν έχει οριστεί, αυτό το σήμα μπλοκάρεται αυτόματα κατά την επεξεργασία.
SA_RESTART Εάν έχει οριστεί μια λειτουργία χειριστή, ένας αριθμός κλήσεων συστήματος που διακόπηκαν από ένα ληφθέν σήμα θα επανεκκινηθούν αυτόματα μετά την επεξεργασία του σήματος. Εάν η σημαία δεν έχει οριστεί, η κλήση συστήματος θα επιστρέψει ένα σφάλμα EINTR.
SA_SIGINFO * Εάν η διάταξη υποδεικνύει υποκλοπή σήματος, καλείται η συνάρτηση που απευθύνεται στο πεδίο sa_sigaction. Εάν η σημαία δεν έχει οριστεί, καλείται ο χειριστής sa_handler.
SA_NOCLDWAIT * Εάν το σήμα που καθορίζεται από το sig είναι SIGCHLD, τα παιδιά δεν θα εισέλθουν στην κατάσταση ζόμπι μετά την ολοκλήρωση. Εάν η διαδικασία καλέσει αργότερα συναρτήσεις περίμενε (2), περίμενε 3 (2), περίμενε (2)ή αναμονή (2), η εκτέλεσή τους θα αποκλειστεί έως ότου όλοι οι απόγονοι αυτής της διαδικασίας ολοκληρώσουν το έργο τους.
SA_NOCLDSTOP * Εάν το σήμα που καθορίζεται από το sig είναι SIGCHLD, το καθορισμένο σήμα δεν θα σταλεί στη διεργασία όταν κάποιο από τα παιδιά του τερματίσει ή σταματήσει.

* Αυτές οι σημαίες δεν έχουν οριστεί για UNIX BSD.

Στα συστήματα UNIX BSD 4.x, η δομή sigaction μοιάζει με αυτό:

struct sigaction (

void (*sa_handler)();

sigset_t sa_mask;

όπου η συνάρτηση χειριστή ορίζεται ως εξής:

void handler(int signo, int code, struct sigcontext *scp);

Το σύμβολο του πρώτου ορίσματος περιέχει τον αριθμό σήματος, τον οποίο καθορίζει ο κωδικός Επιπλέον πληροφορίεςσχετικά με την αιτία του σήματος και το scp υποδεικνύει το πλαίσιο της διαδικασίας.

Για το UNIX System V, έχει εφαρμοστεί η ακόλουθη ευκαιρία για να αποκτήσετε περισσότερα πλήρεις πληροφορίεςσχετικά με το σήμα. Εάν έχει οριστεί η σημαία SA_SIGINFO, τότε όταν λαμβάνεται ένα σήμα σήμα, θα κληθεί ο χειριστής που απευθύνεται στο πεδίο sa_sigaction. Εκτός από τον αριθμό σήματος που συνήθως μεταβιβάζεται στον χειριστή σήματος, θα μεταβιβαστεί ένας δείκτης σε μια δομή siginfo_t που περιέχει πληροφορίες σχετικά με το γιατί ελήφθη το σήμα, καθώς και ένας δείκτης σε μια δομή ucontext_t που περιέχει το περιβάλλον της διαδικασίας.

Η δομή siginfo_t ορίζεται στο αρχείο και περιλαμβάνει τα ακόλουθα πεδία:

Το πεδίο si_sign αποθηκεύει τον αριθμό σήματος. Το πεδίο si_code έχει την εξής σημασία: εάν η τιμή του είναι μικρότερη ή ίση με μηδέν, τότε το σήμα στάλθηκε από τη διαδικασία εφαρμογής, οπότε η δομή siginfo_t περιέχει επίσης τα ακόλουθα πεδία:

τα οποία απευθύνονται στη διαδικασία που έστειλε το σήμα. αν η τιμή του si_code είναι μεγαλύτερη από το μηδέν, τότε υποδεικνύει τον λόγο για την αποστολή του σήματος. Λίστα πιθανές τιμέςΟ si_code για ορισμένα σήματα που αντιστοιχούν στο πεδίο si_signo δίνεται στον πίνακα. 2.19

Πίνακας 2.19. Τιμές του πεδίου si_code της δομής siginfo_t για ορισμένα σήματα

τιμή πεδίου si_sign τιμή πεδίου si_code Περιγραφή
ΣΙΓΙΛ Προσπάθεια εκτέλεσης μη έγκυρης εντολής
ILL_ILLOPC Μη έγκυρος κωδικός λειτουργίας
ILL_ILLOPN Μη έγκυρος τελεστής
ILL_ADR Μη έγκυρη λειτουργία διευθυνσιοδότησης
ILL_ILLTRP Μη έγκυρη παγίδα
ILL_PRVOPC Προνομιακός κωδικός λειτουργίας
ILL_PRVREG Προνομιακό μητρώο
ILL_COPROC Σφάλμα συνεπεξεργαστή
ILL_BADSTK Σφάλμα εσωτερικής στοίβας
SIGFPE Ειδική κατάσταση κινητής υποδιαστολής
FPE_INTDIV Διαίρεση ακέραιου με το μηδέν
FPE_INTOVF Υπερχείλιση ακέραιου αριθμού
FPE_FLTDIV Διαίρεση με μηδέν κινητή υποδιαστολή
FPE_FLTOVF Υπερχείλιση κινητής υποδιαστολής
FPE_FLTUND Απώλεια ακρίβειας κινητής υποδιαστολής (υπορροή)
FPE_FLTRES Διφορούμενο αποτέλεσμα λειτουργίας κινητής υποδιαστολής
FPE_FLTINV Μη έγκυρη λειτουργία κινητής υποδιαστολής
FPE_FLTSUB Ευρετήριο εκτός εύρους
SIGSEGV Παραβίαση τμηματοποίησης
SEGV_MAPPER Η διεύθυνση δεν αντιστοιχίζεται στο αντικείμενο
SEGV_ACCERR Ανεπαρκή δικαιώματα στο εμφανιζόμενο αντικείμενο
SIGBUS Αντιμετώπιση σφάλματος
BUS_ADRALN Μη έγκυρη στοίχιση διεύθυνσης
BUS_ADRERR Ανύπαρκτη φυσική διεύθυνση
BUS_OBJERR Σφάλμα υλικού που σχετίζεται με το αντικείμενο
SIGTRAP Παγίδα
TRAP_BRKPT Η διαδικασία έχει φτάσει σε οριακό σημείο
TRAP_TRACE Παγίδα ανίχνευσης διαδικασίας
SIGCHLD Τερματισμός παιδικής διαδικασίας
CLD_EXITED Η θυγατρική διαδικασία έχει ολοκληρωθεί
CLD_KILLED Η διαδικασία του παιδιού σκοτώθηκε
CLD_DUMPED Μη φυσιολογικός τερματισμός της διαδικασίας του παιδιού
CLD_TRAPPED Η ανιχνευόμενη παιδική διαδικασία παγιδεύεται
CLD_STOPPED Η εκτέλεση της θυγατρικής διαδικασίας έχει διακοπεί
CLD_CONTINUED Η εκτέλεση μιας διακοπείσας διαδικασίας παιδιών συνεχίστηκε
SIGPOLL Συμβάν στη συσκευή που ελέγχεται
POLL_IN Τα δεδομένα εισόδου έχουν φτάσει
POLL_OUT Δωρεάν buffer δεδομένων
POLL_MSG Μήνυμα σε αναμονή εισαγωγής
POLL_ERR Σφάλμα εισόδου/εξόδου
POLL_PRI Τα δεδομένα υψηλής προτεραιότητας αναμένουν εισαγωγή
POLL_HUP Η συσκευή είναι απενεργοποιημένη

Έχει ήδη σημειωθεί ότι κατά τη λήψη ενός σήματος από μια διαδικασία χρήστη, η δομή siginfo_t περιέχει πρόσθετα πεδία (Πίνακας 2.20).

Πίνακας 2.20. Πρόσθετα πεδία της δομής siginfo_t

Μπορείτε να ορίσετε μια μάσκα σήματος ή να λάβετε την τρέχουσα μάσκα χρησιμοποιώντας τη λειτουργία sigprocmask(2):

#περιλαμβάνω

int sigprocmask(int how, sigset_t *set, sigset_t *oset);

Η μάσκα σήματος αλλάζει σύμφωνα με το όρισμα how, το οποίο μπορεί να λάβει τις ακόλουθες τιμές:

Εάν ο δείκτης συνόλου είναι NULL, τότε το όρισμα πώς αγνοείται. Εάν το όρισμα oset δεν είναι NULL, τότε η τρέχουσα μάσκα σήματος τοποθετείται στο σύνολο που απευθύνεται από αυτό το όρισμα.

Λειτουργία υπογραφή (2)χρησιμοποιείται για τη λήψη ενός συνόλου μπλοκαρισμένων σημάτων εν αναμονή παράδοσης:

#περιλαμβάνω

int sigpending(int how, sigset_t *set, sigset_t *oset);

Η λίστα των σημάτων που περιμένουν να παραδοθούν επιστρέφεται στο σύνολο που απευθύνεται από το όρισμα set.

Κλήση συστήματος sigsuspend(2)αντικαθιστά την τρέχουσα μάσκα με το σύνολο που απευθύνεται από το όρισμα set και αναστέλλει την εκτέλεση της διεργασίας μέχρι να λάβει σήματα των οποίων η διάταξη έχει ρυθμιστεί είτε να τερματίζει την εκτέλεση της διεργασίας είτε να καλεί μια συνάρτηση χειριστή σήματος.

#περιλαμβάνω

int sigsuspend(const sigset_t *set);

Όταν λαμβάνεται ένα σήμα που τερματίζει τη διαδικασία, η συνάρτηση επιστρέφει sigsuspend(2)δεν συμβαίνει. Εάν η διάταξη του ληφθέντος σήματος έχει ρυθμιστεί να καλεί τη λειτουργία χειριστή, επιστρέψτε από sisuspend(2)εμφανίζεται αμέσως μετά την ολοκλήρωση της επεξεργασίας σήματος. Σε αυτήν την περίπτωση, η μάσκα που υπήρχε πριν από την κλήση αποκαθίσταται sigsuspend(2).

Σημειώστε ότι στο BSD UNIX η κλήση σήμα (3)είναι μια απλοποιημένη διεπαφή για μια γενικότερη λειτουργία sigaction (2), ενώ στον κλάδο System V σήμα (3)συνεπάγεται τη χρήση της παλιάς σημασιολογίας των αναξιόπιστων σημάτων.

Συμπερασματικά, για να επεξηγήσουμε τις παραπάνω σκέψεις, παρουσιάζουμε μια έκδοση της συνάρτησης σήμα(), επιτρέποντας τη χρήση αξιόπιστων σημάτων. Μια παρόμοια υλοποίηση χρησιμοποιείται στο BSD UNIX. Με αυτήν την «στιβαρή» έκδοση, θα επαναλάβουμε το παράδειγμα που συζητήσαμε παραπάνω, σε τροποποιημένη μορφή.

#περιλαμβάνω

#περιλαμβάνω

#περιλαμβάνω

#περιλαμβάνω

#περιλαμβάνω

/* Μια παραλλαγή της συνάρτησης "reliable" signal() */

void (*mysignal(int signo, void (*hndlr)(int)))(int) (

struct sigaction act, oact;

/* Ρύθμιση της μάσκας σήματος */

act.sa_handler = hndlr;

sigemptyset(&act.sa_mask);

act.sa_flags = 0;

if (sign != SIGALRM)

act.sa_flags = SA_RESTART;

/* Ορίστε τη διάταξη */

if (sigaction(sign, &act, &oact)< 0)

return(oact.sa_handler);

/* Λειτουργία χειριστή σήματος */

στατικό κενό sig_hndlr(int signo) (

/* Δεν χρειαζόμαστε πλέον αυτό το μέρος του κώδικα

mysignal(SIGINT, sig_hndlr);

printf("Λήφθηκε σήμα SIGINT");

/* Ορίστε τη διάταξη */

mysignal(SIGINT, sig_hndlr);

mysignal(SIGUSR2, SIG_IGN);

/* Ατελείωτος κύκλος */

Σημειώστε ότι όταν χρησιμοποιείτε αξιόπιστα σήματα, δεν χρειάζεται να επαναφέρετε τη διάταξη στη λειτουργία χειριστή κατά τη λήψη του σήματος.

Από το βιβλίο Αρχιτεκτονική του Λειτουργικού Συστήματος UNIX συγγραφέας Bach Maurice J

7.2 ΣΗΜΑΤΑ Τα σήματα ειδοποιούν τις διεργασίες ότι έχουν συμβεί ασύγχρονα συμβάντα. Τα σήματα αποστέλλονται μέσω διεργασιών - μεταξύ τους, χρησιμοποιώντας τη συνάρτηση kill - ή από τον πυρήνα. Στην έκδοση V (δεύτερη έκδοση) του συστήματος UNIX, υπάρχουν 19 διάφορα σήματα, τα οποία μπορούν να ταξινομηθούν

Από το βιβλίο DIY Linux server συγγραφέας

5.8.2. Σήματα Ο δαίμονας syslogd αποκρίνεται στα ακόλουθα σήματα: SYGTERM, SIGINT, SIGQUIT, SIGHUP, SIGUSR1, SIGCHLD. Η αντίδραση του δαίμονα στα σήματα περιγράφεται στον Πίνακα. 5.8 Αντίδραση δαίμονα σε σήματα Πίνακας 5.8 Αντίδραση σήματος SIGTERM Τερματίζει τον δαίμονα SIGINT, SIGQUIT Τερματίζει τον δαίμονα εάν είναι απενεργοποιημένος ο εντοπισμός σφαλμάτων.

συγγραφέας Raymond Eric Stephen

Από το βιβλίο The Art of Programming for Unix συγγραφέας Raymond Eric Stephen

7.2.6.2. Σήματα Ο απλούστερος και πιο πρόχειρος τρόπος επικοινωνίας μεταξύ δύο διεργασιών στο ίδιο μηχάνημα είναι η μία από αυτές να στείλει στην άλλη κάποιο είδος σήματος. Τα σήματα στο λειτουργικό σύστημα Unix είναι μια μορφή διακοπής λογισμικού. Κάθε σήμα

Από το βιβλίο Υποδομές δημόσια κλειδιά συγγραφέας Polyanskaya Olga Yurievna

Αξιόπιστες πηγές χρόνου Μια ασφαλής υπηρεσία γνωριμιών απαιτεί μία ή περισσότερες αξιόπιστες πηγές χρόνου, δηλαδή έναν τρόπο για να αποκτήσετε μια αξιόπιστη αναπαράσταση της τρέχουσας ώρας (σύγχρονη με την παγκόσμια ώρα, με υψηλό επίπεδοακρίβεια) ένα ή

Από το βιβλίο Ανάπτυξη Εφαρμογών στο περιβάλλον Linux. Δεύτερη έκδοση συγγραφέας Τζόνσον Μάικλ Κ.

12.1.3. Αξιόπιστα σήματα Η υλοποίηση του προβλήματος πολλαπλών σημάτων BSD βασίζεται στην απλή αναμονή για την ολοκλήρωση κάθε χειριστή σήματος σε μια διαδικασία πριν από την παράδοση του επόμενου. Αυτό διασφαλίζει ότι κάθε σήμα θα υποβληθεί σε επεξεργασία αργά ή γρήγορα, και

Από το βιβλίο Linux: The Complete Guide συγγραφέας Kolisnichenko Denis Nikolaevich

3.3.2. Σήματα Ο μηχανισμός σηματοδότησης είναι ένα μέσο που επιτρέπει στις διεργασίες να ειδοποιούνται για ορισμένα συμβάντα στο σύστημα και στη διαδικασία λήψης να ανταποκρίνεται κατάλληλα σε αυτά τα μηνύματα. Το σήμα μπορεί να σταλεί από την ίδια τη διεργασία (για παράδειγμα, όταν προσπαθείτε να διαιρέσετε με το μηδέν) ή από τον πυρήνα (σε περίπτωση αποτυχίας

Από το βιβλίο QNX/UNIX [Anatomy of Concurrency] συγγραφέας Τσιλουρίκ Όλεγκ Ιβάνοβιτς

27.3.10. Σήματα και Υποδοχές Υπάρχουν τρία σήματα που σχετίζονται με τις πρίζες:; SIGIO - η υποδοχή είναι έτοιμη για I/O. Το σήμα αποστέλλεται στη διεργασία που σχετίζεται με την πρίζα; SIGURG - η υποδοχή έλαβε δεδομένα express (δεν θα τα χρησιμοποιήσουμε, επομένως δεν έχει νόημα να σταθούμε σε αυτά); SIGPIPE - δίσκος

Από το βιβλίο Προγραμματισμός για Linux. Επαγγελματική προσέγγιση του Μίτσελ Μαρκ

3. Σήματα

Από το βιβλίο Operating Room Σύστημα UNIX συγγραφέας Ρομπατσέφσκι Αντρέι Μ.

Από το βιβλίο Linux and UNIX: shell programming. Οδηγός προγραμματιστή. από τον Tainsley David

3.3. Σήματα Τα σήματα είναι ο μηχανισμός επικοινωνίας μεταξύ των διεργασιών στο Linux. Αυτό το θέμα είναι πολύ ευρύ, επομένως εδώ θα εξετάσουμε μόνο τα πιο σημαντικά σήματα και τεχνικές ελέγχου διαδικασίας ειδικό μήνυμααποστέλλεται στη διαδικασία. Τα σήματα είναι

Από το βιβλίο Learning Explosion: Nine Rules for an Effective Virtual Classroom του Μέρντοχ Μάθιου

Σήματα Τα σήματα είναι ένας τρόπος μετάδοσης ειδοποίησης από τη μια διεργασία στην άλλη ή από τον πυρήνα του λειτουργικού συστήματος σε μια διεργασία ότι έχει συμβεί ένα συγκεκριμένο συμβάν. Τα σήματα μπορούν να προβληθούν ως απλούστερη μορφήεπικοινωνία μεταξύ διεργασιών. Στο ίδιο

Από το βιβλίο του συγγραφέα

Από το βιβλίο του συγγραφέα

Σήματα Κατά μία έννοια, τα σήματα παρέχουν την απλούστερη μορφή επικοινωνίας μεταξύ διεργασιών, επιτρέποντας σε μια διεργασία ή μια ομάδα διεργασιών να ειδοποιηθεί για την εμφάνιση κάποιου γεγονότος. Έχουμε ήδη εξετάσει τα σήματα από τη σκοπιά του χρήστη και

Από το βιβλίο του συγγραφέα

26.2. Σήματα Ένα σήμα αναφέρεται σε έναν τύπο μηνύματος που αποστέλλεται από ένα σύστημα για να ενημερώσει μια εντολή ή ένα σενάριο ότι έχει συμβεί κάποιο συμβάν. Συνήθως μιλάμε γιασφάλματα μνήμης, προβλήματα πρόσβασης σε πληροφορίες ή

IPC, επικοινωνία μεταξύ διεργασιών ). Στην πραγματικότητα, ένα σήμα είναι μια ασύγχρονη ειδοποίηση σε μια διαδικασία σχετικά με κάποιο συμβάν. Όταν ένα σήμα αποστέλλεται σε μια διεργασία, το λειτουργικό σύστημα διακόπτει την εκτέλεση της διαδικασίας. Εάν μια διεργασία έχει εγκαταστήσει τη δική της χειριστής σήματος, το λειτουργικό σύστημα εκκινεί αυτόν τον χειριστή μεταβιβάζοντάς του πληροφορίες σχετικά με το σήμα. Εάν η διαδικασία δεν έχει εγκαταστήσει ένα πρόγραμμα χειρισμού, εκτελείται ο προεπιλεγμένος χειριστής.

Τα ονόματα των σημάτων "SIG..." είναι αριθμητικές σταθερές (ορισμοί μακροεντολών C) με τιμές που ορίζονται σε αρχείο κεφαλίδαςσήμα.η . Οι αριθμητικές τιμές των σημάτων μπορεί να διαφέρουν από σύστημα σε σύστημα, αν και το κύριο μέρος τους έχει διαφορετικά συστήματατις ίδιες αξίες. Το βοηθητικό πρόγραμμα kill σάς επιτρέπει να καθορίσετε ένα σήμα είτε ως αριθμό είτε ως σύμβολο.

Αποστολή σημάτων

Τα σήματα αποστέλλονται:

  • από το τερματικό πατώντας ειδικά κλειδιάή συνδυασμούς (για παράδειγμα, πατώντας Ctrl-C δημιουργείται SIGINT , Ctrl-\ SIGQUIT και Ctrl-Z SIGTSTP );
  • πυρήνας συστήματος:
    • όταν προκύπτουν εξαιρέσεις υλικού (μη έγκυρες οδηγίες, παραβιάσεις πρόσβασης στη μνήμη, αποτυχίες συστήματος κ.λπ.)
    • λανθασμένες κλήσεις συστήματος.
    • να αναφέρετε συμβάντα εισόδου/εξόδου.
  • μια διεργασία σε μια άλλη (ή στον εαυτό της), χρησιμοποιώντας την κλήση συστήματος kill(), που περιλαμβάνει:

Δεν είναι δυνατή η αποστολή σημάτων σε μια τερματισμένη διαδικασία που βρίσκεται σε κατάσταση ζόμπι.

Επεξεργασία σήματος

Ο προεπιλεγμένος χειριστής για τα περισσότερα σήματα τερματίζει τη διαδικασία. Για να χειριστεί εναλλακτικά όλα τα σήματα εκτός από το SIGKILL και το SIGSTOP, μια διεργασία μπορεί να εκχωρήσει τον δικό της χειριστή ή να αγνοήσει την εμφάνισή τους τροποποιώντας τη μάσκα σήματος. Η μόνη εξαίρεση είναι η διαδικασία με το pid 1 (init), η οποία έχει το δικαίωμα να αγνοήσει ή να επεξεργαστεί οποιαδήποτε σήματα, συμπεριλαμβανομένων των KILL και STOP.

Ασφάλεια

Μια διεργασία (ή χρήστης κελύφους) με ένα αποτελεσματικό UID διαφορετικό από το 0 (το UID υπερχρήστη) μπορεί να στείλει σήματα μόνο σε διεργασίες με το ίδιο UID.

Ταξινόμηση σημάτων

Το POSIX ορίζει 28 σήματα, τα οποία μπορούν να ταξινομηθούν ως εξής:

Ονομα Κώδικας Προεπιλεγμένη ενέργεια Περιγραφή Τύπος
SIGABRT 6 Συμπλήρωση με ένδειξη μνήμης Σήμα που αποστέλλεται με τη συνάρτηση abort(). Ελεγχος
SIGALRM 14 Ολοκλήρωση Σήμα όταν ο χρόνος που καθορίζεται από το alarm() έχει λήξει Γνωστοποίηση
SIGBUS 10 Συμπλήρωση με ένδειξη μνήμης Λανθασμένη πρόσβαση στη φυσική μνήμη Εξαίρεση
SIGCHLD 18 Αγνοήθηκε Η θυγατρική διαδικασία τερματίστηκε ή σταμάτησε Γνωστοποίηση
SIGCONT 25 Συνεχίστε την εκτέλεση Συνεχίστε την εκτέλεση μιας διαδικασίας που είχε σταματήσει προηγουμένως Ελεγχος
ΣΙΓΦΠΕ 8 Συμπλήρωση με ένδειξη μνήμης Λανθασμένη αριθμητική πράξη Εξαίρεση
ΣΙΓΧΟΥΠ 1 Ολοκλήρωση Κλείσιμο τερματικού Γνωστοποίηση
ΣΙΓΙΛ 4 Συμπλήρωση με ένδειξη μνήμης Μη έγκυρη οδηγία επεξεργαστή Εξαίρεση
ΣΗΜΕΙΩΣΗ 2 Ολοκλήρωση Σήμα διακοπής (Ctrl-C) από το τερματικό Ελεγχος
ΣΙΓΚΙΛ 9 Ολοκλήρωση Ολοκλήρωση άνευ όρων Ελεγχος
SIGPIPE 13 Ολοκλήρωση Εγγραφή σε σπασμένη σύνδεση (σωλήνας, πρίζα) Γνωστοποίηση
SIGQUIT 3 Συμπλήρωση με ένδειξη μνήμης Σήμα "Έξοδος" από το τερματικό (Ctrl-\) Ελεγχος
SIGSEGV 11 Συμπλήρωση με ένδειξη μνήμης Μειωμένη ανάκτηση μνήμης Εξαίρεση
SIGSTOP 23 Διακοπή της διαδικασίας Διακοπή μιας διαδικασίας Ελεγχος
SIGTERM 15 Ολοκλήρωση Σήμα τερματισμού (προεπιλεγμένο σήμα για το βοηθητικό πρόγραμμα kill) Ελεγχος
SIGTSTP 20 Διακοπή της διαδικασίας Σήμα διακοπής από το τερματικό (Ctrl-Z). Ελεγχος
SIGTTIN 26 Διακοπή της διαδικασίας Προσπαθήστε να διαβάσετε από το τερματικό με διαδικασία παρασκηνίου Ελεγχος
ΣΙΓΤΤΟΥ 27 Διακοπή της διαδικασίας Μια προσπάθεια εγγραφής στο τερματικό μέσω μιας διαδικασίας παρασκηνίου Ελεγχος
SIGUSR1 16 Ολοκλήρωση Σήμα χρήστη #1 Εθιμο
SIGUSR2 17 Ολοκλήρωση Σήμα χρήστη #2 Εθιμο
SIGPOLL 22 Ολοκλήρωση Το συμβάν παρακολουθείται από δημοσκόπηση() Γνωστοποίηση
ΣΙΓΠΡΟΦ 29 Ολοκλήρωση Ο χρονοδιακόπτης προφίλ έληξε Εντοπισμός σφαλμάτων
ΣΙΓΣΥΣ 12 Συμπλήρωση με ένδειξη μνήμης Λανθασμένη κλήση συστήματος Εξαίρεση
SIGTRAP 5 Συμπλήρωση με ένδειξη μνήμης Παγίδα εντοπισμού ή σημείο διακοπής Εντοπισμός σφαλμάτων
SIGURG 21 Αγνοήθηκε Λήφθηκαν επείγοντα δεδομένα στην πρίζα Γνωστοποίηση
SIGVTALRM 28 Ολοκλήρωση Λήξη του "εικονικού χρονοδιακόπτη" Γνωστοποίηση
SIGXCPU 30 Συμπλήρωση με ένδειξη μνήμης Η διαδικασία έχει υπερβεί το χρονικό όριο της CPU Εξαίρεση
SIGXFSZ 31 Συμπλήρωση με ένδειξη μνήμης Η διαδικασία έχει υπερβεί το επιτρεπόμενο μέγεθος αρχείου Εξαίρεση

Κατά το χειρισμό εξαιρέσεων και σημάτων εντοπισμού σφαλμάτων, μια διεργασία μπορεί να γράψει ένα αρχείο ένδειξης σφαλμάτων μνήμης διεργασίας στον τρέχοντα κατάλογο πριν από την έξοδο. εικόνα πυρήνα), χρησιμοποιώντας το πρόγραμμα εντοπισμού σφαλμάτων μπορεί να ανακατασκευάσει τις συνθήκες υπό τις οποίες προέκυψε αυτή η εξαίρεση. Μερικές φορές (για παράδειγμα, για προγράμματα που εκτελούνται ως υπερχρήστης) δεν δημιουργείται ένδειξη μνήμης για λόγους ασφαλείας.

SA_SIGINFO

Συνήθως, ένας χειριστής σήματος λαμβάνει μόνο ένα όρισμα - τον αριθμό σήματος (αυτό σας επιτρέπει να χρησιμοποιήσετε μια λειτουργία χειριστή για πολλά σήματα). Εάν, κατά τον καθορισμό ενός χειριστή σήματος (χρησιμοποιώντας τη συνάρτηση sigaction()), καθορίσετε την επιλογή SA_SIGINFO, τότε δύο ακόμη ορίσματα θα περάσουν στον χειριστή:

  1. δείκτη σε μια δομή siginfo_t που περιέχει:
    • μια μάσκα πρόσθετων "κωδικών σήματος" που καθορίζουν την αιτία της εμφάνισής του.
    • αναγνωριστικό διεργασίας (PID) που έστειλε το σήμα.
    • το αποτελεσματικό αναγνωριστικό χρήστη (UID) κάτω από το οποίο εκτελείται η διαδικασία (για παράδειγμα, το βοηθητικό πρόγραμμα kill) που έστειλε το σήμα.
    • διεύθυνση της εντολής στην οποία προέκυψε η εξαίρεση·
    • και ούτω καθεξής.
  2. ένας δείκτης στο "περιβάλλον της μηχανής" τη στιγμή που εμφανίστηκε το σήμα (με "στοίβα σήματος" - πρόσθετα δεδομένα που προωθούνται στη στοίβα όταν εγείρονται ορισμένα σήματα εξαίρεσης).

Οι περισσότεροι πρόσθετοι κωδικοί είναι συγκεκριμένοι για κάθε σήμα. Κοινοί κωδικοί για όλα τα σήματα:

δείτε επίσης

Γράψτε μια αξιολόγηση για το άρθρο "Σήματα (UNIX)"

Συνδέσεις

  • - Signal Concept (IEEE Std 1003.1, 2004 Edition)
  • - Περιγραφή δομών και σταθερών που σχετίζονται με σήματα (IEEE Std 1003.1, 2004 Edition)
  • - «Κανόνες για τη χρήση σημάτων στο Unix» (Μήνυμα στη διάσκεψη RU.UNIX.PROG)

Απόσπασμα που περιγράφει σήματα (UNIX)

«Θα σου τραγουδάω όλο το βράδυ», είπε η Νατάσα.
- Η μάγισσα θα μου κάνει τα πάντα! - είπε ο Ντενίσοφ και έλυσε το σπαθί του. Βγήκε από πίσω από τις καρέκλες, πήρε σταθερά την κυρία του από το χέρι, σήκωσε το κεφάλι του και έβαλε το πόδι του κάτω, περιμένοντας τακτ. Μόνο έφιππος και στη μαζούρκα, το κοντό ανάστημα του Ντενίσοφ δεν φαινόταν και φαινόταν να είναι ο ίδιος νέος που ένιωθε ότι ήταν. Αφού περίμενε τον ρυθμό, κοίταξε θριαμβευτικά και παιχνιδιάρικα την κυρία του από το πλάι, χτύπησε ξαφνικά το ένα πόδι του και, σαν μπάλα, αναπήδησε ελαστικά από το πάτωμα και πέταξε μαζί σε κύκλο, σέρνοντας την κυρία του μαζί του. Πέταξε σιωπηλά στα μισά του διαδρόμου με το ένα πόδι, και φαινόταν ότι δεν είδε τις καρέκλες να στέκονται μπροστά του και όρμησε κατευθείαν προς το μέρος τους. αλλά ξαφνικά, χτυπώντας τα σπιρούνια του και απλώνοντας τα πόδια του, σταμάτησε στις φτέρνες του, στάθηκε εκεί για ένα δευτερόλεπτο, με το βρυχηθμό των σπιρουνιών, χτύπησε τα πόδια του σε ένα σημείο, γύρισε γρήγορα και, κάνοντας κλικ στο δεξί του πόδι με το αριστερό του πόδι, πέταξε ξανά σε κύκλο. Η Νατάσα μάντεψε τι σκόπευε να κάνει και, χωρίς να ξέρει πώς, τον ακολούθησε - παραδόθηκε σε αυτόν. Τώρα την έκανε κύκλο, τώρα στο δεξί του, τώρα στο αριστερό του χέρι, τώρα πέφτοντας στα γόνατά του, την έκανε κύκλο γύρω του, και πάλι πήδηξε και έτρεξε μπροστά με τόση ταχύτητα, σαν να είχε σκοπό να τρέξει σε όλα τα δωμάτια χωρίς να πάρεις ανάσα. τότε ξαφνικά σταμάτησε ξανά και ξανά έκανε ένα νέο και απροσδόκητο γόνατο. Όταν εκείνος, περιστρέφοντας βιαστικά την κυρία μπροστά στη θέση της, έσπασε το κέντρισμά του, υποκλινόμενος μπροστά της, η Νατάσα δεν του έβαλε καν το βλέμμα. Τον κοίταξε σαστισμένη, χαμογελώντας σαν να μην τον αναγνώριζε. - Τι είναι αυτό? - είπε.
Παρά το γεγονός ότι ο Γιόγκελ δεν αναγνώρισε αυτή τη μαζούρκα ως πραγματική, όλοι ήταν ευχαριστημένοι με την ικανότητα του Ντενίσοφ, άρχισαν να τον επιλέγουν ασταμάτητα και οι ηλικιωμένοι, χαμογελώντας, άρχισαν να μιλούν για την Πολωνία και τις παλιές καλές μέρες. Ο Ντενίσοφ, κοκκινισμένος από τη μαζούρκα και σκουπιζόμενος με ένα μαντήλι, κάθισε δίπλα στη Νατάσα και δεν έφυγε από το πλευρό της σε όλη τη διάρκεια της μπάλας.

Για δύο ημέρες μετά από αυτό, ο Ροστόφ δεν είδε τον Ντολόχοφ με τους ανθρώπους του και δεν τον βρήκε στο σπίτι. την τρίτη μέρα έλαβε ένα σημείωμα από αυτόν. «Επειδή δεν σκοπεύω πλέον να επισκεφτώ το σπίτι σας για λόγους που γνωρίζετε και πηγαίνω στρατό, σήμερα το απόγευμα κάνω στους φίλους μου ένα αποχαιρετιστήριο πάρτι - ελάτε στο αγγλικό ξενοδοχείο». Ο Ροστόφ στις 10, από το θέατρο, όπου ήταν με την οικογένειά του και τον Ντενίσοφ, έφτασε την καθορισμένη μέρα στο αγγλικό ξενοδοχείο. Αμέσως τον μετέφεραν στο καλύτερο δωμάτιο του ξενοδοχείου, το οποίο είχε καταληφθεί εκείνη τη νύχτα από τον Ντολόχοφ. Περίπου είκοσι άνθρωποι συνωστίστηκαν γύρω από το τραπέζι, μπροστά στο οποίο καθόταν ο Ντολόχοφ ανάμεσα σε δύο κεριά. Υπήρχε χρυσός και χαρτονομίσματα στο τραπέζι και ο Ντολόχοφ πετούσε μια τράπεζα. Μετά την πρόταση και την άρνηση της Σόνιας, ο Νικολάι δεν τον είχε δει ακόμα και μπερδεύτηκε στη σκέψη πώς θα συναντηθούν.
Το λαμπερό, ψυχρό βλέμμα του Ντολόχοφ συνάντησε τον Ροστόφ στην πόρτα, σαν να τον περίμενε πολύ καιρό.
«Πολύ καιρό δεν βλέπω», είπε, «ευχαριστώ που ήρθατε». Μόλις πάω σπίτι και ο Ilyushka θα εμφανιστεί με τη χορωδία.
«Ήρθα να σε δω», είπε ο Ροστόφ κοκκινίζοντας.
Ο Ντολόχοφ δεν του απάντησε. «Μπορείς να στοιχηματίσεις», είπε.
Ο Ροστόφ θυμήθηκε εκείνη τη στιγμή μια παράξενη συζήτηση που είχε κάποτε με τον Ντολόχοφ. «Μόνο οι ανόητοι μπορούν να παίξουν για την τύχη», είπε τότε ο Dolokhov.
– Ή φοβάσαι να παίξεις μαζί μου; - είπε τώρα ο Ντολόχοφ, σαν να είχε μαντέψει τη σκέψη του Ροστόφ, και χαμογέλασε. Λόγω του χαμόγελου του, ο Ροστόφ είδε μέσα του τη διάθεση του πνεύματος που είχε κατά τη διάρκεια του δείπνου στο κλαμπ και γενικά εκείνες τις στιγμές που, σαν να βαριόταν την καθημερινή ζωή, ο Ντολόχοφ ένιωθε την ανάγκη να ξεφύγει από αυτήν με κάτι παράξενο, κυρίως. σκληρός, ενεργώ .
Ο Ροστόφ ένιωσε άβολα. έψαξε και δεν βρήκε ένα αστείο στο μυαλό του που θα ανταποκρινόταν στα λόγια του Dolokhov. Αλλά πριν προλάβει να το κάνει αυτό, ο Ντολόχοφ, κοιτάζοντας κατευθείαν στο πρόσωπο του Ροστόφ, αργά και επίτηδες, ώστε να μπορούν όλοι να ακούσουν, του είπε:
– Θυμάσαι που λέγαμε για το παιχνίδι... ένας ανόητος που θέλει να παίξει για τύχη? Μάλλον θα έπρεπε να παίξω, αλλά θέλω να προσπαθήσω.
«Να προσπαθήσω για τύχη, ή μήπως;» σκέφτηκε ο Ροστόφ.
«Και είναι καλύτερα να μην παίξουμε», πρόσθεσε, και ραγίζοντας το σκισμένο κατάστρωμα, πρόσθεσε: «Τράπεζα, κύριοι!»
Προχωρώντας τα χρήματα προς τα εμπρός, ο Dolokhov ετοιμάστηκε να πετάξει. Η Ροστόφ κάθισε δίπλα του και δεν έπαιξε στην αρχή. Ο Ντολόχοφ του έριξε μια ματιά.
- Γιατί δεν παίζεις; - είπε ο Ντολόχοφ. Και περιέργως, ο Νικολάι ένιωσε την ανάγκη να πάρει μια κάρτα, να της βάλει ένα μικρό τζακ ποτ και να ξεκινήσει το παιχνίδι.
«Δεν έχω χρήματα μαζί μου», είπε ο Ροστόφ.
- Θα το πιστέψω!
Το Ροστόφ πόνταρε 5 ρούβλια στο φύλλο και έχασε, ποντάρισε ξανά και έχασε ξανά. Ο Dolokhov σκότωσε, κέρδισε δηλαδή δέκα κάρτες στη σειρά από το Rostov.
«Κύριοι», είπε, αφού πέρασε λίγο χρόνο, «παρακαλώ βάλτε χρήματα στις κάρτες, διαφορετικά μπορεί να μπερδευτώ στους λογαριασμούς».
Ένας παίκτης είπε ότι ήλπιζε να τον εμπιστευτούν.
– Μπορώ να το πιστέψω, αλλά φοβάμαι μην μπερδευτώ. «Παρακαλώ βάλτε χρήματα στις κάρτες», απάντησε ο Ντολόχοφ. «Μην ντρέπεσαι, θα τα πάμε μαζί σου», πρόσθεσε στο Ροστόφ.
Το παιχνίδι συνεχίστηκε: ο πεζός, χωρίς διακοπή, σέρβιρε σαμπάνια.
Όλα τα χαρτιά του Ροστόφ έσπασαν και γράφτηκαν πάνω του μέχρι και 800 τόνοι ρούβλια. Ήταν έτοιμος να γράψει 800 χιλιάδες ρούβλια σε μια κάρτα, αλλά ενώ του σέρβιραν σαμπάνια, άλλαξε γνώμη και έγραψε ξανά το συνηθισμένο τζακ ποτ, είκοσι ρούβλια.
«Άφησε το», είπε ο Ντολόχοφ, αν και δεν φαινόταν να κοιτάζει το Ροστόφ, «θα το πάρεις ακόμα πιο γρήγορα». Δίνω σε άλλους, αλλά σε κέρδισα. Ή με φοβάσαι; - επανέλαβε.
Ο Ροστόφ υπάκουσε, άφησε το γραμμένο 800 και έβαλε τις επτά καρδιές με μια σχισμένη γωνία, την οποία σήκωσε από το έδαφος. Τη θυμήθηκε καλά μετά. Τοποθέτησε τις επτά καρδιές, γράφοντας 800 από πάνω με ένα σπασμένο κομμάτι κιμωλίας, σε στρογγυλούς, ευθύγραμμους αριθμούς. ήπιε το σερβιρισμένο ποτήρι της ζεσταμένης σαμπάνιας, χαμογέλασε στα λόγια του Ντολόχοφ και με κομμένη την ανάσα, περιμένοντας τους επτά, άρχισε να κοιτάζει τα χέρια του Ντολόχοφ που κρατούσαν το κατάστρωμα. Η νίκη ή η απώλεια αυτής της επτά καρδιών σήμαινε πολλά για τη Ροστόφ. Την Κυριακή την περασμένη εβδομάδα, ο κόμης Ilya Andreich έδωσε στον γιο του 2.000 ρούβλια και αυτός, που ποτέ δεν του άρεσε να μιλάει για οικονομικές δυσκολίες, του είπε ότι αυτά τα χρήματα ήταν τα τελευταία μέχρι τον Μάιο και γι' αυτό ζήτησε από τον γιο του να είναι πιο οικονομικός. αυτή τη φορά. Ο Νικολάι είπε ότι αυτό ήταν πάρα πολύ γι 'αυτόν και ότι έδωσε το λόγο τιμής του να μην πάρει άλλα χρήματα μέχρι την άνοιξη. Τώρα απέμειναν 1.200 ρούβλια από αυτά τα χρήματα. Επομένως, οι επτά καρδιές σήμαιναν όχι μόνο απώλεια 1.600 ρούβλια, αλλά και την ανάγκη αλλαγής αυτή η λέξη. Με βουλιασμένη καρδιά, κοίταξε τα χέρια του Ντολόχοφ και σκέφτηκε: «Λοιπόν, γρήγορα, δώσε μου αυτή την κάρτα και θα πάρω το καπάκι μου, πήγαινε σπίτι για δείπνο με τον Ντενίσοφ, τη Νατάσα και τη Σόνια και σίγουρα δεν θα πάρω ποτέ κάρτα στα χέρια μου». Αυτή τη στιγμή η ζωή στο σπίτιΤα αστεία του με την Πέτια, οι συζητήσεις με τη Σόνια, τα ντουέτα με τη Νατάσα, μια κουβέντα με τον πατέρα του, ακόμη και ένα ήρεμο κρεβάτι στο σπίτι του Μάγειρα, του παρουσιάστηκαν με τόση δύναμη, σαφήνεια και γοητεία, σαν όλα αυτά να ήταν πολύ παλιά, χαμένα και ανεκτίμητη ευτυχία. Δεν μπορούσε να επιτρέψει ότι ένα ηλίθιο ατύχημα, που αναγκάζει τους επτά να ξαπλώσουν πρώτα δεξιά παρά αριστερά, θα μπορούσε να του στερήσει όλη αυτή την πρόσφατα κατανοητή, πρόσφατα φωτισμένη ευτυχία και να τον βυθίσει στην άβυσσο μιας ακόμη άγνωστης και αβέβαιης ατυχίας. Αυτό δεν θα μπορούσε να είναι, αλλά ακόμα περίμενε με κομμένη την ανάσα την κίνηση των χεριών του Dolokhov. Αυτά τα πλατύ κόκαλα, κοκκινωπά χέρια με τις τρίχες που φαίνονται κάτω από το πουκάμισο, άφησαν κάτω μια τράπουλα και έπιασαν το ποτήρι και το σωλήνα που σερβίρονταν.

Σειρά περιεχομένου:

Στα σύγχρονα λειτουργικά συστήματα, υπάρχει η έννοια της επικοινωνίας μεταξύ διεργασιών (IPC) - αυτό είναι ένα σύνολο μεθόδων για την ανταλλαγή δεδομένων μεταξύ διεργασιών ή/και νημάτων. Μία από αυτές τις μεθόδους ανταλλαγής είναι τα σήματα. Η έννοια των σημάτων υποστηρίζεται από τα περισσότερα λειτουργικά συστήματα, αλλά, για παράδειγμα, τα Windows δεν έχουν πλήρη υποστήριξη για τη χρήση τους ως μία από τις μεθόδους IPC - σε τέτοια λειτουργικά συστήματα τα σήματα υλοποιούνται μόνο σε τυπική βιβλιοθήκηγλώσσα Γ.

Έννοια σήματος

Τα σήματα είναι ικανά να διακόπτουν μια διαδικασία σε τυχαίους χρόνους (ασύγχρονα) για την επεξεργασία ενός συμβάντος. Μια διεργασία μπορεί να διακοπεί από ένα σήμα που εκκινείται από μια άλλη διεργασία ή πυρήνα. Ο πυρήνας χρησιμοποιεί σήματα για να ειδοποιεί διεργασίες για διάφορα συμβάντα, όπως ο θάνατος μιας θυγατρικής διεργασίας.

Τα σήματα έχουν συγκεκριμένο κύκλο ζωής. Πρώτον, δημιουργείται το σήμα - αποστέλλεται από τη διεργασία ή δημιουργείται από τον πυρήνα. Στη συνέχεια, το σήμα περιμένει να παραδοθεί στη διαδικασία λήψης. Είναι γενικά αποδεκτό ότι η περίοδος αναμονής για ένα σήμα είναι ίση με το χρονικό διάστημα μεταξύ της δημιουργίας του σήματος και της ενέργειας που στέλνει αυτό το σήμα. Στο τέλος του κύκλου ζωής του σήματος, αναχαιτίζεται (λαμβάνεται) από τη διαδικασία και εκτελούνται ενέργειες που σχετίζονται με το σήμα.

Απλά σήματα και αξιόπιστα σήματα

Υπάρχει μια διαίρεση των σημάτων σε απλά και αξιόπιστα.

Αρχικά, αναπτύχθηκαν και χρησιμοποιήθηκαν απλά (αναξιόπιστα) σήματα. Στην αρχή λειτουργίας τους, μοιάζουν με τον κανονικό μηχανισμό για την επεξεργασία διακοπών υλικού στον επεξεργαστή. Εάν μια διεργασία θέλει να επεξεργαστεί ένα συγκεκριμένο σήμα με έναν ειδικό τρόπο, τότε ενημερώνει τον πυρήνα σχετικά με αυτό καθορίζοντας μια ειδική λειτουργία - έναν χειριστή σήματος. Όταν ένα σήμα παραδίδεται σε μια διεργασία, ο πυρήνας καλεί έναν χειριστή σήματος το συντομότερο δυνατό, διακόπτοντας τη διαδικασία. Όταν ο χειριστής ολοκληρώσει την εκτέλεσή του, η διαδικασία συνεχίζεται από το σημείο που διακόπηκε.

Αντί να γράψετε τη δική σας συνάρτηση χειριστή, μπορείτε απλά να πείτε στον πυρήνα ότι το σήμα προκαλεί την προεπιλεγμένη ενέργεια ή ότι το σήμα απλώς αγνοείται.

Όλη αυτή η ιδέα της εργασίας με σήματα ακούγεται αρκετά καλή μέχρι να φτάσει ένα σήμα σε μια διαδικασία ενώ είναι ήδη απασχολημένο με την επεξεργασία ενός άλλου σήματος. Εδώ προκύπτουν τα προβλήματα - ένας επανειλημμένα καλούμενος χειριστής σήματος μπορεί να καταστρέψει αυτούς τους κοινόχρηστους πόρους ( γενικές δομέςδεδομένα και μεταβλητές) που χρησιμοποιεί. Επιπλέον, εάν φθάσει μεγάλος αριθμός σημάτων, η στοίβα διεργασιών μπορεί να αυξηθεί απεριόριστα, γεγονός που μπορεί να οδηγήσει σε αποτυχίες του προγράμματος.

Στη διαδικασία επίλυσης του προβλήματος αναπτύχθηκαν αξιόπιστα σήματα που τυποποιήθηκαν στο POSIX και χρησιμοποιούνται μέχρι σήμερα. Περαιτέρω στο άρθρο, συζητούνται αξιόπιστα σήματα.

Σήματα και κλήσεις συστήματος

Το σήμα μπορεί να φτάσει στη διεργασία ενώ η διεργασία βρίσκεται μέσα σε κάποια κλήση συστήματος, για παράδειγμα, περιμένοντας την είσοδο για ανάγνωση (). Σε αυτήν την περίπτωση, η ανάπτυξη συμβάντων μπορεί να ακολουθήσει την ακόλουθη διαδρομή: η εφαρμογή δεν προσπαθεί να υποκλέψει το σήμα και διακόπτεται από τον πυρήνα (για παράδειγμα, η άφιξη του σήματος SIGTERM) - τότε το τερματικό παραμένει σε μη τυπικό διαμόρφωση, η οποία μπορεί να περιπλέξει την εργασία του χρήστη. Φυσικά, μπορείτε να υποκλέψετε το σήμα, να διαγράψετε το τερματικό στον χειριστή σήματος και μετά να βγείτε, αλλά είναι αρκετά δύσκολο να γράψετε έναν χειριστή σήματος που να γνωρίζει τι έκανε το πρόγραμμα τη στιγμή της διακοπής, προκειμένου να αποφασίσει εάν θα καθαρίστε το τερματικό ή όχι.

Σήμερα υπάρχει μια εφαρμογή σημάτων που είναι απαλλαγμένη από αυτές τις ελλείψεις. Η λύση είναι απλώς να ορίσετε μια σημαία στον χειριστή σήματος για να υποδείξετε ότι το σήμα έχει ληφθεί και, στη συνέχεια, να διασφαλίσετε ότι η κλήση συστήματος επιστρέφει με έναν κωδικό σφάλματος που υποδεικνύει ότι η κλήση διακόπηκε από το σήμα. Στη συνέχεια, το πρόγραμμα πρέπει να ελέγξει τη σημαία που έχει οριστεί από τον χειριστή σήματος και να προβεί στις κατάλληλες ενέργειες, όπως εκκαθάριση του τερματικού και έξοδος.

Οι σύγχρονες υλοποιήσεις σήματος προκαλούν αργές κλήσεις συστήματος για να επιστρέψουν τον κωδικό σφάλματος EINTR όταν διακόπτονται από ένα εισερχόμενο σήμα. Οι γρήγορες κλήσεις συστήματος πρέπει να ολοκληρωθούν πριν από την παράδοση του σήματος. Μια αργή κλήση συστήματος είναι μια κλήση συστήματος που χρειάζεται απροσδιόριστο χρόνο για να ολοκληρωθεί, όπως read(), wait(), write(). Όλες οι κλήσεις συστήματος που εξαρτώνται από απρόβλεπτους πόρους, όπως ανθρώπινες ενέργειες, δεδομένα δικτύου κ.λπ., είναι αργές. Φυσικά, όλες οι άλλες κλήσεις συστήματος είναι γρήγορες.

Συνήθως το πρόγραμμα χειρίζεται τον κωδικό σφάλματος EINTR και, εάν δεν έχει συμβεί κάτι μοιραίο, επανεκκινεί την κλήση συστήματος. Τα περισσότερα λειτουργικά συστήματα που μοιάζουν με Unix το κάνουν τώρα από προεπιλογή - απλά χρειάζεται να χειριστείτε το σήμα σε έναν χειριστή και η κλήση συστήματος θα επανεκκινηθεί αυτόματα. Στο Linux, οι κλήσεις συστήματος δεν επανεκκινούνται από προεπιλογή, αλλά για κάθε σήμα μια διεργασία μπορεί να ορίσει μια σημαία για να πει στο σύστημα να επανεκκινήσει αργές κλήσεις συστήματος που διακόπτονται από αυτό το σήμα.

Αποστολή σημάτων

Η αποστολή σημάτων από τη μια διεργασία στην άλλη γίνεται συνήθως χρησιμοποιώντας την κλήση συστήματος kill(). Η πρώτη του παράμετρος είναι το PID της διαδικασίας στην οποία αποστέλλεται το σήμα. η δεύτερη παράμετρος είναι ο αριθμός σήματος. Εάν θέλουμε να στείλουμε ένα σήμα SIGTERM σε μια διεργασία με PID 6666, χρησιμοποιούμε την κλήση συστήματος kill() ως εξής:

kill(6666, SIGTERM);

Αντί για μια θετική τιμή PID, μπορείτε να περάσετε την κλήση μια ίση αλλά αρνητική τιμή. Στη συνέχεια, το σήμα θα σταλεί σε όλες τις διεργασίες από την ομάδα με αριθμό ίσο με το συντελεστή PID που πέρασε χρησιμοποιούνται κυρίως από κοχύλια για τη διαχείριση εργασιών.

Εάν περάσετε την τιμή -1 ως PID στην κλήση συστήματος kill(), το σήμα θα σταλεί σε όλες τις διεργασίες εκτός από την init Αυτή η δυνατότητα χρησιμοποιείται για τον τερματισμό του συστήματος.

Για περισσότερες πληροφορίες σχετικά με την κλήση συστήματος kill(), δείτε το man 2 kill.

Μια διεργασία μπορεί να στείλει ένα σήμα στον εαυτό της χρησιμοποιώντας την κλήση συστήματος raise(), η οποία λαμβάνει μία παράμετρο - τον αριθμό σήματος. Παράδειγμα:

αύξηση (SIGTERM);

Φυσικά, κάθε μία από τις κλήσεις συστήματος που συζητήθηκαν παραπάνω επιστρέφει μηδέν εάν είναι επιτυχής και μη μηδενική τιμή εάν παρουσιαστεί κάποιο σφάλμα.

Υποκλοπή σήματος

Όλα τα προγράμματα POSIX καταχωρούν τους χειριστές σήματος τους χρησιμοποιώντας την κλήση συστήματος sigaction(). Αυτή η κλήση συστήματος έχει τρεις παραμέτρους: την πρώτη – int signum – τον ​​αριθμό του σήματος που έχει υποκλαπεί. Το δεύτερο είναι το struct sigaction * act – ένας δείκτης σε μια δομή που περιγράφει τους κανόνες για την εγκατάσταση του χειριστή. Η τρίτη παράμετρος – struct sigaction * oact – παίρνει ήδη καθιερωμένους κανόνεςχειριστής σήματος. Είτε η δεύτερη είτε η τρίτη (αλλά όχι και οι δύο!) παράμετρος μπορεί να οριστεί σε NULL εάν είναι απαραίτητο.

Η δομή struct sigaction έχει την ακόλουθη περιγραφή:

struct sigaction ( __sighandler_t sa_handler; sigset_t sa_mask; int sa_flags; );

Το sa_handler είναι ένας δείκτης στον χειριστή σήματος και ο χειριστής πρέπει να δηλωθεί ως εξής:

void signal_handler(int signo);

όπου η μόνη παράμετρος είναι ο αριθμός του σήματος που συμπεριλήφθηκε στον χειριστή. Το sa_handler μπορεί επίσης να είναι ίσο με SIG_IGN - το σήμα αγνοείται από τη διαδικασία και SIG_DFL - το σήμα προκαλεί μια προεπιλεγμένη ενέργεια, όπως η διακοπή της διαδικασίας.

sa_mask – ένα σύνολο σημάτων που θα πρέπει να αποκλειστούν όταν καλείται ο χειριστής σήματος που καθορίζεται στην ίδια δομή. Ο τρόπος εγκατάστασης τους περιγράφεται παρακάτω.

Η παράμετρος sa_flags επιτρέπει σε μια διεργασία να τροποποιήσει τη συμπεριφορά του σήματος. Η παράμετρος μπορεί να λάβει μόνο τέσσερις τιμές, οι οποίες, ωστόσο, μπορούν να συνδυαστούν χρησιμοποιώντας τη λειτουργία bit "OR":

  1. SA_NOCLDSTOP – Στείλτε το σήμα SIGCHLD μόνο εάν διακοπεί η θυγατρική διαδικασία. Η αναστολή μιας θυγατρικής διαδικασίας δεν προκαλεί την αποστολή σήματος.
  2. SA_NODEFER – εξομοίωση απλών (αναξιόπιστων) σημάτων.
  3. SA_RESTHAND – μετά την άφιξη ενός σήματος, ο χειριστής του επαναφέρεται σε SIG_DFL.
  4. SA_RESTART – επανεκκινήστε την κλήση συστήματος μετά την επιστροφή από το πρόγραμμα χειρισμού σήματος. Εάν η σημαία δεν έχει οριστεί, η κλήση συστήματος επιστρέφει το σφάλμα EINTR.

Ως συνήθως, η sigaction() επιστρέφει 0 στην επιτυχία και αρνητική τιμή στο σφάλμα.

Μάσκα σήματος διαδικασίας

Προσθήκη σημάτων στη δομή sigset_t sa_mask, εκκαθάριση κ.λπ. εκτελούνται χρησιμοποιώντας ένα σύνολο συναρτήσεων sigemptyset(), sigfillset(), sigaddset(), sigdelset(). Οι δύο πρώτες συναρτήσεις λαμβάνουν μία παράμετρο - έναν δείκτη στη δομή sigset_t. Αυτές οι συναρτήσεις διαγράφουν και γεμίζουν τη δομή sigset_t με όλα τα πιθανά σήματα, αντίστοιχα.

Οι δύο τελευταίες συναρτήσεις, αντίστοιχα, προσθέτουν και αφαιρούν ένα συγκεκριμένο σήμα από τη δομή και έχουν δύο παραμέτρους η καθεμία. Η πρώτη τους παράμετρος είναι ένας δείκτης στη δομή sigset_t και η δεύτερη είναι ο αριθμός σήματος.

Όλες οι συναρτήσεις που συζητήθηκαν παραπάνω επιστρέφουν 0 στην επιτυχία και έναν μη μηδενικό αριθμό στο σφάλμα.

Επιπλέον, υπάρχει μια άλλη συνάρτηση που ελέγχει εάν το καθορισμένο σήμα βρίσκεται στο καθορισμένο σύνολο - sigismember(). Οι παράμετροί του είναι ίδιες με αυτές της sigaddset(). Η συνάρτηση επιστρέφει 1 εάν το σήμα είναι στο σετ, 0 αν δεν είναι και αρνητικό αριθμό εάν παρουσιάστηκε σφάλμα.

Μεταξύ άλλων, μπορούμε να καθορίσουμε μια λίστα σημάτων των οποίων η παράδοση στη διαδικασία θα αποκλειστεί. Αυτό γίνεται χρησιμοποιώντας τη συνάρτηση sigprocmask(int how, const sigset_t * set, sigset_t * oldset).

Η πρώτη του παράμετρος περιγράφει τι πρέπει να εκτελεστεί:

  1. SIG_BLOCK – τα σήματα από το σετ είναι μπλοκαρισμένα.
  2. SIG_UNBLOCK – τα σήματα από το σετ ξεμπλοκάρονται.
  3. SIG_SETMASK – τα σήματα από το σετ μπλοκάρονται, τα υπόλοιπα ξεμπλοκάρονται.

Η δεύτερη παράμετρος είναι ένας δείκτης στο ίδιο το σύνολο από το οποίο τα σήματα μπλοκάρονται/αποκλείονται. Εάν είναι NULL, τότε η τιμή της πρώτης παραμέτρου αγνοείται από την κλήση συστήματος.

Η τρίτη παράμετρος είναι ένας δείκτης σε μια ήδη χρησιμοποιημένη μάσκα σήματος. μπορεί να οριστεί σε NULL εάν αυτά τα δεδομένα δεν χρειάζονται.

Για να αποκτήσετε μια λίστα σημάτων σε εκκρεμότητα, μπορείτε να χρησιμοποιήσετε τη συνάρτηση sigpending(), η οποία παίρνει μια παράμετρο - έναν δείκτη στη δομή sigset_t, όπου θα γραφτεί το σύνολο των σημάτων σε εκκρεμότητα.

Αρχές γραφής χειριστών σήματος

Ένας από τους πιο σημαντικούς κανόνες για τη σύνταξη χειριστών σήματος είναι ότι ο χειριστής πρέπει να επανεισέρχεται, δηλ. πρέπει να επιτρέπει στον εαυτό του να κληθεί ξανά όταν η διεργασία βρίσκεται ήδη στον χειριστή. Πρέπει να ληφθεί μέριμνα ώστε ο χειριστής σήματος να μην χρησιμοποιεί παγκόσμιες δομέςδεδομένων ή αργές κλήσεις συστήματος. Εάν, δυστυχώς, είναι αδύνατο να αποφευχθεί αυτό, τότε θα πρέπει να φροντίσετε να προστατεύσετε από επαναλαμβανόμενες κλήσεις του χειριστή ενώ εργάζεστε με μια δομή δεδομένων ή με μια κλήση συστήματος. Αυτό μπορεί να επιτευχθεί μπλοκάροντας προσωρινά την παράδοση του σήματος του οποίου ο χειριστής εκτελείται αυτήν τη στιγμή χρησιμοποιώντας την κλήση συστήματος sigprocmask(). Για παράδειγμα, έχουμε έναν χειριστή σήματος SIGCHLD και τον αποκλείουμε ως εξής:

void chld_handler(int signum) ( sigset_t set; if (sigemptyset(&set)) ( return;) if (sigaddset(&set, SIGCHLD)) ( return; ) if (sigprocmask(SIG_BLOCK, &set, NULL)) ( return; ) / * κάνοντας κάτι σημαντικό εδώ */ if (sigprocmask(SIG_UNBLOCK, &set, NULL)) ( return; ) return;

Εκτός από όλα όσα αναφέρονται παραπάνω, πιστεύεται ότι ο χειριστής πρέπει να είναι όσο το δυνατόν πιο απλός - ιδανικά, θα πρέπει να ορίσει μια συγκεκριμένη σημαία και να τερματίσει, και τα υπόλοιπα θα πρέπει να εκτελούνται από το κύριο μέρος του προγράμματος.

συμπέρασμα

Το υλικό που παρέχεται είναι βασικό για την κατανόηση της έννοιας των σημάτων. Κατ 'αρχήν, θα πρέπει να είναι αρκετό για να αρχίσετε να χρησιμοποιείτε σήματα στα προγράμματά σας.

Η σειρά θα ολοκληρωθεί με μια ματιά στον τρόπο λήψης (και αποστολής) πρόσθετων δεδομένων σήματος εάν δεν έχετε αρκετά συνηθισμένες πληροφορίεςότι ένα σήμα μπήκε στη διαδικασία σας από κάπου.

Πόροι για λήψη

static.content.url=http://www.site/developerworks/js/artrating/

ID άρθρου=495997

ArticleTitle=Εργασία με σήματα στο Linux: Μέρος 1. Βασικά στοιχεία της εργασίας με σήματα