Curs 03 - Procese

  • Cuvinte cheie: resurse, instrucțiuni, atribute, ps, top, shel, init, fg, bg, descriptor de fișiere, kill, killall, semnale, interacțiuni, daemoni

Demo

Uptime

Comanda uptime se folosește dacă dorim să aflăm de cât timp este aprins (rulează) sistemul. Se afișează timpul curent, starea sistemului (up), timpul de cat timp rulează, numărul de utilizatori logați pe sistem și media încărcăturii în ultimele 1, 5 si 15 minute.

student@uso:~/uso-lab$ uptime
 13:37:20 up  1:34,  1 user,  load average: 0,05, 0,16, 0,10

Se poate folosi tagul -p pentru un format mai frumos, mai lizibil (pretty), tagul -s pentru a vedea ora de cand este pornit sistemul într-o mod mai exact (specific)

student@uso:~/uso-lab$ uptime -p
up 1 hour, 44 minutes
student@uso:~/uso-lab$ uptime -s
2020-10-14 12:02:26

fg & bg

Un proces poate fi oprit, sau poate rula fie în foreground fie în background. Dacă procesul rulează în foreground, acesta va acapara terminalul actual până când se va termina, spre deosebire de un proces care rulează în background. Se trece un proces din foreground în background oprind prima dată procesul folosind combinatia de taste Ctrl + Z, iar apoi tastând comanda bg. Un proces poate fi adus din background în foreground folosind comanda fg.

student@uso:~$ sleep 100
^Z
[1]+  Stopped             	sleep 100
student@uso:~$ jobs
[1]+  Stopped             	sleep 100
student@uso:~$ bg
[1]+ sleep 100 &
student@uso:~$ jobs
[1]+  Running             	sleep 100 &
student@uso:~$ fg
sleep 100

Folosim utilitarul jobs pentru a vedea procesele pornite din terminalul actual și statusul lor.

Pentru a verifica faptul că procesul din primul terminal (sleep 100) rulează în foreground, putem da diferite comenzi, precum ls, și observam ca acestea nu au niciun efect, terminalul fiind acaparat de procesul sleep 100.

student@uso:~$ fg
sleep 100
ls
ps
tree

Semnale (Kill)

Comanda kill se folosește pentru a da semnale proceselor, nu neapărat sa le omoare, cum sugerează numele comenzii. Pentru a vedea ce comenzi putem trimite proceselor se folosește comanda kill -l.

student@uso:~$ kill -l
 1) SIGHUP     2) SIGINT     3) SIGQUIT     4) SIGILL     5) SIGTRAP
 6) SIGABRT     7) SIGBUS     8) SIGFPE     9) SIGKILL    10) SIGUSR1
11) SIGSEGV    12) SIGUSR2    13) SIGPIPE    14) SIGALRM    15) SIGTERM
16) SIGSTKFLT    17) SIGCHLD    18) SIGCONT    19) SIGSTOP    20) SIGTSTP
21) SIGTTIN    22) SIGTTOU    23) SIGURG    24) SIGXCPU    25) SIGXFSZ
26) SIGVTALRM    27) SIGPROF    28) SIGWINCH    29) SIGIO    30) SIGPWR
31) SIGSYS    34) SIGRTMIN    35) SIGRTMIN+1    36) SIGRTMIN+2    37) SIGRTMIN+3
38) SIGRTMIN+4    39) SIGRTMIN+5    40) SIGRTMIN+6    41) SIGRTMIN+7    42) SIGRTMIN+8
43) SIGRTMIN+9    44) SIGRTMIN+10    45) SIGRTMIN+11    46) SIGRTMIN+12    47) SIGRTMIN+13
48) SIGRTMIN+14    49) SIGRTMIN+15    50) SIGRTMAX-14    51) SIGRTMAX-13    52) SIGRTMAX-12
53) SIGRTMAX-11    54) SIGRTMAX-10    55) SIGRTMAX-9    56) SIGRTMAX-8    57) SIGRTMAX-7
58) SIGRTMAX-6    59) SIGRTMAX-5    60) SIGRTMAX-4    61) SIGRTMAX-3    62) SIGRTMAX-2
63) SIGRTMAX-1    64) SIGRTMAX

Cel mai puternic semnal pentru a termina un proces este SIGKILL, transmis prin comanda kill -9, urmat de PID-ul procesului pe care îl vom termina.

Dacă vrem sa terminăm un proces dintr-un terminal care este acaparat de acesta, aflăm PID-ul procesului din alt terminal folosind comanda ps aux urmată de comanda kill -9 și PID-ul aflat la pasul anterior. De exemplu, dacă dorim să terminăm procesul sleep 100 din primul terminal, în al doilea vom avea următoarele comenzi:

