Lab1: Observando el Comportamiento de Linux

Objetivos

Iniciar los laboratorios con un proyecto sencillo, donde se muestre como a través del sistema de archivos virtual /proc de Linux, podemos  inspeccionar  información interna del kernel. Se deberá generar la utilidad ksamp que muestra de diversas formas algún subconjunto de la información disponible en /proc.

Introducción

Podemos pensar el kernel de Linux como una colección de funciones y estructuras de datos. Estas estructuras de datos (o variables de kernel) contienen la visión del kernel respecto al estado del sistema, donde cada interrupción,  cada llamada al sistema, cada fallo de protección hacen que este estado cambie. Inspeccionando las variables del kernel podemos obtener información relevante a los procesos, interrupciones, dispositivos, sistemas de archivos, capacidades del hardware, etc.

Muchas variables conforman el estado del kernel y estas pueden estar alojadas de manera estática o dinámica en un stack frame de la memoria del kernel. Dado que el kernel de Linux es un programa "C" de código abierto,  es posible inspeccionar el código fuente y encontrar algunos ejemplos relevantes de estas variables como por ejemplo xtime definido en include/linux/sched.h que mantiene la hora del sistema, la estructura task_struct definida en include/linux/sched.h que contiene la descripción completa de un proceso, o los valores nr_threads y nr_running definidos en kernel/fork.c los cuales indican cuantos procesos existen y cuantos de estos están corriendo.

El código fuente de Linux lo podemos encontrar en el directorio /usr/src/linux de la mayoría de las distribuciones, pero también existen páginas donde podemos navegar el código de varias versiones de kernel, como por ejemplo Linux Cross Reference. También existen utilidades para navegación de código local como Source Navigator que está disponible en la distribución RedHat.

Tareas

Parte A

Buscar información acerca de la estructura del directorio /proc, y averiguar los siguientes datos Estos datos se tomaron del servidor de alumnos:
Type: GenuineIntel
Model: Pentium Pro
Uptime: 47d 0:10:14
UserTime: 7:35:14
SysTime: 9:42:43
IdleTime: 46d  6:52:16
TotalMem: 66682880
FreeMem: 3624960
Disk: 35702711
Context: 237097560
Processes: 748877

Parte B

Escriba una versión inicial del programa que inspeccione las variables del kernel a través del /proc e informe por stdout: También se pide incluir una cabecera donde se indique el nombre de la máquina y la fecha y hora actuales.

Parte C

Escriba una segunda versión del programa que imprima la misma información que la versión por defecto, pero en caso de invocarse con la opción -s, agrega la siguiente información:

Parte D

La tercera parte involucra imprimir todo lo de las versiones anteriores, pero cuando se invoca con la opción -l interval duration imprime además: Asi por ejemplo ksamp -l 2 100 mostrará el promedio de carga por 100 segundos tomando muestras  en intervalos de 2 segundos.

Cómo atacar los problemas

La página del manual de Linux man 5 proc contiene suficiente información al respecto, también se pueden ver artículos de la revista Linux Magazine "An Overview of the Proc Filesystem" o The Official Red Hat Linux Reference Guide en su capítulo "The /proc Filesystem". En general basta con realizar una búsqueda de "/proc filesystem" en cualquier buscador de la Web para encontrar información en cualquier idioma.

Una vez encontrados los archivos de /proc donde está la información, es necesario abrirlos, leer la información y cerrarlos. Esto se puede lograr con las funciones de la biblioteca "C" fopen, fgets (o fscanf) y fclose. Un ejemplo de uso sería el siguiente.
 
 
#include <stdio.h>

#define BUFFSIZE 256

int 
main(int argc, char *argv[])
{
        FILE *fd;
        char buffer[BUFFSIZE+1];

        fd = fopen("/proc/sys/kernel/hostname","r");
        fgets(buffer, BUFFSIZE+1, fd);
        printf("Hostname: %s\n",buffer);
        fclose(fd);
}

Para leer los argumentos de entrada e interpretarlos (proceso de parsing) hay que hacer uso de las variables int argc y char *argv[]. La primera indica cuantos argumentos se pasaron y argv es el arreglo de tamaño argc con cada uno de las cadenas de los argumentos. Notar que como el propio comando se incluye en la lista de argumentos una llamada ksamp -l 10 100 implica que al inicio del main se cumple {argc=4 & argv[]={"ksamp", "-l", "10", "100"}}. Probablemente se necesite convertir entre tipos de datos ASCII y enteros, la función atoi y las relacionadas pueden ser útiles.

Para obtener la fecha y hora que va en el encabezado del informe que brinda el programa, se pueden utilizar la funciones de la glibc (biblioteca de "C") gettimeofday y ctime,o bien leer el tiempo de inicio del sistema y sumarlo al  transcurrido para luego convertirlo a fecha.

Cuando se necesite realizar las muestra del promedio de carga de 1 minuto, puede ser útil la función sleep que duerme un proceso por un intervalo determinado de tiempo.
 

Qué se debe Entregar

Cómo se debe Entregar

Basta con generar un tar.gz con todo el código y el informe que deberá seguir el siguiente patrón regular
LabxGyy.tar.gz
donde x es el número de laboratorio y yy es el número de grupo con relleno de ceros a la izquierda para completar los 2 dígitos.

Todo el proyecto, es decir el código, documentación y makefile, deberán estar dentro de un directorio de la forma LabxGyy/.
El tarball deberá hacerse sobre éste directorio de la siguiente manera:

tar zcvf Lab1G02.tar.gz Lab1G02/
La fecha de entrega es el viernes 30 de Agosto de 2002, y se deberá env iar un email a so2002@famaf.unc.edu.ar con subject igual al nombre del tar.gz y el archivo aduntado.

Tips

No intenten hacer todo de golpe, vayan de a partes, y sobre todo discutan, analicen y trabajen en ideas de forma grupal. Una hora pensando en papel libremente suele ahorrar muchos problemas en el momento de codificar.

Para lograr un estilo de código razonable, basta con ser ordenados y leer un poco de código de personas con experiencia en programación. Aunque no existe un estilo de código, Linus Torvalds escribió un documento al respecto que se puede encontrar en varios formatos, aquí está en español y aquí en inglés.

Hemos visto que distintas versiones de kernel estructuan de manera distinta la forma de leer la cantidad de accesos a disco, tener esto en cuenta si se quiere que el programa sea portable entre diferentes versiones de kernel.

Utilicen debuggers de linea de comandos como gdb o interfaces gráficas para estos como ddd. También pueden realizar compilación condicional para hacer debugging de la siguente manera.
 
 
 
#define STDOUT 0
#define DEBUG
.
.
#ifdef DEBUG
fprintf(STDOUT,"DEBUG> argc: %d\n",argc);
#endif
.
.

Tareas Adicionales

Si les sobra tiempo pueden hacer las siguientes mejoras:

 

Nicolás Wolovick, 28 de Agosto de 2002