Μάθε παιδί μου Linux (μέρος 9) | Διεργασίες συστήματος

Linux processes

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

Τι είναι οι διεργασίες συστήματος και πώς τις ξεχωρίζουμε


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

Όπως ο κάθε χρήστης και η κάθε ομάδα έχουν ένα μοναδικό αναγνωριστικό (UID και GID αντίστοιχα), έτσι και οι διεργασίες έχουν το δικό τους με τη μορφή του PID (εκ του "Process ID"). Για να δούμε τις διεργασίες μας με τα PID τους στο τερματικό, θα δώσουμε την εντολή:

ps aux

Η απάντηση του τερματικού θα μοιάζει κάπως έτσι:

USER    PID    %CPU    %MEM VSZ    RSS    TTY    STAT START    TIME    COMMAND
root    1     0.0     0.0   8936    312  ?      Ssl   11:27    0:00    /init
root      6     0.0     0.0   8936   220    tty1   Ss      11:27  0:00    /init
chris     7     0.0     0.0  16784  3440 tty1   S       11:27  0:00    -bash
chris    34     0.0   0.0  17384   1932   tty1  R       11:34    0:00    ps aux
chris   935    0.0 0.0      0  0    tty1   Z     11:35    0:00    something

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

  • το USER που είναι ο χρήστης με την άδεια του οποίου τρέχει η διεργασία
  • το PID που αποτελεί τον μοναδικό αριθμό αναγνώρισης της διεργασίας
  • το TTY που είναι το τερματικό στο οποίο τρέχει η διεργασία
  • το STAT που είναι ο κωδικός κατάστασης της διεργασίας
  • το START που μας λέει τη διάρκεια εκτέλεσης της διεργασίας
  • το TIME που δείχνει το χρονικό διάστημα κατά το οποίο η διεργασία απασχόλησε τον επεξεργαστή και
  • το COMMAND που είναι το όνομα του εκτελέσιμου αρχείου ή της εντολής του

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

top

Linux top command

Τέλος αξίζει να πούμε ότι στο Linux οι διεργασίες αποθηκεύονται προσωρινά και σε αρχεία! Αυτά περιλαμβάνονται στο φάκελο "/proc" (εκ του "processes") όπως είδαμε στο άρθρο για το σύστημα αρχείων και φακέλων και χωρίζονται σε υποφακέλους ανάλογα με το PID τους.


Διαφήμιση

Οι γονείς, τα παιδιά και ο Θεός των διεργασιών!


Εκτός από το PID πολλές διεργασίες έχουν και τον αριθμό PPID (εκ του "Parent Process ID"). Αυτός ο αριθμός μας δείχνει από που προέρχεται η κάθε διεργασία ή για να το πούμε με ελεύθερη μετάφραση ποιος είναι ο "γονέας" της. Για να το καταλάβουμε στην πράξη ας δούμε ξανά τις διεργασίες μας με την εντολή:

ps l

Το τερματικό θα μας επιστρέψει κάτι τέτοιο:

F   UID   PID  PPID PRI  NI VSZ   RSS WCHAN  STAT   TTY TIME   COMMAND
0  1001     7      6  20   0 16792  3452 -       S      tty1  0:00   bash
0  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    COMMAND
root      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    COMMAND
root    1     0.0     0.0   8936    312  ?      Ssl   11:27    0:00    /init
root      6     0.0     0.0   8936   220    tty1   Ss      11:27  0:00    /init
chris     7     0.0     0.0  16784  3440 tty1   S       11:27  0:00    -bash
chris    34     0.0   0.0  17384   1932   tty1  R       11:34    0:00    ps aux
chris   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).

Στο πρώτο μας παράδειγμα βλέπουμε ότι η διεργασία με PID 1, έχει ένα ερωτηματικό ("?") στη θέση TTY. Αυτό σημαίνει ότι τρέχει ανεξάρτητα και δε σχετίζεται με κανένα τερματικό. Αυτές οι διεργασίες είναι συνήθως οι απολύτως απαραίτητες για να τρέχει το λειτουργικό μας σύστημα και σε καμία περίπτωση δεν πρέπει να τις πειράζουμε.