student@uso:~$ ps aux
USER       PID  %CPU  %MEM	VSZ      RSS   TTY  	STAT START   TIME COMMAND
root             1       0.0         0.3         168976   12980    ?       	  Ss     12:01     0:03  /sbin/init sp
root             2       0.0         0.0               0 	    0         ?    	   S	12:01    0:00  [kthreadd]
root             3       0.0         0.0  	   0 	    0         ?    	   I<     12:01   	 0:00  [rcu_gp]
root             4       0.0         0.0  	   0 	    0         ?    	   I<      12:01    0:00 [rcu_par_gp]
[...]
root   	    24687  0.0        0.0  	   0           0         ?    	   I	13:32   0:00 [kworker/1:0-
root          24717  0.0        0.0  	   0 	    0         ?    	   I	13:37  	0:00  [kworker/0:1-
student    24735  0.0        0.0  	19572    592     pts/0	  S+     13:43   0:00  sleep 100
student    24736  0.0        0.0  	22972   3608    pts/1 	  R+     13:43   0:00  ps aux
student@uso:~$ kill -9 24735

Și observam ca în terminalul inițial apare “Killed”:

student@uso:~$ sleep 100
Killed
student@uso:~$

Putem afla PID-ul procesului folosind, de asemenea, comanda pgrep sleep, obtinând PID-ul comenzii sleep, 24735.

Redirectarea din fișier (< și >)

Pentru a redirecta dintr-un fișier pentru un anumit proces se folosește <, iar pentru redirectarea într-un fișier se va folosi >. De exemplu, dacă avem următorul program scris în C, care doar afișează inputul, se poate redirecta continutul fisierului README.md pentru a-l avea ca input.

#include <stdio.h>
int main() {
»   	char line[1000];
»   	while (fgets(line,1000,stdin)) {
»   	»   	printf("%s",line);
»   	}
»   	return 0;
}
student@uso:~/uso-lab$ ./readfile < README.md
# uso-lab
Public repository for USO labs

Pentru a verifica faptul că acesta este chiar conținutul fișierului README.md, folosim comanda cat.

student@uso:~/uso-lab$ cat README.md
# uso-lab
Public repository for USO labs

Pentru a redirecta outputul unui proces (comenzi) putem folosi numele comenzii, urmat de >, apoi de numele fișierului.

student@uso:~/uso-lab$ ps > ps.txt
student@uso:~/uso-lab$ cat ps.txt
PID     TTY      TIME      CMD
24501 pts/0	00:00:00 bash
25026 pts/0	00:00:00   ps

Se poate, de asemenea, sa folosim atat redirectarea intrării, cât și cea a ieșirii în aceeași comanda. De exemplu, dacă vrem sa redirecționăm continutul fișierului README.md la executabilul readfile prezentat mai sus și să redirecționăm output-ul în fișierul file.txt. Apoi putem verifica conținutul fișierului file.txt folosind comanda cat.

student@uso:~/uso-lab$ ./readfile < README.md >file.txt
student@uso:~/uso-lab$ cat file.txt
# uso-lab
Public repository for USO labs
student@uso:~/uso-lab$

Se folosește » pentru a redirecta output-ul într-un fișier și a î-l adăuga la finalul fișierului

student@uso:~/uso-lab$ cat file.txt
# uso-lab
Public repository for USO labs
student@uso:~/uso-lab$ echo "new content" >> file.txt
student@uso:~/uso-lab$ cat file.txt
# uso-lab
Public repository for USO labs
new content

Înlănțuirea de comenzi

Putem inlantui comenzi folosind ;, || sau &&.

  • Pentru înlănțuire necondiționată se folosește “;”, dacă avem comanda x;y, mai intai se rulează x, apoi y.
  • Dacă avem comanda x || y, se rulează x, iar în cazul în care aceasta comanda nu a fost finalizată cu succes se va rula y, însă dacă comanda x a fost rulata fără erori, y nu se va mai rula.
  • Dacă avem x && y se vor rula ambele comenzi doar dacă comanda x nu a întâmpinat probleme la rulare.
student@uso:~/uso-lab$ echo "a";echo "b"
a
b
student@uso:~/uso-lab$ echo "a" || echo "b"
a
student@uso:~/uso-lab$ echo "a" && echo "b"
a
b
student@uso:~/uso-lab$ cd file.txt || echo "nu e director"
bash: cd: file.txt: Not a directory
nu e director
student@uso:~/uso-lab$ cat file.txt && echo "comanda cat a avut succes"
# uso-lab
Public repository for USO labs
new content
comanda cat a avut succes
student@uso:~/uso-lab$

Pipe

Se poate redirecta output-ul unei comenzi în input-ul unei alte comenzi dând comanda a | b, unde output-ul comenzii a va fi folosit ca input pentru comanda b. De exemplu, putem afisa continutul fisierului README.md ca sa fie utilizat de programul precedent (readfile), sau sa redirectionam conținutul fișierului /etc/passwd utilitarului grep pentru a găsi secvența “student”:

student@uso:~/uso-lab$ cat README.md | ./readfile
# uso-lab
Public repository for USO labs
student@uso:~/uso-lab$ cat /etc/passwd | grep "student"
student:x:1000:1000:student,,,:/home/student:/bin/bash

ps

Folosim comanda ps pentru a afișa informații despre procesele active.

student@uso:~$ ps
    PID TTY          TIME CMD
   2975 pts/0    00:00:00 bash
   3005 pts/0    00:00:00 ps
  • În prima coloană se află PID-ul procesului( process ID). FIecare PID este unic.
  • În a doua coloană se afla tipul terminalului în care utilizatorul este logat.
  • În a treia coloană se află timpul în care procesul rulează.
  • În a patra coloană se află comanda care pornește procesul.

Pentru o afișare mai detaliată a proceselor, trebuie să utilizați opțiunea –aux în linia de comandă.

student@uso:~$ ps -aux
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           1  0.2  0.3 103420 12860 ?        Ss   14:03   0:03 /sbin/init sp
root           2  0.0  0.0      0     0 ?        S    14:03   0:00 [kthreadd]
root           3  0.0  0.0      0     0 ?        I<   14:03   0:00 [rcu_gp]
root           4  0.0  0.0      0     0 ?        I<   14:03   0:00 [rcu_par_gp]
root           6  0.0  0.0      0     0 ?        I<   14:03   0:00 [kworker/0:0H
root           7  0.0  0.0      0     0 ?        I    14:03   0:00 [kworker/u4:0
root           8  0.0  0.0      0     0 ?        I<   14:03   0:00 [mm_percpu_wq
root           9  0.0  0.0      0     0 ?        S    14:03   0:00 [ksoftirqd/0]
root          10  0.0  0.0      0     0 ?        I    14:03   0:00 [rcu_sched]
root          11  0.0  0.0      0     0 ?        S    14:03   0:00 [migration/0]
root          12  0.0  0.0      0     0 ?        S    14:03   0:00 [idle_inject/
root          14  0.0  0.0      0     0 ?        S    14:03   0:00 [cpuhp/0]
root          15  0.0  0.0      0     0 ?        S    14:03   0:00 [cpuhp/1]
root          16  0.0  0.0      0     0 ?        S    14:03   0:00 [idle_inject/
root          17  0.0  0.0      0     0 ?        S    14:03   0:00 [migration/1]
root          18  0.0  0.0      0     0 ?        S    14:03   0:00 [ksoftirqd/1]
root          19  0.0  0.0      0     0 ?        I    14:03   0:00 [kworker/1:0-
root          20  0.0  0.0      0     0 ?        I<   14:03   0:00 [kworker/1:0H
root          21  0.0  0.0      0     0 ?        S    14:03   0:00 [kdevtmpfs]
root          22  0.0  0.0      0     0 ?        I<   14:03   0:00 [netns]
root          23  0.0  0.0      0     0 ?        S    14:03   0:00 [rcu_tasks_kt
root          24  0.0  0.0      0     0 ?        S    14:03   0:00 [kauditd]
root          25  0.0  0.0      0     0 ?        S    14:03   0:00 [khungtaskd]
root          26  0.0  0.0      0     0 ?        S    14:03   0:00 [oom_reaper]
root          27  0.0  0.0      0     0 ?        I<   14:03   0:00 [writeback]
root          28  0.0  0.0      0     0 ?        S    14:03   0:00 [kcompactd0]
root          29  0.0  0.0      0     0 ?        SN   14:03   0:00 [ksmd]
root          30  0.0  0.0      0     0 ?        SN   14:03   0:00 [khugepaged]
root         123  0.0  0.0      0     0 ?        I<   14:03   0:00 [kintegrityd]
root         124  0.0  0.0      0     0 ?        I<   14:03   0:00 [kblockd]
  • -a = arată procesele tuturor utilizatorilor.
  • -u = afișează utilizatorul care deține procesul.
  • -x = afișează și procesele ce nu aparțin terminalului.

pidof

Ca să găsiți PID-ul unui proces (cu numele specificat) activ folosiți comanda pidof.

student@uso:~$ ps
    PID TTY          TIME CMD
   2975 pts/0    00:00:00 bash
  23891 pts/0    00:00:00 ps
student@uso:~$ pidof bash
2975

Procesul init are întotdeauna PID-ul 1.

student@uso:~$ pidof init
1 

pstree

Pentru că în Linux procesele au un proces părinte, uneori vrem să vizualizăm toate procesele într-o structură ierarhică. Pentru asta folosim comanda pstree. Dacă folosim opțiunea –c pentru a afișa și PID-ul procesului.

lsof

Această comandă ne ajută să aflăm informații despre fișierele deschise de fiecare proces din sistem.

student@uso:~$ lsof
gsd-usb-p  2083                         student  mem       REG              252,5   157944     533402 /usr/lib/x86_64-linux-gnu/libgdk_pixbuf-2.0.so.0.4000.0
gsd-usb-p  2083                         student  mem       REG              252,5    64808     534307 /usr/lib/x86_64-linux-gnu/libwayland-client.so.0.3.0
gsd-usb-p  2083                         student  mem       REG              252,5  2029224     533090 /usr/lib/x86_64-linux-gnu/libc-2.31.so
gsd-usb-p  2083                         student  mem       REG              252,5  1207920     533430 /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3
gsd-usb-p  2083                         student  mem       REG              252,5   387448     533460 /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.6400.3
gsd-usb-p  2083                         student  mem       REG              252,5  1957200     533420 /usr/lib/x86_64-linux-gnu/libgio-2.0.so.0.6400.3
gsd-usb-p  2083                         student  mem       REG              252,5    38984     533841 /usr/lib/x86_64-linux-gnu/libnotify.so.4.0.0

pgrep

pgrep este o comandă ce afișează anumite PID-uri bazate pe anumite criterii.

student@uso:~$ pgrep ssh
765
1705

În exemplul de mai sus sunt afișate PID-urile proceselor care contin in nume ”ssh”. Dacă vrem să afișăm doar PID-urile proceselor unui anumit utilizator folosim optiunea –u urmat de numele utilizatorului.

student@uso:~$ pgrep -u student
1505
1507
1518
1520
1524
1528
1530
1533
1539
1546
1560
1570
1574
1579
1583
1587
1602
1612
1705
1722
1729
1730
1733
1735
1738
1758
1763
1771

top & htop

Pentru a avea o vizualizare în timp real a sistemului nostru putem folosi comanda top. Aceasta oferă informații despre procesele care rulează în sistem(PID, utilizator, procentul de memorie folosită etc.)

Htop este o comandă ce oferă o vizualizare interactivă a resurselor vitale ale sistemului. Față de comanda top este mai nouă și oferă îmbunătățiri. Un exemplu este că poți scroll atât pe verticală cât și pe orizontală, pentru a putea vedea toate procesele ce rulează în sistem împreună cu toate specificatiile lor.

Ptrace este un apel către sistemul de operare folosit pentru investigarea amănunțită a proceselor și este folosit în cadrul utilitarelor pentru debug (cum este utilitarul gdb) sau în cadrul tool-urilor strace și ltrace.

Comanda strace monitorizează apelurile pe care le face o altă comandă către sistemul de operare (strace – system call tracing). Pentru început, pornim de la un program simplu scris în C care afișează șirul de caractere “Hello World” la ieșirea standard.

hello_world.c
#include <stdio.h>

int main() {
        printf("Hello World\n");
        return 0;
}

Pentru compilarea programului vom lansa comanda:

student@uso:~/uso-lab$ gcc hello_world.c -o hello_world

În urma rulării executabilului, obținem următorul rezultat:

student@uso:~/uso-lab$ ./hello_world
Hello World

Dacă dorim să vedem apelurile către sistemul de operare efectuate de programul hello_world, putem folosi următoarea comandă:

student@uso:~/uso-lab$ strace ./hello_world
execve("./hello_world", ["./hello_world"], 0x7fffe3d9b840 /* 21 vars */) = 0
brk(NULL)                               = 0x7fffc4eec000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
[...]
write(1, "Hello World\n", 12Hello World
)           
[...]

Un alt utilitar înrudit cu strace este ltrace. Acesta urmăreşte apelurile de bibliotecă. În cazul programului hello_world, rezultatul este următorul:

$ ltrace ./hello_world
puts("Hello World"Hello World
)                                              
uso/cursuri/curs-03.txt · Last modified: 2022/10/17 14:23 by sergiu.weisz
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0