PRÁ CTICA Introducció n a Linux DSO Objetivos El alumno: Requisitos 1. Tomará contacto real - desde el punto de vista de un usuario - con el sistema operativo Linux. 2. Se familiarizará y hará uso de los comandos del sistema operativo Linux mas comunes. 3. Manejará comandos básicos de Linux. 4. Comprenderá y pondrá en practica el proceso de elaboración de un programa en lenguaje C, haciendo uso de un editor para la generación de código fuente y del compilador gcc para la obtención del ejecutable. 1. Leer alguno de los manuales de C que hay disponibles en la web de la asignatura en el apartado Prácticas. 2. Conocer la cuenta y la clave para poder acceder a la maquina Linux en la que se desarrollaran las prácticas. Tareas a realizar Durante esta sesión, el alumno utilizará sus datos para conectarse a la maquina labatc.umh.es y se familiarizará con el compilador gcc. Duración 1 sesión Memoria: NO
1. Conexión al servidor En primer lugar, el alumno se conectará al servidor de las prácticas mediante Escritorio remoto. Para el acceso a una máquina remota Linux, serán necesarios varios datos: Login: Cuenta de usuario que proporciona el administrador del sistema Password : Contraseña de usuario que proporciona el administrador Host : matrix.umh.es:8016. 2. Cambio de Password A todos los alumnos se les ha dotado de un login y password. El primero no se puede cambiar, pero el segundo sí, y además, es conveniente cambiarlo periódicamente. Para ello se utiliza el comando passwd. Para conocer su funcionamiento véase la ayuda del comando mediante $man passwd Nota : Si os aparece algún mensaje indicando que hay algún problema, volver a insistir más tarde, es debido a que sólo puede estar un usuario cambiando el password a la vez. Una vez realizado el cambio de password, será el que debéis utilizar en próximos accesos al sistema. 3. Comandos Linux Probar el funcionamiento y opciones de algunos comandos útiles. Para obtener información sobre un comando utilizar el comando man comando. Ejecuta los siguientes comandos e indica cual es su función. Escribe sus opciones mas importantes. ls who nano Ejecutar, hacer un fichero de ejemplo y guardar con Ctrl-X.
top rm mv cp cat fichero sort exit logout
wc pwd Nota : Si alguna de estas aplicaciones no se pueden ejecutar, comunicárselo al profesor de prácticas.
4. Creación de directorios Para mantener ordenado el directorio HOME del alumno y favorecer al profesor las tutorías de prácticas, el alumno deberá de crear un directorio para cada práctica. Para crear los directorios ejecute: # cd # mkdir arco # cd arco # mkdir practica0 # mkdir practica1 # mkdir practica2 y así sucesivamente para todas las prácticas. Es conveniente crear, dentro de cada directorio de prácticas, un directorio de pruebas llamado tmp, en donde crear y guardar los ficheros de prueba que se vayan generando. Una vez que la práctica esté realizada completamente, hay que mover los ficheros al directorio superior mediante (cd..). 5. Preguntas Contesta a las siguientes preguntas: 1. Has tenido algún problema con el cambio de password?. Explica brevemente tu experiencia. 2. Por qué crees que hay que cambiar periódicamente el password?. 3. Por qué crees que el password no puede ser demasiado simple?. 4. En relación a nano, dónde crees tú que se ha guardado el fichero de ejemplo que has creado?.
6. Desarrollo de programas en lenguaje C en un entorno Linux La generación de un ejecutable requiere la intervención de dos programas, el compilador y el montador. En los sistemas Linux, estos programas son lla- mados usando un único comando llamado gcc (gnu C compiler). Este comando va llamando mediante fork() y exec() a otros comandos que el usuario nor- malmente nunca usa directamente y que realizan las fases de preprocesador de directivas con el prefijo #, compilación y montado del ejecutable con las libr- erías. Con las opciones del comando gcc controlamos cuales de estas fases van a tener lugar. Por defecto, si no ponemos opciones, el comando gcc va a realizar todas las fases sobre los ficheros pasados como argumentos. El fichero resultante que contiene el programa ejecutable tendrá el nombre a.out. $ gcc modulo1.c modulo2.c Este comando compila separadamente el código fuente contenido en los ficheros modulo1.c y modulo2.c produciendo los ficheros modulo1.o y modulo2.o, genera el ejecutable a.out montando ambos módulos más la librería del lenguaje C libc.a. Finalmente borra los ficheros objeto que ha generado en la fase anterior, por lo que no podremos ver más que el fichero a.out como resultado del comando. Podemos alterar el comportamiento de este comando mediante numerosas opciones. Algunas muy prácticas son: -c Solo se realiza la compilación. Suprime la fase de montaje, por lo que no se intenta generar ningún ejecutable. No se borran los ficheros objeto producido. Se usa para compilar uno o varios módulos sin tener todavía todos los módulos de código del programa completo, o para compilar cada módulo por separado. -o nombre Usa el nombre indicado para el fichero ejecutable en lugar de a.out. Es recomendable usar esta opción cuando se están generando varios programas en el mismo directorio para darles nombres distintos. El nombre no tiene que tener ninguna extensión predeterminada. Es más, en Unix, los ejecutables no suelen tener ninguna extensión. -g Incluye información sobre el programa para el depurador o debugger. Si queremos ejecutar el programa paso a paso examinando el contenido de las variables es necesaria esta opción. -O, -O2, -O3 Optimiza el código del programa para conseguir una ejecución más rápida. Las optimizaciones dependen del nivel indicado y se refieren a cosas tales como reordenación de instrucciones para adaptarlas a la arquitectura del procesador evitando dependencias entre instrucciones adyacentes o incrementando el número de aciertos en la cache del procesador. Su efecto solo suele notarse en programas con una gran cantidad de cálculos. Estas opciones son incompatibles con -g.
-Idirectorio Indica que también se busque en el directorio indicado para localizar los ficheros.h incluidos en el código C mediante las directivas #include "fichero.h" Mediante estas opciones podremos compilar todas las partes del programa generando los ficheros objetos correspondientes sin realizar el montado. Por ejemplo: $ gcc -c prog.c f1.c f2.c f3.c Este comando genera los ficheros prog.o, fl.o, f2.o y f3.o. Para realizar el montaje generando el fichero ejecutable se usa el mismo comando sobre los ficheros objeto. El comando gcc reconoce los ficheros.o y sabe que no les hace falta la fase de compilación sino la de montaje: $ gcc -o prog prog.o fl.o f2.o f3.o Incluso se pueden mezclar en un solo comando ficheros objeto ya compilados con ficheros de código fuente cuyo módulo objeto no ha sido compilado. En el siguiente ejemplo, el primer comando genera tres ficheros objeto y el segundo comando compila el fichero prog.c y lo monta con los ficheros.o que generó el primer comando, generando el fichero ejecutable: $ gcc -c f1.c f2.c f3.c $ gcc -o prog prog.c fl.o f2.o f3.o 7. Ejemplo de uso del compilador gcc Realiza este ejemplo en tu ordenador. Vamos a desarrollar un programa que imprima los parámetros que se le pasan en la línea de comando. Cuando se ejecuta un programa en Linux, puede recibir del proceso que lo crea, una serie de datos como parámetros. La forma de introducir parámetros en un programa escrito en C sobre el sistema operativo Linux es a través de los parámetros que se aceptan en la definición de la función main. int main(numero, argumentos) int numero; char *argumentos[]; En la mayor parte de la bibliografía se adopta argc como nombre estándar para el parámetro numero y argv, para el parámetro argumentos, con to que la definición anterior queda como: int main(argc, argv) int argc; char *argv[]; en donde argc es un entero que indica el numero de parámetros que se le han pasado al programa, y argv es un vector de punteros a cadenas de caracteres, en el que cada cadena de caracteres se corresponde con una de las palabras introducidas en la línea de comandos para invocar la ejecución de dicho programa.
La cantidad de elementos que tiene argv esta contenida en argc. Por ejemplo, si se introduce la siguiente línea de comandos para invocar la ejecución de un determinado programa: $ programa primero segundo tercero el parámetro argc toma el valor 4 mientras que el parámetro argv contendrá los siguientes datos: argv[0] "programa" argv[1] "primero" argv[2] "segundo" argv[3] "tercero" Como verificación del funcionamiento descrito se puede ejecutar el siguiente programa: argum.c
Podríamos pensar en desarrollar una función que dado un elemento de argv compruebe si es una opción (comenzará por un guión) y nos devuelva el nombre de la opción. El procedimiento param.h implementa esta función, comprobando si un parámetro es o no una opción, y devolviendo la opción sin guión. También vemos en la página siguiente las modificaciones pertinentes a realizar en el programa principal prog.c. param.h A continuación podemos compilar, montar y ejecutar.
$ gcc prog.c param.h -o prog $./prog pl -opc p2 programa: prog argumento: pl opcion: opc argumento: p2 8. Utilizacion del comando make make es una utilidad (existente también para otros sistemas) que permite la compilación rápida de los diversos módulos que componen un programa. Para comprobar el funcionamiento de make, realizar este ejemplo paso a paso. Para ello, podeis utilizar el fichero prueba.c que se encuentra en la web. Supongamos que tenemos un programa fuente llamado prueba.c, los pasos básicos de compilación son los siguientes $ls -l total 2 -rw-r-----1 mayo inf 344 Jul 11 11:28 prueba.c $gcc -c prueba.c $ls -l total 18 -rw-r-----1 mayo inf 1144 Jul 11 11:31 prueba.o Con este primer paso se ha realizado la fase de compilación, produciéndose un fichero objeto que se puede enlazar con las librerías externas que sea necesario.la segunda fase que debe realizarse es el enlazado (linkado). Normalmente se realiza con el mismo comando gcc, que a su vez hace use del comando ld. Es por ello que en muchas ocasiones, cuando se realiza en un solo paso la compilación y el linkado, el error lo produzca el comando ld y no el comando gcc. $gcc -o prueba prueba.o $ls -lt total 48 -rwxr-x--x 1 mayo inf 20529 Jul 11 11:32 prueba -rw-r-----1 mayo inf 1144 Jul 11 11:31 prueba.o Con esto ya se ha generado el fichero con el código ejecutable. $ls -l total 2 -rw-r-----1 mayo inf 344 Jul 11 11:28 prueba.c $gcc -o prueba prueba.c $ls -lt total 24 La opción -t del comando ls muestra los ficheros ordenados por fecha de ultima modificación. Como se puede comprobar, prueba es mas nuevo que prueba.o y este a su vez es mas nuevo que prueba.c.
El comando make hace uso de esta información para verificar si se necesita o no la compilación de un determinado fichero. En el ejemplo que estamos utilizando, la compilación sera necesaria únicamente si la fecha de ultima modificación del fichero prueba.c es posterior a la del fichero prueba. Utilizando la facilidad que proporciona el tener disponible la fecha de ultima modificación de un fichero, el comando make necesita que el usuario le proporcione los dos siguientes datos: 1. La dependencia que existe entre los ficheros. En el ejemplo se tiene que el fichero prueba depende del fichero prueba.c (es decir, prueba se obtiene a partir de un determinado tratamiento del fichero prueba.c). 2. Tratamiento que se necesita realizar para obtener los resultados deseados. Para el ejemplo anterior el tratamiento necesario es la compilación del fichero prueba.c, es decir, ejecutar el comando gcc -o prueba prueba.c La especificación de estos datos al comando make se realiza a traves de un fichero,que normalmente se denomina makefile (o también Makefile). En caso de que en un mismo directorio exista un fichero de nombre Makefile y otro de nombre makefile, el comando make eligira el fichero makefile. 8.1. Sintaxis básica del fichero makefile El fichero makefile debe de seguir una determinada sintaxis para que pueda ser interpretado por el comando make. En el fichero makefile deben existir especificados una serie de objetivos a conseguir, junto con los ficheros de los que depende y las instrucciones para conseguirlos. objetivo :lista de ficheros de los que depende tabulador orden para conseguir el objetivo. En el caso del ejemplo del fichero prueba el fichero makefile que se necesitara es: prueba:prueba.o gcc -o prueba prueba.o prueba.o :prueba.c De esta forma, al invocar el comando make, automáticamente leera el fichero makefile, y considerara que el objetivo deseado es obtener el fichero prueba. Dentro del makefile se pueden expresar otras acciones diferentes a la compilación,como por ejemplo. prueba:prueba.o gcc -o prueba prueba.o prueba.o :prueba.c En este makefile se define el objetivo limpiar, que no tiene ninguna dependencia y que cuando se solicite producirá el borrado de los ficheros *.o y del fichero prueba. Estos pasos se realizan normalmente con una única llamada al compilador.
9. Ejercicios gcc Accede a la ayuda en linea de gcc. Toma nota de los aspectos mas destacables. Creación de ejecutables El alumno deberá de escribir, compilar y probar el programa micat.c, cuyo fuente se encuentra más abajo, utilizando la orden gcc -o micat micat.c micat.c // Muestra de fichero por pantalla. #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> main(argc,argv) int argc; char *argv[]; { int fichero; char cadena; if((fichero=open(argv[1],o_rdonly))!=-1) { printf(" Fichero: %s\n",argv[1]); while(read(fichero,&cadena,1)) putchar(cadena); close(fichero); } }