Linux tty1 terminal

Διαφήμιση

Τερματισμός διεργασιών με σήματα (signals)


Τώρα που μάθαμε όλα τα βασικά για τις διεργασίες μας, ήρθε η ώρα να περάσουμε στην πράξη και να δούμε πώς θα τις τερματίσουμε. Αυτό γίνεται με σήματα (signals) και ένα από τα πιο γνωστά εκτελείται με τα πλήκτρα Ctrl+C. Δώσαμε για παράδειγμα πριν την εντολή "top" για να δούμε τη λίστα των διεργασιών μας. Για να τερματίσουμε λοιπόν τη διεργασία "top" πατάμε Ctrl+C στο πληκτρολόγιο.

Μπορούμε να δούμε μία λίστα με όλα τα διαθέσιμα σήματα δίνοντας την εντολή:

trap -l

Linux trap command

Σημείωση:
Η αρίθμηση που βλέπουμε δεν είναι τυχαία και μπορούμε να χρησιμοποιήσουμε το νούμερο στην εντολή διακοπής που θα δώσουμε, έναντι του ονόματος του σήματος. Για παράδειγμα το "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" θα δούμε οτι το αρχείο μας συνεχίζει να κατεβαίνει στο παρασκήνιο, ενώ το τερματικό είναι ελεύθερο για να συνεχίσουμε να το χρησιμοποιούμε.

Linux jobs command

Για να φέρουμε ξανά τη διεργασία αυτή στο προσκήνιο θα δώσουμε την εντολή "fg" σε συνδυασμό με το Job ID της (π.χ. [3]) ως εξής:

fg %3

Τέλος για να "σκοτώσουμε" οποιαδήποτε εργασία βρίσκεται στο παρασκήνιο, θα χρησιμοποιήσουμε το "kill" και το Job ID της (π.χ. [3]) ως εξής:

kill %3

Σημείωση:
Για να τα θυμόμαστε ευκολότερα το "bg" προέρχεται από τη λέξη "background", ενώ το "fg" από το "foreground".

Εν κατακλείδι


Αυτά είναι λοιπόν τα βασικά για τις διεργασίες του Linux συστήματος. Από όλα όσα μάθαμε κρατάμε κυρίως:

  1. την εντολή "top" με την οποία μπορούμε να δούμε με μια ματιά τι τρέχει στον υπολογιστή μας,
  2. τον αριθμό PID με τον οποίο μπορούμε να ξεχωρίσουμε τις διεργασίες,
  3. την εντολή "kill" με την οποία μπορούμε να διακόψουμε βίαια οποιαδήποτε διεργασία και
  4. τα jobs με τα οποία μπορούμε να τρέξουμε διεργασίες στο παρασκήνιο.

Το άρθρο είναι μέρος της σειράς "Μάθε παιδί μου Linux".

Σχόλια

Δείτε επίσης...

Φεύγω από την Google (μέρος 15) | ''Ξηλώνουμε'' τα Google apps από το Android

Android | Γιατί δε θα αγόραζα ποτέ smartphone της OnePlus

Ιδιωτικό απόρρητο | Το αφελές επιχείρημα του ''Δεν έχω τίποτα να κρύψω''

Docker (μέρος 7) | Στήνουμε έναν reverse proxy για τα container μας με το Traefik

Μάθε παιδί μου Linux (μέρος 11) | Δίσκοι, κατατμήσεις και σύστημα αρχείων (filesystem)

Ubuntu Touch 2020 review | Μια πραγματική mobile GNU/Linux διανομή έτοιμη για καθημερινή χρήση

Docker (μέρος 1) | Τι είναι και πώς το εγκαθιστούμε στον υπολογιστή μας;

Android | Περιόρισε την παρακολούθηση των εφαρμογών και κόψε τις διαφημίσεις με το TrackerControl

Απόρρητο | ''Μπερδεύουμε'' τον αλγόριθμο Google και Facebook με ψεύτικες πληροφορίες

Android | Βάλε στην ''απομόνωση'' τις εφαρμογές που δεν εμπιστεύεσαι με το Shelter