Μάθε παιδί μου Linux (μέρος 9) | Διεργασίες συστήματος
Στο προηγούμενο άρθρο όπου μιλήσαμε για
τις άδειες των αρχείων και των εφαρμογών, "αγγίξαμε" λίγο και τις διεργασίες συστήματος. Οι διεργασίες είναι στην
ουσία τα προγράμματα που τρέχουν στον υπολογιστή μας και για αυτές θα
μιλήσουμε σήμερα. Θα δούμε κυρίως πού θα τις βρούμε, πώς μπορούμε να τις
ξεχωρίσουμε, τι πληροφορίες μας δίνουν και πώς μπορούμε να τις "σκοτώσουμε" αν
κάτι πάει στραβά.
Τι είναι οι διεργασίες συστήματος και πώς τις ξεχωρίζουμε
Κάθε φορά που ανοίγουμε μία εφαρμογή στον υπολογιστή μας, ξεκινούν διάφορες
διεργασίες για να την εμφανίσουν στην οθόνη μας. Υπεύθυνος για τις διεργασίες
αυτές είναι ο Linux πυρήνας (kernel), ο οποίος φορτώνει τον κώδικά τους στη
μνήμη και τους δίνει ένα μέρος του επεξεργαστή για να εκτελεστούν. Μόλις
κλείσουμε την εφαρμογή, ο Linux πυρήνας τερματίζει τις διεργασίες της και
απελευθερώνει τη μνήμη και το ποσοστό του επεξεργαστή που καταλάμβαναν.
Όπως ο κάθε χρήστης και η κάθε ομάδα έχουν ένα μοναδικό αναγνωριστικό (UID και
GID αντίστοιχα), έτσι και οι διεργασίες έχουν το δικό τους με τη μορφή του PID
(εκ του "Process ID"). Για να δούμε τις διεργασίες μας με τα PID τους στο
τερματικό, θα δώσουμε την εντολή:
ps aux
Η απάντηση του τερματικού θα μοιάζει κάπως έτσι:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMANDroot 1 0.0 0.0 8936 312 ? Ssl 11:27 0:00 /initroot 6 0.0 0.0 8936 220 tty1 Ss 11:27 0:00 /initchris 7 0.0 0.0 16784 3440 tty1 S 11:27 0:00 -bashchris 34 0.0 0.0 17384 1932 tty1 R 11:34 0:00 ps auxchris 935 0.0 0.0 0 0 tty1 Z 11:35 0:00 something
Στις στήλες πληροφοριών που μας δίνει το τερματικό βλέπουμε μεταξύ άλλων:
- το USER που είναι ο χρήστης με την άδεια του οποίου τρέχει η διεργασία
- το PID που αποτελεί τον μοναδικό αριθμό αναγνώρισης της διεργασίας
- το TTY που είναι το τερματικό στο οποίο τρέχει η διεργασία
- το STAT που είναι ο κωδικός κατάστασης της διεργασίας
- το START που μας λέει τη διάρκεια εκτέλεσης της διεργασίας
- το TIME που δείχνει το χρονικό διάστημα κατά το οποίο η διεργασία απασχόλησε τον επεξεργαστή και
- το COMMAND που είναι το όνομα του εκτελέσιμου αρχείου ή της εντολής του
Αυτό που λαμβάνουμε με την παραπάνω εντολή είναι μία στατική λίστα των
διεργασιών που έτρεχαν στη σύστημα τη στιγμή που τη δώσαμε στο τερματικό. Για
να δούμε τι συμβαίνει ζωντανά στο σύστημά μας, θα δώσουμε την εντολή:
top
Τέλος αξίζει να πούμε ότι στο Linux οι διεργασίες αποθηκεύονται προσωρινά και
σε αρχεία! Αυτά περιλαμβάνονται στο φάκελο "/proc" (εκ του "processes") όπως
είδαμε στο άρθρο για το σύστημα αρχείων και φακέλων και χωρίζονται σε
υποφακέλους ανάλογα με το PID τους.
Οι γονείς, τα παιδιά και ο Θεός των διεργασιών!
Εκτός από το PID πολλές διεργασίες έχουν και τον αριθμό PPID (εκ του "Parent
Process ID"). Αυτός ο αριθμός μας δείχνει από που προέρχεται η κάθε διεργασία
ή για να το πούμε με ελεύθερη μετάφραση ποιος είναι ο "γονέας" της. Για να το
καταλάβουμε στην πράξη ας δούμε ξανά τις διεργασίες μας με την εντολή:
ps l
Το τερματικό θα μας επιστρέψει κάτι τέτοιο:
F UID PID PPID PRI NI VSZ RSS WCHAN STAT TTY TIME COMMAND0 1001 7 6 20 0 16792 3452 - S tty1 0:00 bash0 1001 32 7 20 0 17088 1728 - R tty1 0:00 ps l
Εδώ βλέπουμε ότι στο σύστημά μας τρέχει η διεργασία με PID 7, η οποία
χρησιμοποιεί την εντολή "bash". Η διεργασία αυτή είναι το τερματικό που έχουμε
ανοιχτό στον υπολογιστή μας. Η δεύτερη διεργασία με PID 32 είναι η εντολή "ps
l" που μόλις τρέξαμε. Το PPID της δεύτερης διεργασίας είναι ίδιο με το PID της
πρώτης, πράγμα που σημαίνει ότι είναι η πρώτη είναι ο "γονέας" και η δεύτερη
το "παιδί". Στην ουσία δηλαδή έτσι μπορούμε να καταλάβουμε ποιες εντολές
τρέχουν σε ποια τερματικά ή με ποιες εφαρμογές συγγενεύουν γενικότερα.
Η πρώτη διεργασία έχει PPID 6, άρα προέρχεται από μία άλλη διεργασία που έχει
αριθμό PID 6, σωστά; Πολύ σωστά! Την είδαμε πριν όταν δώσαμε την εντολή "ps
aux". Η διεργασία αυτή τρέχει την εντολή "init" στο σύστημά μας και είναι
υπεύθυνη για τη δημιουργία όλων των άλλων διεργασιών του συστήματος. Είναι
δηλαδή ο "Θεός" όλων των διεργασιών!
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMANDroot 6 0.0 0.0 8936 220 tty1 Ss 11:27 0:00 /init
"Ορφανές" διεργασίες και "ζόμπι"
Τώρα που μάθαμε οτι οι διεργασίες συγγενεύουν και ότι μεταξύ τους υπάρχει και
ένας "Θεός", αξίζει να πούμε επιγραμματικά και σε απλή γλώσσα τι συμβαίνει
όταν "πεθαίνουν". Όταν λοιπόν ένα "παιδί" τερματίζεται, ενημερώνει τον "γονέα"
του για να δώσει τη συγκατάθεσή του. Ο "γονέας" τσεκάρει το λόγο διακοπής και
δίνει το ΟΚ για να τερματιστεί.
Αν ο "γονέας" έχει "πεθάνει" νωρίτερα από το "παιδί", η διεργασία γίνεται
πλέον "ορφανή" και την εντολή τερματισμού της την αναλαμβάνει ο "Θεός" (init).
Υπάρχει επίσης και η περίπτωση ένα "παιδί" να τερματιστεί χωρίς να περιμένει
τη συγκατάθεση του "γονέα". Σε αυτό το σενάριο ο Linux πυρήνας μετατρέπει τη
διεργασία σε "ζόμπι" και μας την παρουσιάζει στη λίστα διεργασιών με σκοπό να
ελέγξουμε τι πήγε στραβά. Τις "ζόμπι" διεργασίες τις αναλαμβάνει επίσης ο
"Θεός" ο οποίος τις κλείνει με παρόμοιο τρόπο.
H κατάσταση των διεργασιών εμφανίζεται στη στήλη "STAT" όπου μεταξύ άλλων θα
δούμε:
- το "R" που σημαίνει οτι η διεργασία εκτελείται κανονικά,
- το "S" που σημαίνει οτι βρίσκεται σε κατάσταση αναμονής,
- το "Z" που σημαίνει ότι είναι σε κατάσταση "ζόμπι",
- το "D" που σημαίνει οτι κλείνει μόνο με επανεκκίνηση του συστήματος και
- το "T" που σημαίνει ότι έχει σταματήσει.
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMANDroot 1 0.0 0.0 8936 312 ? Ssl 11:27 0:00 /initroot 6 0.0 0.0 8936 220 tty1 Ss 11:27 0:00 /initchris 7 0.0 0.0 16784 3440 tty1 S 11:27 0:00 -bashchris 34 0.0 0.0 17384 1932 tty1 R 11:34 0:00 ps auxchris 935 0.0 0.0 0 0 tty1 Z 11:35 0:00 something
Διεργασίες και τερματικό
Οι διεργασίες εκτός από το χρήστη είναι "δεμένες" και με ένα συγκεκριμένο
τερματικό. Αν για παράδειγμα εκτελέσουμε την εντολή "wget" για να κατεβάσουμε
ένα αρχείο από το ίντερνετ και κλείσουμε το τερματικό πριν ολοκληρωθεί, η
διεργασία θα διακοπεί μαζί του.
Στο παράδειγμά μας παραπάνω είδαμε τη στήλη "TTY" η οποία μας ενημερώνει σε
ποιο τερματικό τρέχει η κάθε διεργασία. Όσες γράφουν "TTY1" τρέχουν στο πρώτο
τερματικό του συστήματος στο οποίο μπορούμε να μπούμε πατώντας Ctrl+Alt+F1.
Υπάρχουν άλλα πέντε τερματικά στα οποία μπαίνουμε με τα αντίστοιχα "F"
πλήκτρα, (από Ctrl+Alt+F1 έως Ctrl+Alt+F6) ενώ για να επανέλθουμε στο γραφικό
περιβάλλον θα πατήσουμε Ctrl+Alt+F7. Αυτά τα έξι λέγονται και "κανονικά"
τερματικά (regular terminals), ενώ αυτά που χρησιμοποιούμε ανοίγοντας την
εφαρμογή "Τερματικό" στον υπολογιστή μας λέγονται "ψευδοτερματικά"
(pseudoterminals).
Διαφήμιση
Τερματισμός διεργασιών με σήματα (signals)
Τώρα που μάθαμε όλα τα βασικά για τις διεργασίες μας, ήρθε η ώρα να περάσουμε
στην πράξη και να δούμε πώς θα τις τερματίσουμε. Αυτό γίνεται με σήματα
(signals) και ένα από τα πιο γνωστά εκτελείται με τα πλήκτρα Ctrl+C. Δώσαμε
για παράδειγμα πριν την εντολή "top" για να δούμε τη λίστα των διεργασιών μας.
Για να τερματίσουμε λοιπόν τη διεργασία "top" πατάμε Ctrl+C στο πληκτρολόγιο.
Μπορούμε να δούμε μία λίστα με όλα τα διαθέσιμα σήματα δίνοντας την εντολή:
trap -l
Σημείωση:
Η αρίθμηση που βλέπουμε δεν είναι τυχαία και μπορούμε να χρησιμοποιήσουμε το
νούμερο στην εντολή διακοπής που θα δώσουμε, έναντι του ονόματος του σήματος.
Για παράδειγμα το "SIGKILL" που θα δούμε παρακάτω, μπορούμε να το καλέσουμε με
τον αριθμό εννιά ("9").
Για τον τερματισμό των διεργασιών μας τα πιο συνηθισμένα είναι τα εξής:
- SIGHUP ή 1 (εκ του "Signal Hangup"). Λέγαμε πριν οτι οι διεργασίες είναι "δεμένες" με συγκεκριμένα τερματικά σωστά; Όταν κλείνουμε λοιπόν το τερματικό, η διεργασία που εξαρτάται από αυτό, λαμβάνει στην ουσία το σήμα SIGHUP για να κλείσει.
- SIGINT ή 2 (εκ του "Signal Interrupt"). Το συγκεκριμένο σήμα είναι αυτό που δίνουμε πατώντας Ctrl+C στο πληκτρολόγιο για να κλείσουμε τη διεργασία που θέλουμε. Το είδαμε πριν με την εντολή "top".
- SIGSTOP ή 19 (εκ του "Signal Stop"). Με το "SIGSTOP" μπορούμε να σταματήσουμε μια διεργασία και να τη βάλουμε σε κατάσταση "sleep". Ενεργοποιείται πατώντας Ctrl+Z για οποιαδήποτε διεργασία. Για παράδειγμα αν δώσουμε την εντολή "top" και τη σταματήσουμε με Ctrl+Z, όταν ξαναδώσουμε "top" θα δούμε ότι υπάρχει ήδη στο σύστημά μας αλλά σταματημένο.
- SIGTERM ή 15 (εκ του "Signal Terminate"). Αυτό είναι το σήμα που κλείνει τα προγράμματά μας όταν πατάμε το "X" στη γωνία του παραθύρου τους ή όταν απενεργοποιούμε τον υπολογιστή μας. Το συγκεκριμένο σήμα επιτρέπει στις διεργασίες να "καθαρίσουν" τα σκουπίδια τους από τη μνήμη πριν κλείσουν.
- SIGKILL ή 9 (εκ του "Signal Kill"). Αν κάτι δεν πάει καλά με το "SIGTERM", τότε στέλνεται το σήμα "SIGKILL" για να κλείσει βίαια την εφαρμογή μας. Αυτό είναι πιθανότατα και το σήμα που θα χρησιμοποιήσουμε όταν κάτι πάει στραβά στο σύστημά μας και θέλουμε να διορθώσουμε το πρόβλημα.
Ας πούμε λοιπόν οτι θέλουμε να κλείσουμε τη διεργασία με PID 935 η οποία είναι
"ζόμπι". Μπορούμε να δώσουμε απλά την εντολή:
kill 935
Από προεπιλογή το σύστημά μας θα στείλει το σήμα "SIGTERM" για να τερματίσει
με σωστό τρόπο τη διεργασία μας. Αν όμως η διεργασία δεν αντιδράει καλά στα... "λογικά
επιχειρήματά μας", μπορούμε να δώσουμε το "SIGKILL" για να τη "σκοτώσουμε",
χρησιμοποιώντας τον αριθμό του ως εξής:
kill -9 935
Διεργασίες στο παρασκήνιο του τερματικού (Job control)
Είναι γνωστό ότι αν τρέξεις μια εντολή στο τερματικό, πρέπει να περιμένεις να
τελειώσει για να τρέξεις την επόμενη. Για να προσπεράσεις αυτό το πρόβλημα
μπορείς να ανοίξεις ένα δεύτερο τερματικό και να συνεχίσεις τη δουλειά σου από
εκεί, αλλά αυτό δεν είναι πάντα εφικτό. Το τερματικό λοιπόν μας δίνει τη
δυνατότητα να στείλουμε κάποιες διεργασίες στο παρασκήνιο με τη διαδικασία που
λέγεται "job control".
Για να στείλουμε για παράδειγμα στο παρασκήνιο τις διεργασίες με PID 938, 564
και 872, θα δώσουμε τις εντολές:
sleep 938 &sleep 564 &sleep 872 &
Μπορούμε να δούμε τις διεργασίες που τρέχουν στο παρασκήνιο του τερματικού με
την εντολή:
jobs
Το τερματικό θα μας απαντήσει κάτι τέτοιο:
[1] Running sleep 938 &[2]- Running sleep 564 &[3]+ Running sleep 872 &
Αυτό που βλέπουμε είναι το Job ID και σε ποια κατάσταση βρίσκονται ("running"), ενώ το "+"
σημαίνει ότι αυτή είναι η τελευταία διεργασία που στείλαμε στο παρασκήνιο και
το "-" οτι αυτή είναι η προτελευταία.
Αν θέλουμε να τερματίσουμε μία από τις διεργασίες που βρίσκονται στο
παρασκήνιο θα δώσουμε την εντολή "kill" και το Job ID της (π.χ. [2]) ως εξής:
kill %2
Ένα πολύ χρήσιμο παράδειγμα
Θα κλείσουμε τέλος με ένα ωραίο παράδειγμα χρήσης του παρασκηνίου, το οποίο
είναι ιδιαίτερα χρήσιμο στην καθημερινότητα. Ας πούμε οτι θέλουμε να κάνουμε
μία εργασία που θα διαρκέσει πολλή ώρα, όπως να κατεβάσουμε ένα αρχείο με το
"wget":
wget https://us.download.nvidia.com/XFree86/Linux-x86_64/450.80.02/NVIDIA-Linux-x86_64-450.80.02.run
Για να βάλουμε τη διεργασία αυτή στο παρασκήνιο και να ελευθερώσουμε το
τερματικό, θα τη σταματήσουμε προσωρινά πατώντας Ctrl+Z και θα δώσουμε την
εντολή:
bg
Αν δώσουμε τώρα την εντολή "jobs" θα δούμε οτι το αρχείο μας συνεχίζει να
κατεβαίνει στο παρασκήνιο, ενώ το τερματικό είναι ελεύθερο για να συνεχίσουμε
να το χρησιμοποιούμε.
Για να φέρουμε ξανά τη διεργασία αυτή στο προσκήνιο θα δώσουμε την εντολή "fg"
σε συνδυασμό με το Job ID της (π.χ. [3]) ως εξής:
fg %3
Τέλος για να "σκοτώσουμε" οποιαδήποτε εργασία βρίσκεται στο παρασκήνιο, θα
χρησιμοποιήσουμε το "kill" και το Job ID της (π.χ. [3]) ως εξής:
kill %3
Σημείωση:
Για να τα θυμόμαστε ευκολότερα το "bg" προέρχεται από τη λέξη "background",
ενώ το "fg" από το "foreground".
Εν κατακλείδι
Αυτά είναι λοιπόν τα βασικά για τις διεργασίες του Linux συστήματος. Από όλα
όσα μάθαμε κρατάμε κυρίως:
- την εντολή "top" με την οποία μπορούμε να δούμε με μια ματιά τι τρέχει στον υπολογιστή μας,
- τον αριθμό PID με τον οποίο μπορούμε να ξεχωρίσουμε τις διεργασίες,
- την εντολή "kill" με την οποία μπορούμε να διακόψουμε βίαια οποιαδήποτε διεργασία και
- τα jobs με τα οποία μπορούμε να τρέξουμε διεργασίες στο παρασκήνιο.
Το άρθρο είναι μέρος της σειράς "Μάθε παιδί μου Linux".
Σχόλια
Δημοσίευση σχολίου
Πες την άποψή σου ή κάνε την ερώτησή σου ελεύθερα, ακολουθώντας όμως τους στοιχειώδεις κανόνες ευγένειας.