Los programas que se ejecutan en un sistema Linux están sujetas a limitaciones de recursos. Pueden ser límites físicos im,puestos por el hardware (como la memoria), límites impuestos por la política de sistemas (por ejemplo, tiempo de CPU permitido) o límites de ejecución (como el tamaño de un entero o el número máximo de caracteres permitido en un nombre de archivo). La especificación UNIX define algunos de estos límites, que pueden ser determinados por una aplicación. En los próximos capítulos veremos los límites y las consecuencias de romperlos.
El archivo limits.h
define varias constantes manifiestas que representan las restricciones impuestas por el sistema operativo. Se incluyen las restricciones que aparecen en la siguiente tabla: Existen muchos más límites que podemos usar con las aplicaciones creadas, por eso debería acudir a los archivos de cabecera de su instalación.
El archivo de cabecera sys/resource.h
proporciona definiciones para las operaciones de recursos. Incluye las funciones que determinan y configuran los límites en el tamaño permitido de un programa, en la prioridad de ejecución, y en los recursos de archivos:
id_t
es un tipo entero usado para los identificadores de usuario y de grupo.
La estructura rusage
, definida en sys/resource.h
, se usa para determinar cuánto tiempo de CPU ha usado el programa actual.
Debe contener como mínimo los siguientes miembros:
La estructura timeval
está definida en sys/time.h
y contiene los campos tv_sec
y tv_usec
, que representan los segundos y los micro segundos respectivamente.
El tiempo de CPU consumido consumido por un programa se divide en tiempo de uso (el tiempo que el propio programa ha consumido ejecutando sus propias instrucciones) y el tiempo de sistema (el tiempo de CPU consumido por el sistema operativo en nombre del programa, es decir, el tiempo consumido en las llamadas al sistema ejecutando entradas y salidas y otras funciones del sistema).
La función getrusage
escribe información sobre el tiempo de CPU en la estructura rusage
que indica el parámetro r_usage
.
El parámetro who
puede ser una de las siguientes constantes:
Más adelante estudiaremos los procesos hijo y las tareas prioritarias, pero por una cuestión de coherencia, vamos a estudiar su implicación en los recursos del sistema aquí. Por ahora es suficiente con decir que cada programa en ejecución tiene una prioridad asociada, y que a los programas con una mayor prioridad se les asigna más tiempo de CPU disponible.
Las aplicaciones pueden determinar y alternar sus prioridades (y las de otros) con las funciones getpriority
y setptiority
.
El proceso que han de examinar o modificar las funciones prioritarias puede ser definido por los identificadores de proceso, por el identificador de grupo o de usuario.
El parámetro which
específica cómo se ha de tratar al parámetro who
. De manera que, para determinar la prioridad del proceso actual, debería llamar a
Por defecto, la prioridad es 0
. Las prioridades positivas se usan para las tareas secundarias que se ejecutan cuando no hay ninguna otra tarea prioritaria lista para la ejecución. Las prioridades negativas hacen que el programa se ejecute con más frecuencia consumiendo una mayor porción del tiempo CPU disponible. El rango de prioridades va de -20
a +20
. Puede resultar confuso porque cuanto más alto es el valor numérico, menor es el nivel de preferencia de ejecución.
getpriority
envía una prioridad válida si tiene éxito o -1
con errno
si se produce un error. Como -1
es un valor válido, errno
debería ser cero antes de llamar a getpriority
y a la vuelta debería seguir siendo cero. setpriority
envía 0
si tiene éxito, o -1
en caso contrario.
getrlimit
y setrlimit
pueden leer y establecer los límites de recursos del sistema. Ambas funciones usan una estructura general, rlimit
, para describir los límites de los recursos. Se define en sys/resource.h
y tiene los siguientes miembros:
El tipo definido rlim_t
es un tipo entero usado para describir niveles de recursos. Normalmente, el límite menor es un límite recomendado que no se debería superar, porque si se hacen puede provocar que las funciones de biblioteca envíen errores. Si se supera el límite más duro podría intentar que el sistema intentase finalizar el programa enviándole una señal. Por ejemplo, la señal SIGXCPU
excediendo el tiempo límite de la CPU y la señal SIGSEGV
excediendo el tamaño límite de los datos. Un programa puede establecer sus propios límites, siempre por debajo del límite superior. También puede reducir dicho límite. Sólo un programa que se ejecute con privilegios de superusuario puede aumentar el límite superior.
Se pueden limitar varios recursos de sistemas. Son especificados por el parámetro resource
de las funciones rlimit
y se definen en sys/resources
tal como indica la tabla de abajo: La siguiente sección nos mostrará un programa de ejemplo que llamaremos limits.c, y simula una aplicación típica. También configura y rompe el límite de un recurso.
- Incluya los archivos de cabecera de todas laas funciones que vamos a usar en este programa:
- La función
void
escribe una cadena en un archivo temporal10000
veces y después realiza una operación aritmética para provocar la carga en la CPU: - La función
main
llama awork
y después usa la funcióngetrusage
para descubrir cuánto tiempo de CPU ha usado. Muestra la información en pantalla: - A continuación, llama a
getpriority
y agetrlimit
para descubrir su prioridad actual y los límites del tamaño del archivo, respectivamente: - Finalmente, establece un límite en el tamaño del archivo usando setrlimit y llamando de nuevo a work, que falla porque intenta crear un archivo muy largo:
Cuando ejecute este programa, podrá ver cuántos recursos de la se han consumido y la prioridad de ejecución predeterminada del programa. Una vez que se ha configurado el tamaño límite de un archivo, el programa no puede escribir más de 2048 bytes en un archivo temporal.
Podemos modificar la prioridad del programa iniciándolo con el comando nice
. Aquí, puede ver las modificaciones de la prioridad a +10
y, como resultado, el programa tarda un poco más en ejecutarse:
El programa limits
llama a la función work
para simular las acciones de un programa típico.
Realiza algunos cálculos y produce alguna salida, en este caso, en torno a 150K en un archivo temporal.
Llama a las funciones de recursos para descubrir su prioridad y los límites de tamaño de los archivos.
En este caso, no se han configurado los límites en el tamaño del archivo, permitiendole crear un archivo tan largo como desee (todo lo que le permita el espacio del disco duro). Después, el programa configura el límite de su tamaño de archivo en 2K
e intenta realizar de nuevo algún trabajo. Esta vez, la función work
falla porque no puede crear un archivo temporal tan grande.
También pueden establecer límites en un programa que se ejecute con una shell en particular con el comando bash ulimit
.
En este ejemplo, el mensaje de error «Error de escritura en archivo temporal
(Error writing to temporary file)» no aparece tal como esperábamos. Esto se debe a que algunos sistemas (como Linux 2.2 y posteriores) finalizan el programa cuando excede el límite de un recurso. Lo hace enviando una señal, SIGXFSZ
. Más adelante veremos más a fondo las señales y su uso.
Debe estar conectado para enviar un comentario.