resource - Gestione delle Risorse di Sistema
Scopo: Gestisce i limiti delle risorse di sistema per un programma Unix
Le funzioni in resource rilevano le risorse del sistema corrente consumate da un processo, e pongono limiti su di esse per controllare quanto carico un programma può imporre a un sistema.
Utilizzo Corrente
Si usi getrusage()
per rilevare le risorse usate dal processo corrente e/o dai suoi figli. Il valore di ritorno è una struttura dati contenente parecchie metriche di risorse basate sullo stato corrente del sistema.
# resource_getrusage.py
import resource
RESOURCES = [
('ru_utime', 'Tempo utente'),
('ru_stime', 'Tempo sistema'),
('ru_maxrss', 'Dimensione massima memoria\nfisica'
' mappata dal processo '),
('ru_ixrss', 'Dimensione memoria condivisa '),
('ru_idrss', 'Dimensione memoria non condivisa'),
('ru_isrss', 'Dimensione dello stack'),
('ru_inblock', 'Blocchi input'),
('ru_oublock', 'Blocchi output'),
]
usage = resource.getrusage(resource.RUSAGE_SELF)
for name, desc in RESOURCES:
print('{:<32} ({:<10}) = {}'.format(
desc, name, getattr(usage, name)))
Il programma di test è estremamente semplice, quindi non usa molte risorse.
$ python3 resource_getrusage.py Tempo utente (ru_utime ) = 0.021376 Tempo sistema (ru_stime ) = 0.0 Dimensione massima memoria fisica mappata dal processo (ru_maxrss ) = 10016 Dimensione memoria condivisa (ru_ixrss ) = 0 Dimensione memoria non condivisa (ru_idrss ) = 0 Dimensione dello stack (ru_isrss ) = 0 Blocchi input (ru_inblock) = 40 Blocchi output (ru_oublock) = 0
Limiti delle Risorse
Oltre al reale utilizzo, è possibile verificare i limit imposti all'applicazione, per puoi modificarli.
# resource_getrlimit.py
import resource
LIMITS = [
('RLIMIT_CORE', 'Dimensione file core'),
('RLIMIT_CPU', 'Tempo CPU'),
('RLIMIT_FSIZE', 'Dimensione file'),
('RLIMIT_DATA', 'Dimensione heap '),
('RLIMIT_STACK', 'Dimensione stack '),
('RLIMIT_RSS', 'Dimensione massima memoria\n'
'fisica mappata del processo '),
('RLIMIT_NPROC', 'Numero di processi'),
('RLIMIT_NOFILE', 'Numero di file aperti'),
('RLIMIT_MEMLOCK', 'Indirizzo di memoria bloccabile'),
]
print('Limit delle risorse (soft/hard):')
for name, desc in LIMITS:
limit_num = getattr(resource, name)
soft, hard = resource.getrlimit(limit_num)
print('{:<32} {}/{}'.format(desc, soft, hard))
Il valore di ritorno per ciascun limite è una tupla che contiene il limite soft imposto dalla configurazione corrente e il limite hard imposto dal sistema operativo.
$ python3 resource_getrlimit.py Limit delle risorse (soft/hard): Dimensione file core 0/-1 Tempo CPU -1/-1 Dimensione file -1/-1 Dimensione heap -1/-1 Dimensione stack 8388608/-1 Dimensione massima memoria fisica mappata del processo -1/-1 Numero di processi 31345/31345 Numero di file aperti 1048576/1048576 Indirizzo di memoria bloccabile 67108864/67108864
I limiti possono essere cambiati con setrlimit()
.
# resource_setrlimit_nofile.py
import resource
soft, hard = resource.getrlimit(resource.RLIMIT_NOFILE)
print('Limite soft inizia come :', soft)
resource.setrlimit(resource.RLIMIT_NOFILE, (4, hard))
soft, hard = resource.getrlimit(resource.RLIMIT_NOFILE)
print('Limite soft modificato in:', soft)
random = open('/dev/random', 'r')
print('random ha fd =', random.fileno())
try:
null = open('/dev/null', 'w')
except IOError as err:
print(err)
else:
print('null ha fd =', null.fileno())
Questo esempio usa RLIMIT_NOFILE
per controllare il numero di file aperti consentiti, modificandolo con un limite soft inferiore rispetto al predefinito.
$ python3 resource_setrlimit_nofile.py Limite soft inizia come : 1048576 Limite soft modificato in: 4 random ha fd = 3 [Errno 24] Too many open files: '/dev/null'
Può anche essere utile limitare l'ammontare di tempo di CPU che un processo può consumare, per evitarne di utilizzarne troppo. Quando il processo supera il limite di tempo allocato, invia un segnale SIGXCPU
.
# resource_setrlimit_cpu.py
import resource
import signal
import time
# Imposta un gestore di segnale per notificare
# quando il tempo si esaurisce
def time_expired(n, stack):
print('SCADUTO :', time.ctime())
raise SystemExit('(tempo scaduto)')
signal.signal(signal.SIGXCPU, time_expired)
# Adjust the CPU time limit
soft, hard = resource.getrlimit(resource.RLIMIT_CPU)
print('Limite soft inizia come :', soft)
resource.setrlimit(resource.RLIMIT_CPU, (1, hard))
soft, hard = resource.getrlimit(resource.RLIMIT_CPU)
print('Limite soft modificato in:', soft)
print()
# Consume some CPU time in a pointless exercise
print('Partenza:', time.ctime())
for i in range(200000):
for i in range(200000):
v = i * i
# We should never make it this far
print('Uscita :', time.ctime())
Normalmente un gestore di segnale finisce di scrivere tutti i file aperti e li chiude, ma in questo caso stampa semplicemente un messaggio ed esce.
$ python3 resource_setrlimit_cpu.py Limite soft inizia come : -1 Limite soft modificato in: 1 Partenza: Thu Jun 3 09:15:32 2021 SCADUTO : Thu Jun 3 09:15:33 2021 (tempo scaduto)