Esistono processi che necessitano di maggiori risorse computazionali rispetto ad altri. In passato ciò poteva creare problemi di ordine pratico con una certa frequenza quando gli stessi andavano a coesistere con altri processi. Nella modernità, invece, la gestione manuale delle scelte relative a come abbinare i processi e le risorse con cui sfamarli si rivela generalmente non necessaria poiché le attuali implementazioni multicore dei processori nonché l’evoluzione degli automatismi di gestione interni ai sistemi operativi multitask e multithread hanno di fatto reso quasi sempre superfluo l’intervento umano diretto per mediare questi aspetti.
Detto ciò possiamo trovarci di fronte a due condizioni rare ma entrambe possibili: le scelte automatiche per la gestione delle risorse si rivelano inadeguate per le nostre esigenze oppure desideriamo “pilotare” un sistema particolarmente obsoleto. In questi casi potrà rivelarsi utile saper agire sulla priorità assegnata a un processo. Essa rappresenta il peso con cui un processo deve essere considerato ripartendo le risorse di calcolo.
Per influenzarla è possibile modificare i valori di nice per ogni processo. Un utente comune può agire solo sui processi di cui è proprietario e solo decrementandone la priorità ovvero limitandone l’accesso al calcolo. L’utente root può, invece, assegnare qualsiasi valore a qualsiasi processo. A tale scopo illustreremo due comandi: nice e renice. Adoperandoli modifichiamo per l'appunto il valore di nice di un processo che a sua volta influenzerà la priorità presa in considerazione dallo scheduler che gestisce il tempo di calcolo.
E' possibile assegnare valori di nice da -20, in cui il processo è segnalato quale di massima priorità, a 19, in cui il processo è da intendersi di minima priorità. Prima di far ciò osserviamo quanto avviene nei due terminali seguenti precisando che essi sono stati eseguiti contemporaneamente. Potremmo anche ottenere risultati simili utilizzando il bakgrounding e un unico terminale.
fprincipe@html52:~$ sudo renice -3 14149
14149 (process ID) old priority 0, new priority -3
fprincipe@html52:~$ nice -n 2 nano
fprincipe@html52:~$ ps -u fprincipe -o pid,pri,ni,cmd
PID PRI NI CMD
2069 19 0 /lib/systemd/systemd --user
2080 19 0 (sd-pam)
2175 19 0 -bash
14149 22 -3 sshd: fprincipe@pts/1
14150 19 0 -bash
14389 19 0 sshd: fprincipe@pts/0
14390 19 0 -bash
14408 17 2 nano
14409 19 0 ps -u fprincipe -o pid,pri,ni,cmd
renice e nice
Il comando renice agisce su un processo già lanciato mentre il comando nice influisce sul processo che lanciamo passandolo a questo come argomento. Nel primo terminale, quindi, chiediamo di assegnare un valore di nice -3 al PID 14149 adoperando il comando renice. Poi utilizziamo il comando nice specificando che quanto stiamo lanciando in quel momento dovrà avere un incremento di nice pari a 2.
Osserviamo il secondo terminale per prendere atto degli effetti causati dalle nostre azioni. Partendo dalla kernel priority (PRI) di base 19 quest’ultima viene ricalcolata a 22 per il PID 14149 come effetto di un valore nice -3 mentre nano è effettivamente eseguito con kernel priority 17
quale conseguenza del valore di nice pari a 2. Altri argomenti per renice (oltre -n che specifica il valore di nice) sono riportati nella tabella seguente.
Interpreta gli argomenti seguenti come: | ||
---|---|---|
-g | group IDs | |
-p | PIDs | default |
-u | Usernames o UIDs |
Ricordiamo che potremo trovare la spiegazione di queste sigle al capoverso “Raggruppamento di Processi” di Introduzione ai Processi Linux.
kill e killall
Quando desideriamo terminare un processo le metodologie che possono essere adoperate sono molteplici ma operando su CLI la strada maestra è rappresentata dai due comandi kill e killall.
Il primo invia un segnale atto a invocare la terminazione dei PIDs che gli passiamo come argomento. Nell’esempio seguente questo effetto appare chiaro. Osserviamo la lista processi ottenuta tramite ps, prima esiste un processo top, dopo l'invio di un kill al suo PID questo sparisce.
fprincipe@html52:~$ ps -u fprincipe
PID TTY TIME CMD
2123 ? 00:00:00 systemd
2131 ? 00:00:00 (sd-pam)
2154 tty1 00:00:00 bash
2440 ? 00:00:00 sshd
2441 pts/0 00:00:00 bash
2531 ? 00:00:00 sshd
2532 pts/1 00:00:00 bash
2566 pts/1 00:00:00 top
2570 pts/0 00:00:00 ps
fprincipe@html52:~$ kill 2566
fprincipe@html52:~$ ps -u fprincipe
PID TTY TIME CMD
2123 ? 00:00:00 systemd
2131 ? 00:00:00 (sd-pam)
2154 tty1 00:00:00 bash
2440 ? 00:00:00 sshd
2441 pts/0 00:00:00 bash
2531 ? 00:00:00 sshd
2532 pts/1 00:00:00 bash
2571 pts/0 00:00:00 ps
In realtà è possibile inviare segnali diversi verso un processo adoperando il comando kill nell’intenzione che ciò causi azioni volte a:
- Terminarlo (Term). Richiediamo cioè la terminazione del processo.
- Ignorarlo (Ign). Inviamo un segnale che verrà ignorato.
- Creare un Core Dump (Core). Chiediamo che il processo sia terminato e venga generato un file che contiene informazioni utili a tracciare con un debugger il comportamento del processo nell’istante immediatamente antecedente al segnale.
- Arrestarlo (Stop). Inoltriamo richiesta per arrestare temporaneamente il processo.
- Riattivarlo (Cont). Chiediamo che il processo sia riattivato se precedentemente arrestato.
I segnali più comunemente usati sono:
- SIGHUP, inviamo il segnale che di norma comunica ai figli di un processo che il processo padre è stato terminato.
- SIGINT, inviamo il segnale 2, è un effetto equivalente a quello che otterremmo premendo i tasti “CTRL”+“C” su un processo in esecuzione interattiva nel terminale.
- SIGKILL, inviamo il segnale 9, questo è un segnale che normalmente termina un processo quando è appeso. In alcuni casi può però fallire e le risorse precedentemente assegnate al processo possono risultare comunque occupate anche a processo terminato.
- SIGTERM, inviamo il segnale 15, questo è un segnale di terminazione più brutale che non prevede un messaggio di risposta dal gestore delle risorse. In genere ha efficacia su quasi tutti i processi e non lascia appeso nulla che sia stato precedentemente assegnato al processo.
Con kill -s possiamo specificare il tipo di segnale da inviare agli argomenti che segueno il segnale. I segnali riportati nella precedente lista risultano dall'alto in basso sempre più aggressivi nei confronti di processi che intendiamo sospendere o terminare. Eseguiti nell’ordine in cui sono elencati, ovvero passando dal precedente al successivo qualora il precedente risulti inefficace, possono rappresentare un utile strumento per arrestare processi di cui si è perso il controllo.
Esistono altri possibili segnali, vi esortiamo a invocare i comandi kill -l e man signal per averne contezza.
Concludiamo quindi la puntata attuale con killall. Questo termina tutti i processi che sono in relazione con la command line argomento.
Non è necessario illustrare molto altro per adoperarlo ma consigliamo una certa cautela. E' meglio avere le idee chiare sulla gerarchia e sui gruppi di processi che andiamo a "potare". L'esempio a seguire chiarirà meglio le potenzialità del comando. Nel terminale che vedete in chiusura un’unica istanza killall ternina due distinti processi top.
fprincipe@html52:~$ ps -u fprincipe -o pid,cmd
PID CMD
2123 /lib/systemd/systemd --user
2131 (sd-pam)
2154 -bash
2440 sshd: fprincipe@pts/0
2441 -bash
2531 sshd: fprincipe@pts/1
2532 -bash
2972 top
3101 sshd: fprincipe@pts/2
3102 -bash
3112 top
3197 sshd: fprincipe@pts/3
3198 -bash
3210 ps -u fprincipe -o pid,cmd
fprincipe@html52:~$ killall top
fprincipe@html52:~$ ps -u fprincipe -o pid,cmd
PID CMD
2123 /lib/systemd/systemd --user
2131 (sd-pam)
2154 -bash
2440 sshd: fprincipe@pts/0
2441 -bash
2531 sshd: fprincipe@pts/1
2532 -bash
3101 sshd: fprincipe@pts/2
3102 -bash
3197 sshd: fprincipe@pts/3
3198 -bash
3212 ps -u fprincipe -o pid,cmd