Introducción al desarrollo de prácticas de CAD en el entorno Unix/Linux
OBJETIVOS.
El objetivo de este documento es introducir al alumno
en el manejo de los equipos que se utilizarán en las prácticas
de CAD, acercándolo al uso del sistema operativo UNIX/LINUX bajo
el entorno X-Windows, así como a la programación en C bajo
este entorno utilizando las funciones de OpenGL, y la utilización
de un depurador de código.
FUNDAMENTOS
Para la realización de esta práctica
será necesario conocer algunos conceptos básicos sobre el
entorno X-Windows, las órdenes principales de UNIX/LINUX y la funcionalidad
que ofrecen el compilador y el depurador que utilizaremos.
El entorno
Para comenzar las sesiones nos conectaremos al sistema a través de los ordenadores de las aulas de los laboratorios. Para ello al conectar la máquina aparecerá en pantalla una ventana para identificarnos en el sistema, pidiéndonos nuestro USERNAME y PASSWORD.
Una vez introducidos correctamente, aparecerá una ventana con las distintas posibilidades de arranque, de las que elegiremos Linux. Después, seleccionamos Linux RedHat 7.0 (aunque las prácticas funcionarán en cualquier versión). Tras el proceso de arranque de Linux, tendremos que volver a identificarnos en el sistema. En ese momento estamos en disposición de lanzar el entorno X-Windows mediante la orden:
$ startx
El sistema de ventanas X está controlado por ratón y teclado, y la pantalla también contendrá un cursor de ratón en algún lugar. Se puede desplazar el ratón para cambiar la posición del cursor, que puede cambiar de aspecto al pasar por áreas diferentes de la pantalla.
Dependiendo del entorno con el que trabajemos, la apariencia puede variar de un sistema a otro. Sin embargo, la forma de trabajar es similar en cualquier caso. Si por defecto no nos aparece ninguna ventana en la que podamos introducir órdenes (lo que se conoce como -terminal x- ) debemos abrir uno para poder trabajar. En nuestro caso, podemos hacerlo de dos formas:
Moviendo el ratón y pulsando el botón izquierdo, puede "activar" o seleccionar una determinada ventana y las pulsaciones de teclas que efectúe serán enviadas a ella. Cuando una ventana está activa, su borde superior estará realzado en un color que contraste con los de las otras ventanas. Puede, entonces, ejecutar órdenes normales del sistema dentro de la ventana activa.
Se pueden crear, mover o eliminar ventanas según se necesite. El sistema de ventanas X contiene un salvapantallas automático que borra la pantalla cuando transcurre cierto tiempo sin actividad de teclado o de ratón. Se activará de nuevo la pantalla moviendo el ratón o pulsando alguna tecla.
Las múltiples ventanas de la pantalla pueden solaparse y se pueden cambiar su tamaño y posición para acomodarse a las necesidades del usuario. También se puede iconizar una ventana, lo que la empequeñece y la quita de en medio sin suprimirla. La ventana se iconiza moviendo el puntero del ratón a la pequeña caja de la esquina superior izquierda del borde de la ventana y presionando luego el botón izquierdo del ratón.
Podemos invocar al menú de ventanas pulsando el botón derecho del ratón en cualquier lugar del borde de la ventana. Aparecerá un menú que nos permitirá cerrar la ventana, hacer que la ventana ocupe la pantalla completa, moverla , cambiar su tamaño, iconizar, o mandar a otro escritorio (por defecto tenemos 4 que podemos seleccionar desde la barra inferior).
Para mover una ventana sobre la pantalla se coloca el puntero sobre el borde de la ventana, se presiona el botón izquierdo del ratón y se mantiene pulsado, mientras se mueve el ratón se moverá una representación de la ventana al rededor de la pantalla. Una vez que esté situada en la posición deseada, se libera el ratón y la ventana pasará a ocupar dicha posición.
La pulsación del botón izquierdo del ratón en el borde de la ventana también hace que la ventana pase a un primer plano, en caso de solapamiento de ventanas, exponiendo la ventana completa para su uso.
Para cambiar el tamaño de una ventana se utilizan unas pequeñas áreas que existen en las esquinas del borde de la ventana. Si se posiciona el puntero en una de estas esquinas y se presiona y mantiene presionado el botón izquierdo del ratón, se puede ampliar o estrechar la ventana antes de liberar el botón. La esquina opuesta permanece fija, de modo que no se puede cambiar el tamaño y mover la ventana en la misma operación.
Algunas ventanas pueden tener barras de deslizamiento horizontal o vertical. Esto permite mover el contenido de la ventana dentro sus bordes. Existen unas flechas que son sobre las que se pulsa para moverse dentro de la ventana línea a línea. Y si pulsamos en los extremos el movimiento será más rápido.
Cuando se termina de utilizar el sistema, debería
informarle que ha finalizado. A este proceso se le denomina despedida
o desconexión. Cuando se despide, el sistema Unix libera el
terminal para que pueda utilizarlo alguien más y evita que otra
persona sin privilegios pueda utilizarlo (como medida de seguridad). Para
ello, debemos primero salir de X-Windows pulsando la opción
Terminar
en el menú contextual que aparece al pulsar con el botón
derecho del ratón en el fondo de la pantalla (o desde el menú
principal de la barra inferior), y después, cuando nos encontremos
en modo texto, salirnos de nuestra sesión de trabajo con la orden
exit.
El Sistema Operativo LINUX
UNIX/LINUX es un sistema operativo multitarea y multiusuario, es decir, pueden existir varios procesos ejecutándose simultáneamente y pueden estar conectados varios usuarios a la vez.
Cada uno de estos usuarios tiene asociado una parte del disco del servidor como propia, en la que, en principio, solo tiene acceso su propietario. El espacio de que dispone cada usuario no es muy grande por lo que es aconsejable tener cuidado con el uso que hacemos de él, ya que si superamos el espacio asignado algunas aplicaciones no funcionarán correctamente.
Una vez que nos conectamos al sistema podemos interactuar con él introduciendo cualquier orden UNIX/LINUX en algunas de las ventanas de órdenes. Estas serán aquellas ventanas en las que aparezca el prompt del sistema que en este caso es el carácter $, indicando que espera que introduzcamos algún mandato.
El Shell es el programa que atiende a las órdenes introducidas desde el terminal y traduce dichas órdenes a instrucciones en la sintaxis interna del sistema. El Shell tiene dos funciones distintas: actúa como un intérprete de órdenes y además es un lenguaje de programación, es decir, se pueden agrupar un conjunto de comandos básicos para realizar una tarea mayor.
Generalmente, las órdenes son programas ejecutables independientes que el Shell encuentra y ejecuta en respuesta a instrucciones tecleadas. Los elementos constitutivos de una orden son:
- el nombre de la orden.- las opciones: modifican la orden.
- los argumentos: sobre los que va a actuar la orden en cuestión.
Cuando se reúnen en una línea todos
estos elementos (o parte de ellos), ésta recibe el nombre de
línea de orden, en la que es necesario que se sigan unas determinadas
reglas. Algunas de ellas son:
Generalmente, cuando se introduce una línea de orden incorrecta, la orden responde con un mensaje recordando la forma correcta.
El Shell proporciona herramientas que hacen fácil especificar múltiples nombres de ficheros como argumentos. Existen tres caracteres especiales, llamados comodines, que pueden sustituir a nombres de ficheros o a partes de ellos. Estos son:
Las órdenes más útiles que usaremos se resumen a continuación
La orden clear
Es una sencilla herramienta que borra la pantalla y visualiza el prompt
$ en la línea superior.
La orden who
Cuando se introduce esta orden, el sistema responde con la lista de usuarios que están conectados en ese momento. En esta lista se ofrece información de cada usuario, como: su identificador de presentación, el terminal que está utilizando y la fecha y hora en que se conectó. Si se usa la orden de la forma "who am i" la respuesta es la correspondiente a su propio terminal.
La orden passwd
Se utiliza para asignarnos una contraseña (password) al carecer de ella, o para cambiarla (el cambio periódico de contraseña es una buena medida de seguridad).
Al elegir una contraseña debe tener presente que ésta debe contener, generalmente, al menos un carácter no numérico, y tener como mínimo seis caracteres. Intente no olvidarla, ya que las contraseñas están cifradas y si no la recuerda, lo único que el administrador del sistema puede hacer es suprimir la contraseña actual y asignarle una nueva.
La orden ls
La orden ls proporciona varias opciones que controlan la visualización de la salida y que ficheros o directorios se seleccionan para visualizar. Algunas de ellas son:
-a : como ls no lista los nombres de todos los ficheros del directorio
(incluso los ficheros ocultos).
-l : visualiza la salida en formato largo, indicando para cada fichero
o directorio los privilegios, el número de vínculos, el propietario,
el grupo, la longitud en bytes, la fecha y hora en que fue modificado por
última vez y el nombre.
ls /udir/textos/pepe
Este argumento es lo que se denomina nombre de camino. Hay dos formas de especificar los nombres de camino (path):
b) nombre de camino relativo: el recorrido comienza en el directorio actual. Por ejemplo: ls dir1/hola , el directorio hola es un subdirectorio de dir1 que, a su vez, es un subdirectorio del directorio actual.
Para conocer nuestro directorio actual, utilizamos la orden pwd. Una vez ejecutada, muestra el nombre de camino del directorio actual.
Las órdenes mkdir y rmdir
Se pueden crear y eliminar directorios que ya no se necesiten. Para crear un nuevo directorio se utiliza la orden mkdir. Esta orden acepta un nombre de directorio como argumento y lo crea. El nuevo directorio estará vacío, no contiene ningún fichero (aunque automáticamente se han creado los directorios "." y "..".
Para borrar un directorio se utiliza la orden rmdir y como argumento el directorio a eliminar. Su ejecución fallará si el directorio no está vacío, y mostrará un mensaje de error. Recordemos que podemos suprimir un directorio y todo lo que contiene (lo cual es muy peligroso), incluyendo ficheros y directorios, utilizando la orden rm con la opción -r (por recursivo). Por ejemplo:
$ rm -r dir1
La orden cd
Para moverse por la jerarquía de directorios (y cambiar de directorio de trabajo) se utiliza la orden cd (cambiar directorio) dándole como argumento un directorio (o el nombre de camino de un directorio).
Existen dos directorios especiales que nos pueden ser útiles y que están presentes como subdirectorios de todos los directorios creados:
$ cd .. (dejando un espacio entre la orden y el argumento)
La orden rm
Se utiliza para borrar ficheros. Una vez que se ha borrado un fichero con esta orden es imposible recuperarlo. Necesita como argumento un nombre de fichero o una lista de nombres de ficheros (o caminos). Se puede interrumpir su ejecución presionando la tecla DEL o BREAK (esta operación de ruptura se puede utilizar para casi cualquier orden). Se dispone de las siguientes opciones:
-r : borra un directorio con todos los ficheros que contiene.
Se utiliza para crear una copia exacta de un fichero, necesita dos argumentos. El primer argumento es el nombre del fichero que se desea copiar, el segundo es el nuevo fichero a crear o un nombre de camino. Por ejemplo:
Esta orden también aceptará una lista de nombres de ficheros
como fuente y copiará todos estos ficheros al destino. Para ello
debe darse un directorio existente (cp no lo crea) y no un nombre de fichero
como destino, o se producirá un error. Para copiar el contenido
de un directorio a uno nuevo, se debe designar cada uno de los ficheros
que se desea copiar, explícitamente o utilizando un operador comodín.
Por ejemplo:
$ cp dir1/* dir2
Con esta orden podemos utilizar las siguientes opciones:
-r : si la fuente es un directorio, copia el directorio y todos sus
ficheros y subdirectorios. El destino debe ser también un directorio.
Esta orden sigue las mismas reglas de cp y se utiliza para mover el fichero fuente de un lugar a otro (destino) o para cambiar el nombre del fichero fuente. No crea una copia del fichero. Esta orden se utiliza también para renombrar un fichero o directorio. Utilizando la forma:
$ mv nombre-antiguo nombre-nuevo
La orden cat
Se utiliza para presentar el contenido de uno o más ficheros en la pantalla del terminal. Cuando se le da como argumento una lista de ficheros, los lee secuencialmente y los escribe en la salida estándar. Si no se indica ningún nombre de fichero cat leerá de la entrada estándar (el teclado). La operación se detiene pulsando <CTRL><D>.
Se puede usar cat con el operador de redirección de salida para crear un nuevo fichero e introducir texto en él. Por ejemplo:
$ cat > prueba
La orden more
Esta orden impide que la salida que se dirige a la pantalla se deslice fuera de ella demasiado rápido para verla. Su función es dividir la salida en trozos del tamaño de la pantalla. Visualiza una pantalla y hace una pausa mostrando el mensaje "--More--" al final. Cuando se presiona la barra de espacios, muestra la siguiente pantalla y así sucesivamente hasta el fin del fichero. Normalmente se utiliza como filtro, por ejemplo:
$ cat /etc/profile | more
Si se quiere detener el programa more antes de finalizar, se puede presionar la tecla q (quit) o la tecla DEL para volver inmediatamente al shell.
Además, more puede tener como argumentos una lista de ficheros. Por ejemplo:
$ more /etc/profile nota
Protección
Cada fichero y directorio tiene muchos atributos además de su nombre. Algunos de estos atributos pueden verse utilizando ls -l (comentada anteriormente). Ya que el Unix soporta múltiples usuarios, los ficheros pueden ser creados por usuarios individuales, quienes son "dueños" de los ficheros. Cada usuario pertenece además a un grupo (por ejemplo, un departamento) y puede compartir ficheros con los usuarios de su grupo.
Unix proporciona una forma de proteger los ficheros
de cada usuario, ya que le asigna a cada fichero o directorio unos permisos
o modos del fichero. Los permisos se representan por nueve bits, llamados
bits
de derechos, de forma que los tres primeros indican los permisos para
el propietario, los tres siguientes indican los permisos para el
grupo
al
que pertenece el fichero y los tres últimos indican los permisos
para los restantes usuarios del sistema. Cada grupo de tres bits
tiene la siguiente forma y significado:
Cuando se crea un fichero o directorio, el sistema le asigna unos permisos por defecto, sin embargo, Unix proporciona varias órdenes para manipular la propiedad y los permisos de éstos.
Se puede ceder la propiedad de un fichero con la orden chown (change owner), suponiendo que el fichero fuese suyo. Esta orden acepta un nombre de fichero o una lista de nombres de fichero como argumento, junto con el identificador del usuario (el último argumento) al que se desea ceder el fichero o ficheros. También se puede utilizar la orden chgrp para cambiar el grupo al que pertenece un fichero, suponiendo que el que lo hace es el propietario del fichero.
Para cambiar los permisos de un fichero de su propiedad se utiliza la orden chmod (change mode). Los tres grupos de permisos son conocidos como u (usuario), g (grupo) y o (otros). Una forma de utilizar esta orden es:
chmod [+,-] [r,w,x] fichero
Por ejemplo, supongamos que el fichero notas tiene el siguiente modo: rw-rw-rw-, si ejecutamos la siguiente orden:
$ chmod -w notas
el resultado será que se suprimen los permisos de escritura de notas, que tendrá ahora el siguiente modo: r--r--r--. Si ahora realizamos la misma operación pero con el argumento +w:
$ chmod +w notas
los volverá a restaurar. Por lo tanto, utilizaremos + para establecer permisos y - para suprimirlos. Se pueden cambiar más de uno de los tres permisos en la misma orden:
$ chmod -w+x notas
También se pueden efectuar cambios para cualquier clase individualmente, añadiendo una letra delante del - o del +. Por ejemplo:
$ chmod g-w notas
suprime el acceso de escritura al grupo.
Luego, la sintaxis de chmod es clase de usuario (u,g,o),
seguido de la acción a tomar (+,-), a continuación el permiso
a modificar (r,w,x) y por último, el fichero o directorio o una
lista de ellos.
El compilador
Para ejecutar el compilador deberíamos introducir la orden gcc con todos los argumentos necesarios para indicarle que biblioteca de funciones utilizar, que ficheros compilar y como enlazarlos para crear un ejecutable. Pero el sistema UNIX nos ofrece una macro modificable por el usuario para facilitarnos esta tarea: la orden make.
Para modificar la macro crearemos un fichero llamado
Makefile
el cual, al almacenarlo, hará que esa macro se adapte a nuestras
necesidades. Dentro de este fichero podemos utilizar diversas instrucciones
(que incluso forman un propio lenguaje) que se transformarán en
la orden de compilación make necesaria para crear nuestro
fichero ejecutable. Veamos algunas de estas instrucciones dentro de un
ejemplo:
##############################################################
# Practicas de CAD. 4 Ingenieria en Informatica.
# Makefile de ejemplo para la construccion de
las practicas.
##############################################################
# EJECUTABLE= nombre del fichero ejecutable que
queremos crear
#
EJECUTABLE= p1
# MODULOS= lista de nombres con los modulos que
se van a
# compilar. Cada uno se corresponde con un fichero
C
# Se le pone la extension .o para indicar el
fichero objeto
# generado por el compilador.
#
MODULOS= $(EJECUTABLE).o
################ NO MODIFICAR A PARTIR DE AQUI
########################
# CFLAGS= Parametros para el compilador de C
#
# -G (para que genere informacion para el depurador)
# -c (solo compilar cada modulo, no linkar)
# -I (indicamos directiorios donde buscar los
include)
CFLAGS= -g -c -DXWINDOWS -I/usr/X11R6/include
-I/usr/include
# LDFLAGS= Parametros para el linkador. (ld)
# le decimos que busque las librerias
# de X WINDOWS en el directorio indicado
LDFLAGS= -L/usr/X11R6/lib -L/usr/lib
# LIBS= librerias que vamos a linkar para hacer
nuestro programa
#
# en este caso necesitamos las siguientes:
#
# X11 manejo de X Windows
# c libreria estandard de C
# malloc para usar la funcion malloc
# m funciones matematicas (sin y cos, p.ej.)
LIBS= -lglut -lGLU -lGL
-lX11 -lXext -lXmu -lXi -lc -lm
# CC= orden de UNIX que invoca al compilador de
C
# (en este caso "gcc" llama al compilador de
C/C++ de GNU)
CC= gcc
# Las siguientes lineas le indican al programa
make que
# para construir el ejecutable debe compilar
primero los
# ficheros objeto que aun no esten compilados
y despues linkarlos
# todos juntos.
$(EJECUTABLE): $(MODULOS)
$(CC) -o$(EJECUTABLE) $(LDFLAGS) $(MODULOS) $(LIBS)
El depurador
Además del compilador gcc tenemos a nuestra disposición el depurador de código de dominio público gdb. Pero no lo utilizaremos como tal, sino que usaremos xxgdb que utiliza el entorno X-Windows como interface para gdb, facilitando así su uso. (puede ser que en la instalación que tengamos de Linux no se encuentre este depurador, o que además se encuentre otro, llamado ddd).
Esta aplicación ofrece información de realimentación visual y entrada mediante el ratón y el teclado para controlar la ejecución de un programa a través de puntos de ruptura, observar valores de variables y estructuras de datos, movernos por el código y obtener ayuda sobre órdenes del depurador gdb.
La sintaxis que utilizaremos de esta orden es la siguiente:
xxgdb [ ejecutable [ fichero_core ]]
donde ejecutable es un fichero binario producido por un compilador con la opción -g que produce información sobre la tabla de símbolos para el depurador gdb. Si no se especifica ningún fichero, dentro del propio depurador se podrá indicar el fichero a utilizar.
Si existe el fichero core (fichero que el sistema crea cuando se detiene la ejecución de un programa por algún error) en el directorio actual o especificamos un determinado fichero_core en la línea de órdenes, podemos utilizar mxgdb para examinar el estado del programa cuando se produjo el error.
Al ejecutar el depurador aparece en pantalla una
ventana dividida en las siguientes partes:
Ventana de archivo: Visualiza
información sobre el archivo visualizado en la ventana de código
fuente.
Ventana de código fuente:
Donde se visualiza el código fuente del fichero y en la que aparecen
una serie de botones asociados a las órdenes más usuales
de gdb.
Ventana de mensajes: Para visualizar
el estado de la ejecución y los mensajes de error de mxgdb.
Ventana de diálogo: Permite
introducir directamente por teclado órdenes gdb.
stack
Muestra una traza de las llamadas a funciones
realizadas.
Locals
Ver el contenido de las variables locales a la zona
de código seleccionada.
up
Nos movemos un nivel hacia arriba en la pila de
llamadas.
args
Visualiza los argumentos de la función en
la pila seleccionada.
down
Nos movemos un nivel hacia abajo en la pila de llamadas.
print *
Imprime el valor del objeto al que estemos apuntando
dentro de lo seleccionado.
print
Imprime el valor de la expresión seleccionada.
cont
Continua la ejecución desde donde se paró.
step
Ejecuta una linea de código, de forma que
si esa linea es una llamada a una función, pasamos a ejecutar paso
a paso su código.
finish
Continua la ejecución del programa hasta
que el procedimiento seleccionado (o el actual si no hemos seleccionado
nada) acaba.
next
Ejecuta una línea de código sin entrar
a ejecutar paso a paso las instrucciones de una función.
clear
Borra el punto de ruptura de la línea de
código o función seleccionada.
break
Detiene la ejecución del programa en la línea
seleccionada. Para definir un punto de ruptura, seleccione este
botón una vez colocado el cursor en la línea deseada.
undisplay
Elimina la visualización del valor de la
expresión seleccionada.
display
Visualiza el valor de la expresión seleccionada,
actualizan su valor cada vez que realizamos un paso en la ejecución.