Esta página puede ser redistribuida libremente bajo los términos de la licencia GPL. Vease ( GPL texto original ) o si lo prefiere (Traducción española no oficial de la GPL) Al margen de las obligaciones legales que se derivan del uso de esta licencia rogamos sea respetada la referencia a su lugar de publicación original www.ciberdroide.com. y a su autor original Antonio Castro Snurmacher (Madrid 01/01/2000). |
![]() |
Esta ausencia de garantía se hace extensa a cualquier tipo de uso de este material y muy especialmente a las prácticas, ejercicios, y de ejemplos que encuentre en estas páginas. Deberá trabajar siempre salvo indicación contraria con un SO Linux y con un usario distinto de 'root' sin privilegios especiales. Como directorio de trabajo se procurará usar el directorio '/tmp' o algún otro que no contenga información valiosa. Tampoco se considera buena idea practicar en una máquina que contenga información valiosa. Todo esto son recomendaciones de prudencia. En cualquier caso si algo sale mal toda la responsabilidad será únicamente suya. En ningún caso podrá reclamar a nadie por daños y perjuicios derivados del uso de este material. Para más información lea el contenido de la licencia GPL y abstengase de hacer prácticas si no está dispuesto a asumir toda la responsabilidad.
|
Introducción
Muchas veces un administrador tiene dificultades para gestionar los escasos
recursos de una máquina porque los usuarios no los utilizan del modo más
racional.
En un sistema con muchos usuarios estos deben compartir los recursos de
modo racional, pero generalmente ocurre lo contrario. El no comprender
como funcionan las cosas y la avaricia de recursos puede conducir a conductas
absurdas.
Por ejemplo un usuario que tiene que compilar 500 programas sabe
que tendrá que esperar mucho. Si este usuario es suficientemente ignorante y
egoísta puede pensar que lanzando las 500 compilaciones simultáneamente
causará un retraso a los demás pero el terminará antes. Lo cierto es que
los recursos del sistema se desperdician en trabajos internos totalmente
inútiles para el usuario cuando el sistema está sobrecargado.
Tanto si se persigue compartir los recursos de forma razonable con los demás
usuarios, como si lo que se pretende es usar los recursos de todo el sistema
para sacar el mayor beneficio personal, se necesita comprender como funcionan
algunas cosas.
Esta lección será totalmente teórica porque para un usuario normal no resulta
prudente cierto tipo de experimentos que podrían provocar incomodidades o
incluso algunos problemas en el sistema. De todas formas si el sistema empieza
a tener problemas, si que es bueno tener los conocimientos suficientes para
averiguar si eso tiene que ver con algo que estemos haciendo nosotros.
Quizás podamos incluso advertir a algún compañero que trabaje en el mismo
equipo que el problema en el sistema tiene que ver con lo que el hace.
Limitar el uso de recursos
La cantidad de memoria es limitada pero existen distintos
limites que afectan al uso de la memoria. Para limitar el uso de ciertos
recursos existe un comando interno de la shell llamado 'ulimit'.
Por ejemplo 'ulimit -c
También se pueden limitar otras muchas cosas como la cantidad de CPU por
segundo, tamaño máximo de un fichero, máximo número de procesos, máximo
numero de ficheros abiertos, cantidad máxima de memoria virtual, etc...
Para ver las limitaciones con las que estamos trabajando haremos lo
siguiente:
Bueno en este ejemplo vemos que estamos en una sesión con muy pocas
limitaciones. Eso es señal de que el administrador confía en nosotros
y nos concede mucha libertad.
'ulimit' permite establecer dos clases de límites. Límites duros (solo
se pueden poner una vez y generalmente esto lo hace root) y límites blandos
que se pueden
cambiar varias veces pero no se permite sobrepasar los valores establecidos
en el límite duro. root establece estos límites en algún fichero de
configuración y los usuarios pueden tener en su $HOME/.bashrc alterar los
limites blandos. Para más información consulte la página man de 'ulimit'.
Multitarea
Volvamos al caso del usuario ignorante y egoísta del capítulo anterior. El
de las 500 compilaciones simultáneas. El
sistema necesita parar cada uno de los procesos que usan la CPU una vez que
han consumido su rodaja de tiempo para tomar el siguiente proceso en espera
de CPU.
Cuando un proceso necesita usar algo y en ese instante no está disponible
pasa a un estado de inactividad. Se dice que queda dormido.
Este cambio de un proceso a otro no es gratuito porque una vez parado
el proceso hay que anotar la situación en la cual ese proceso ha sido detenido
para luego poder volver a continuar exactamente en el mismo punto cuando le
vuelva a tocar y quizás parte del código o de los datos del proceso ya no
estén en memoria RAM (también la llamaremos indistintamente memoria física.
Ver más adelante paginación). Todo esto consume muchos
recursos y se puede alcanzar la situación en la cual el SO consume la mayor
parte del tiempo en esta gestión de procesos intercambiando datos entre
memoria y disco constantemente porque la memoria física no puede con todo
por el
contrario los procesos que son la parte realmente útil apenas dispondrán de
recursos. En esta situación el sistema se vuelve muy lento y los discos del
sistema tienen una actividad altísima. En realidad es una situación de
auténtico agobio para el sistema y su comportamiento se vuelve torpe. Es
como si el sistema actuara a la desesperada.
Por esa razón decimos que el usuario
del capítulo anterior además de ser egoísta es ignorante porque está
provocando un enorme retraso no solo a los demás usuarios (cosa que ya sabe)
sino también a si mismo.
Si alguna vez notamos que el sistema va muy lento y sospechamos la causa
tendremos que parar en primer
lugar el proceso que está provocando la sobrecarga. Si no sabemos cual es
o si se trata de un proceso que no es nuestro podemos investigar con el
comando 'top'. Tenga en cuenta que de este comando se sale con 'q'.
Este comando saca en cabecera un resumen de la situación general del
sistema y luego saca solo la información de los procesos que mayor
consumo de recursos están provocando en el sistema.
Tenga en cuenta que 'top' sirve para diagnosticar el uso de recursos y
permite identificar procesos que consumen demasiado pero en si mismo 'top'
también consume bastantes recursos. Por eso en situaciones de sobrecarga
del sistema conviene no abusar de su uso. 'top' refresca cada cierto tiempo
la información de la pantalla. Por defecto lo hace cada 5 segundos. Podemos
aumentar a 15 segundos. Para ello usaremos 'top d 15'. Esto consumirá menos
recursos y nos permitirá mirar con más tranquilidad la información de top.
Vamos a ver un ejemplo del uso de 'top' que corresponde a un sistema
con muy poca actividad.
Solo 5 usuarios. La CPU está ociosa 99.6% del tiempo, la cantidad de
memoria disponible es alta y no se está usando la swap.
USER es es usuario que arrancó el proceso,
%CPU es el porcentaje de tiempo de CPU usado por el proceso.
%MEM Porcentaje de memoria física usada por el proceso. Podría incluso
superar el 100%. Un valor alto puede delatar a un proceso como el causante
de los problemas de paginación (swaping) en el sistema.
Otro comando que nos da información sobre la carga del sistema es
'uptime'
Coincide con la primera linea de 'top'.
Los datos son hora actual tiempo transcurrido desde el arranque del
sistema, número de usuarios y las tres últimas cifras se
corresponden con promedios de carga en el último minuto, 5 últimos
minutos y 15 últimos minutos respectivamente.
Memoria virtual
Eso no significa que estemos burlando la seguridad del sistema ni que
seamos más listos que el administrador.
Si el administrador configura el sistema de forma paranoica para evitar
cualquier posible riesgo, los usuarios se verán sometidos a unas
restricciones bastante incómodas para trabajar.
Por eso lo normal es que el administrador asuma que los
usuarios autorizados utilizaran los recursos de forma razonable.
Para gestionar la memoria virtual lo que se hace es
recurrir al espacio de disco para ampliar este espacio. La memoria RAM
tiene una velocidad de acceso mucho más rápida que un disco duro y para
conseguir que todo funcione de forma transparente y de forma eficiente
se utilizan unas técnicas de segmentación y paginación que describiremos
a continuación.
Segmentación de la memoria
Las casillas son las posiciones de memoria y
a pesar de lo dicho existen posiciones de memoria compartidas. Por
ejemplo el código de un programa que se está ejecutando en varios
procesos será compartido en modo exclusivo de lectura por los procesos
que estén ejecutando ese programa. Es decir que si por ejemplo hay
varias personas ejecutando el editor 'vim' el código de ese programa
no estará repetido en memoria. Sería un desperdicio porque el código
es el mismo, no se puede alterar y la CPU se limita a leer la información
consistente en instrucciones para la CPU.
Todo este tipo de información
es lo que se denomina segmento de texto. Los proceso manejan otros
tipos de información distintas y para ello se organiza en segmentos de
distinto tipo. Por ejemplo hay segmentos de datos de solo lectura,
segmentos de datos de lectura escritura, segmentos de datos de pila,
segmentos datos de memoria compartida, segmentos de memoria dinámica.
No vamos a explicar estas cosas porque excede en mucho los propósitos
de este capítulo pero si queremos dejar una idea. Los procesos tienen
la memoria organizada en segmentos de distinto tipo. Gracias a esto
se consigue utilizar la memoria RAM de forma muy eficiente.
Pese a que el
código de un programa puede desaparecer de la RAM para dejar espacio a
otros programas, no será necesario salvar la información a disco. Si fuera
necesario volver a
cargarlo en RAM bastará acudir al fichero que contiene su código ejecutable.
Esto hace que los ficheros que contienen programas que se están ejecutando
no puedan ser borrados ni modificados por nadie, ni siquiera por root.
Copie el ejecutable 'top' en el directorio /tmp (Seguramente estará en
'bin/top' y sino deberiá ser capaz de encontrarlo). Ejecutelo como /tmp/top
y desde otra sesión intente borrar el fichero. Sencillamente le resultará
imposible pese a que es usted es dueño de esa copia.
Cuidado. Esto no es aplicable a los scripts de bash o a otros scripts porque
en realidad estos programas son datos que se ejecutan dentro de un programa
que los interpreta en lugar de hacerlo en la CPU.
Paginación
Se intenta reducir el número de lecturas y escrituras a disco. Para ello
se actúa en base a suposiciones de uso de la memoria.
Las páginas recientemente utilizadas tienen
mayor probabilidad de volver a ser usadas pronto que aquellas que ya
hace tiempo que no han sido accedidas. Intentaremos explicar porque.
Los programas se comportan
generalmente usando pequeñas partes de código durante la mayor parte
del tiempo mientras que otras partes se ejecutarán de forma muy ocasional.
Además los programas usan partes comunes de código que pertenecen a
librerías compartidas. El aprovechamiento de la RAM se consigue
manteniendo una sola copia de ese código compartido en memoria RAM.
Los accesos a estas páginas de memoria que contienen código pueden serán
para leer información. En el caso de datos de lectura escritura también
podrán ser accedidas para su modificación. Cuando una página ha sido modifica
se marca para
escribir su contenido en disco en el caso de que se necesite el espacio que
ocupa para otra página distinta.
El area de disco que se utiliza para ello se llama
swap (también se denomina memoria de intercambio) y un usuario normal no
puede modificarla aunque root si puede hacerlo para aumentarla o disminuirla
de tamaño por ejemplo.
La memoria virtual es la suma de la memoria física (RAM) más el swap
(area de intercambio) menos algunas páginas de reserva.
Las paginas de reserva están limpias de información para poder cargar
en ellas información nueva desde la swap cuando se necesita.
Al proceso de traer una página de la swap a memoria
física se le llama (swap in). Esto necesita un tiempo y normalmente el proceso
espera dormido. Al proceso de volcar una página de memoria física a swap
se le llama (swap out) y generalmente el proceso ya está dormido cuando esto
ocurre.
Cuando se agota la memoria física (RAM) se empezará a usar la swap.
Cuando la memoria virtual se agota el kernel empezará a matar procesos.
Dicho de otro modo un proceso que intenta usar memoria virtual cuando está
agotada terminará recibiendo una señal del kernel que provocará su muerte.
Utilidades para monitorizar el uso de memoria virtual
Ya vimos el uso de 'top'. Nos sirvió para introducir el tema. Se trata
de un comando realmente bueno para localizar los procesos responsables
del mayor consumo de CPU y memoria.
La información del estado de núcleo del sistema se encuentra en
/proc/ Ya comentamos en capítulos anteriores parte de su cometido
y también resulta muy útil para obtener información sobre el uso
de la memoria en el sistema.
También 'ps v' puede darnos información sobre el consumo de memoria
virtual de procesos. Con top solo salía la información de los procesos
que más consumen pero quizás necesitemos información de determinados
procesos. Por ejemplo para sacar la información de los procesos asociados
al nuestro terminal bastará usar 'ps v'. Si necesita precisar otras
condiciones consulte las opciones de ps en su página man.
Si solo deseamos saber cuanta memoria queda libre podemos usar 'free'.
Este comando también indica si se está usando la swap.
Con 'vmstat' podemos tener información del uso de memoria virtual, cpu, y
del consumo de entrada salida.
Con 'memstat' podemos ver el uso de memoria virtual de los procesos y de
las librerías compartidas.
Para mostrar solo la informacion del proceso 271 (en nuestro caso es
sendmail) haríamos lo siguiente:
Con esto vemos lo bien aprovechado que está el sistema ya que muchas de las
librerías aparecen compartidas con un montón de procesos que se están
ejecutando.
Hemos conseguido ver las librerías compartidas que esta usando y cuanto
ocupan en memoria pero la utilidad para saber usa o usará un ejecutable
es 'ldd'. Este comando no necesita que el programa se esté ejecutando
porque saca la información analizando el código del ejecutable.
Actuación con procesos conflictivos
De todas formas puede ocurrir que nos de pena matar a un proceso que se
había comportado razonablemente durante bastante tiempo y que está llevando
a cabo unas tareas que nos interesan.
Lo más suave que se puede hacer es bajarle la prioridad con 'renice'
por ejemplo 'renice 20 PID'. Bajar la prioridad de un proceso no perjudica
en nada al proceso cuando la CPU está ociosa por falta de trabajo. Si
el proceso continua consumiendo demasiados recursos y no podemos bajar
más su prioridad podemos pararlo sin matarlo. Para ello se envía al proceso
una señal SIGSTOP mediante 'kill -19' Para volver a arrancarlo podemos
hacerlo mandando una señal SIGCONT 'kill -18'
Test
Este curso no trata de la administración del sistema pero en este
capítulo se van a explicar algunas cosas que son materia de administración
del sistema pero que un usuario también debe conocer.
En un sistema se suele llamar recursos a ciertos elementos que no pueden
ser utilizados de forma ilimitada. Por ejemplo. 'yes' es un programa
que genera una salida infinita y no es buena idea redirigir su salida a
un fichero porque llenaremos nuestro espacio de disco. En algunos sistemas
el administrador establece un limite de espacio para cada usuario. Si no
fuera el caso llenaríamos el disco. Si la salida de 'yes' la redirigimos
a /dev/null no pasará nada. El número de ficheros que podemos tener
abiertos simultáneamente también tiene un límite. Lo mismo puede decirse
de otras muchas cosas.
$ ulimit -a
core file size (blocks) 0
data seg size (kbytes) unlimited
file size (blocks) unlimited
max locked memory (kbytes) unlimited
max memory size (kbytes) unlimited
open files 1024
pipe size (512 bytes) 8
stack size (kbytes) 8192
cpu time (seconds) unlimited
max user processes 256
virtual memory (kbytes) unlimited
Ya hemos hablado algo de ella cuando estudiamos los procesos. Queda claro
que en un sistema en el que se están ejecutando en apariencia varios
procesos simultáneamente lo que ocurre realmente es que el tiempo de la
CPU se va repartiendo entre los distintos procesos concediendo rápidamente
sucesivas rodajas de tiempo a cada uno en función de su prioridad y
de la política de reparto de ese tiempo. Esta política no nos interesa ahora.
Se supone que las cosas están pensadas para que el funcionamiento global de
todo el sistema sea el más adecuado.
$ top
12:17pm up 2:06, 5 users, load average: 0.00, 0.00, 0.00
55 processes: 54 sleeping, 1 running, 0 zombie, 0 stopped
CPU states: 0.0% user, 0.3% system, 0.0% nice, 99.6% idle
Mem: 258100K av, 93320K used, 164780K free, 66800K shrd, 7652K buff
Swap: 393552K av, 0K used, 393552K free 40744K cached
PID USER PRI NI SIZE RSS SHARE STAT LIB %CPU %MEM TIME COMMAND
1002 root 11 0 1312 1312 700 R 0 0.3 0.5 0:00 top
1 root 0 0 464 464 404 S 0 0.0 0.1 0:05 init
2 root 0 0 0 0 0 SW 0 0.0 0.0 0:00 kflushd
3 root 0 0 0 0 0 SW 0 0.0 0.0 0:00 kupdate
.... ..... .. .. ... ... ... .. .. ... ... .:.. ......
.... ..... .. .. ... ... ... .. .. ... ... .:.. ......
.... ..... .. .. ... ... ... .. .. ... ... .:.. ......
$ uptime
12:27pm up 2:16, 5 users, load average: 0.00, 0.00, 0.00
Vamos a explicar en primer lugar que significa eso de memoria virtual.
En muchos sistemas operativos el SO ofrece a los programas un espacio
de memoria superior al que realmente existe. La memoria física es la memoria
RAM. La CPU no puede hacer nada con los datos si antes no pasan a la RAM.
A pesar de esto un sistema con 64Mbytes de RAM puede ejecutar por ejemplo
un programa use variables con el doble de tamaño que el de la memoria RAM
disponible. Si
el programa accediera mucho y de forma aleatoria dentro de esta enorme
variable, se produciría una fuerte sobrecarga en el sistema. Si alguien
se pregunta
si una barbaridad como esta, puede hacerla un usuario normalito sin
privilegios especiales, la respuesta es, usuario normal si, pero
autorizado.
La memoria de un ordenador es una especie de enorme casillero.
Cada casilla contendrá cierta información pero un proceso no
puede acceder a toda la información del sistema. Cada casilla
tiene una dirección y cada proceso puede usar ciertas direcciones
para almacenar información. De esta forma se evita que un proceso
interfiera accidentalmente o intencionadamente a la información de
otro proceso distinto.
La información se organiza en bloques y los bloques que la CPU usa se
mantienen el mayor tiempo posible en RAM. A estos bloques de información
se les llama páginas.
$ cat /proc/meminfo
total: used: free: shared: buffers: cached:
Mem: 264294400 103956480 160337920 58118144 10465280 53153792
Swap: 402997248 0 402997248
MemTotal: 258100 kB
MemFree: 156580 kB
MemShared: 56756 kB
Buffers: 10220 kB
Cached: 51908 kB
SwapTotal: 393552 kB
SwapFree: 393552 kB
$ ps v
PID TTY STAT TIME MAJFL TRS DRS RSS %MEM COMMAND
301 tty3 S 0:00 600 420 1743 1300 0.5 -bash
1640 tty3 S 0:00 326 518 1829 1568 0.6 vi recursyst.dat
1665 tty3 S 0:00 194 420 1451 832 0.3 /bin/bash -c (ps v) >/tmp/vok2gkuv 2>&1
1666 tty3 R 0:00 240 55 2844 1176 0.4 ps v
$ free
total used free shared buffers cached
Mem: 258100 101668 156432 56800 10248 51988
-/+ buffers/cache: 39432 218668
Swap: 393552 0 393552
$ vmstat
procs memory swap io system cpu
r b w swpd free buff cache si so bi bo in cs us sy id
0 0 0 0 156404 10252 52000 0 0 2 1 141 132 1 0 98
$ memstat
44k: PID 1 (/sbin/init)
60k: PID 98 (/sbin/portmap)
80k: PID 156 (/sbin/syslogd)
468k: PID 158 (/sbin/klogd)
40k: PID 165 (/sbin/kerneld)
52k: PID 170 (/sbin/rpc.statd)
140k: /lib/libreadline.so.4.1 228
24k: /lib/libwrap.so.0.7.6 98 271
72k: /lib/ld-2.1.3.so 1 98 156 158 165 170 178 179 180 181 182 188 193 ...
864k: /lib/libc-2.1.3.so 1 98 156 158 165 170 178 179 180 181 182 188 19...
20k: /lib/libcrypt-2.1.3.so 228 292 295 306 307 308 309 310 311 461 966...
...: .........................
...: .........................
...: .........................
--------
3768092k
$ memstat | grep 271
264k: PID 271 (/usr/sbin/sendmail)
24k: /lib/libwrap.so.0.7.6 98 271
232k: /lib/libdb-2.1.3.so 156 193 206 271 292 295 306 307 308 309 310 31...
76k: /lib/libnsl-2.1.3.so 98 228 271 284 287 292 295 299 300 301 303 30...
40k: /lib/libnss_compat-2.1.3.so 228 271 284 287 292 295 299 300 301 30...
20k: /lib/libnss_db-2.1.3.so 156 193 206 271
32k: /lib/libnss_files-2.1.3.so 156 170 193 206 271 292 295 306 307 308...
48k: /lib/libresolv-2.1.3.so 271
308k: /usr/sbin/sendmail 271
$ ldd /usr/sbin/sendmail
libdb.so.3 => /lib/libdb.so.3 (0x40019000)
libwrap.so.0 => /lib/libwrap.so.0 (0x40054000)
libnsl.so.1 => /lib/libnsl.so.1 (0x4005b000)
libresolv.so.2 => /lib/libresolv.so.2 (0x40071000)
libc.so.6 => /lib/libc.so.6 (0x40081000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
Llegados a este punto conviene explicar que se puede hacer con un
proceso conflictivo. Evidentemente la solución más drástica es matarlo.
Para ello se usará primero un 'kill -15 PID'. La señal 15 es un SIGTERM
que permite al proceso parar ordenadamente pero si el proceso ignora esta
señal habrá que matarlo con un 'kill -9 PID'. La señal 9 es un SIGKILL que
no puede ser ignorado.
Puede comprobar sus conocimientos respondiendo el siguiente test.
Para ello seleccione las opciones que se ajusten a la verdad y luego
pulse el boton para ver el resultado de su test.
Si quiere hacernos llegar alguna duda, aclaración,
crítica, o contribución personal, utilice nuestro
formulario de contacto y nosotros le contestaremos