Programacion de Sistemas LINUX

18

description

Texto sobre Programacion de Sistemas LINUXpróximamente de venta en librerias.http://www.ukranio.com

Transcript of Programacion de Sistemas LINUX

Page 1: Programacion de Sistemas LINUX
Page 2: Programacion de Sistemas LINUX

2

Page 3: Programacion de Sistemas LINUX

3

Page 4: Programacion de Sistemas LINUX

4

Ukranio Coronilla Contreras

Profesor de la Escuela Superior de Cómputo

Instituto Politécnico Nacional – México

Programación de

sistemas LINUX

Guía de autoeducación

Page 5: Programacion de Sistemas LINUX

5

Page 6: Programacion de Sistemas LINUX

6

Agradecimientos

A la institución que ha coadyuvado en gran medida a

consolidar la mayor riqueza de nuestro México actual, a

saber: el capital humano técnicamente preparado. Porque

no tarde me di perfecta cuenta de que no es importante lo

que se sabe, sino, que se hace con lo que se sabe. Mi

mayor agradecimiento por permitirme ser parte en esta

noble labor, de formar profesionistas.

Al Instituto Politécnico Nacional, mi reconocimiento por

coadyuvar en la creación de esta obra. Y sirva también

como muestra de su compromiso social, el de poner la

técnica al servicio de la patria.

Page 7: Programacion de Sistemas LINUX

7

Page 8: Programacion de Sistemas LINUX

8

Índice

Prólogo ………………………………………………………………………...9

1 Introducción a UNIX ………………………………………………………… 11

2 Paso de argumentos …………………………………………………………. 15

3 PID, UID y variables de ambiente …………………………………………. 18

4 Creación de procesos ………………………………………………………... 19

5 Tuberías ………………………………………………………………………. 23

6 Memoria compartida ………………………………………………………... 26

7 Semáforos …………………………………………………………………..... 30

8 Manejo de archivos ………………………………………………………..… 35

9 Servidor de dominio Internet tipo UDP …………………………………… 39

10 Cliente Internet tipo UDP ………………………………………………...... 45

11 Señales y temporización ……………………………………………………… 48

12 Hilos (Threads) ……………………………………………………………….. 55

13 Servidor y Cliente TCP ………………………………………………….….. 60

14 RPC ……………………………………………………………………..……. 65

15 Mapas de memoria ……………………………………………………..……. 70

16 Gráficos en UNIX con X11…………………………………………………… 73

ANEXO A UNIX Instalación y comandos básicos…………………………….... 78

ANEXO B Soluciones…………………………………………………………….. 81

BIBLIOGRAFÍA…………………………………………………………………….... 88

Page 9: Programacion de Sistemas LINUX

9

Page 10: Programacion de Sistemas LINUX

10

Prólogo

El Sistema operativo UNIX® es uno de los más usados en los ámbitos académico y comercial

debido a su fiabilidad, potencia y flexibilidad. En los últimos años su popularidad se ha

extendido debido a las versiones LINUX para computadoras personales. LINUX se dispone

de manera gratuita junto con una gran cantidad de utilidades, herramientas de programación

y de redes, además de un código fuente abierto. Su alta seguridad ante los ataques por red y

virus lo hace un sistema operativo robusto y estable. Una de las razones más importantes

para el éxito de LINUX es su naturaleza de código fuente abierta. Debido a que permite la

constante mejora y eliminación de errores, por parte de programadores en todo el mundo.

Para los desarrolladores, la interfaz de llamadas al sistema que brinda LINUX, provee las

herramientas necesarias para la construcción de aplicaciones a bajo nivel, con excelente

desempeño y uso mínimo de recursos. Metas todas de cualquier ingeniero dedicado a la

programación de sistemas.

El lenguaje de desarrollo utilizado a lo largo del texto es C dada la estrecha relación que

guarda con la interfaz nativa de los sistemas UNIX®. A pesar de existir diversas variantes de

UNIX® se ha optado por trabajar con LINUX, aunque se han tratado de utilizar solo las

llamadas que son parte del estándar POSIX, lo cual garantiza su funcionamiento en

cualquiera de sus clones. Es muy recomendable conocer los comandos básicos de UNIX®

aunque se pueden ir aprendiendo sobre la marcha.

Este libro se ha estructurado para ser una guía en el proceso de auto enseñanza en la

programación de sistemas UNIX®. El único requisito son conocimientos previos de

programación en lenguaje C y de arquitectura de computadoras.

Se incluyen al inicio de cada capítulo programas en su forma más simple que ilustran el

concepto clave. Dichos programas se pueden ejecutar de inmediato para facilitar la

comprensión del “fenómeno”. Posteriormente se da una explicación sobre las líneas de

código utilizadas, así como una serie de preguntas y actividades de programación que

permiten al lector mejorar el entendimiento del mismo. La intención principal es que el lector

comprenda de manera rápida, a utilizar la interfaz que ofrece UNIX para comunicarse con el

hardware subyacente. De esta manera el programador puede ahorrar tiempo en la elaboración

de proyectos sobre esta plataforma.

Como es el caso de cualquier texto, este también es susceptible de presentar errores.

Agradezco de antemano su enorme ayuda al hacérmelo saber, por medio de la editorial o del

correo electrónico: [email protected]

Page 11: Programacion de Sistemas LINUX

11

Page 12: Programacion de Sistemas LINUX

12

1

Figura 1-1

Interfaz del SO

para el

programador y

el usuario.

Introducción a UNIX

El sistema operativo UNIX así como sus clones derivados (LINUX, Mac OS,

MINIX, IRIX, etc.) mantienen ciertas características que lo han hecho exitoso

respecto a otros sistemas operativos, tanto en el campo educativo como en el

comercial. Con el objeto de tener una mejor comprensión de las funciones que

se verán a lo largo del texto daremos una explicación general del modo en que

opera UNIX.

El sistema operativo es el software que se instala en un área de memoria dentro

de cualquier sistema de cómputo. Dicho sistema de cómputo debe contar al

menos con una unidad de procesamiento (CPU), pero también puede constar

de varias unidades de procesamiento que podrían trabajar en paralelo. El

sistema operativo se encarga de administrar los recursos del sistema de

cómputo así como permitir al usuario interactuar con el hardware mediante una

interfaz. Para los usuarios finales la interfaz puede ser gráfica (con ventanas y

un apuntador que se controla con el mouse) o en modo texto la cual consiste en

un intérprete de comandos (Shell). Para el programador la interfaz consiste en

un conjunto de funciones conocidas como llamadas al sistema. Estas pueden

incorporarse a los programas y permiten acceder a los recursos de hardware. El

propósito del presente texto es precisamente mostrar el uso de dichas llamadas

al sistema, y por consiguiente utilizar el hardware del sistema de cómputo en

las aplicaciones de software que desarrolle el programador. Cabe aclarar que

las llamadas al sistema aquí vistas son parte de un estándar definido por IEEE

conocido como POSIX (Portable Operating System Interface, la X viene de

UNIX). Un diagrama simple de esta interacción se muestra en la figura 1-1.

1

Page 13: Programacion de Sistemas LINUX

13

Figura 1-2

Sistema

multiusuario.

Como programador es muy importante que conozca y sepa usar la interfaz de

usuario para UNIX, es decir el conjunto de comandos que acepta el Shell y

permiten el manejo y administración del sistema. Una guía para este

aprendizaje se puede encontrar en el apéndice del texto.

UNIX es un sistema operativo multiusuario, lo cual significa que dos o más

usuarios pueden trabajar al mismo tiempo, y en sesiones distintas sobre un

mismo sistema de cómputo. Para este propósito se cuenta con una gran

cantidad de utilidades. Esta característica permite a varios programadores,

editar y compilar proyectos complejos sobre el mismo sistema de cómputo.

Un esquema típico se muestra en la figura 1-2 donde se tiene un sistema

compartido de varias terminales tontas (teclado y pantalla) conectadas a una

unidad de procesamiento central con varios procesadores.

También UNIX es un sistema operativo multiproceso, es decir que puede

ejecutar dos o más programas de manera simultánea. Por ejemplo podría

visualizarse un video mp4 y al mismo tiempo estarse reproduciendo una

canción almacenada en mp3. El multiprocesamiento se lleva a cabo mediante

la ejecución concurrente de los programas.

Dado que una CPU (Central Processing Unit) solo puede ejecutar una

operación aritmética en un instante dado. Para poder ejecutar dos programas,

es necesario que dichos programas compartan el CPU. De modo que cada

programa utiliza el CPU unos cuantos milisegundos (proceso en ejecución)

mientras el otro programa espera (proceso en estado de listo).

Como en general existen muchos procesos ejecutándose concurrentemente

(incluyendo las líneas de código del mismo sistema operativo), existe un

modulo del sistema operativo conocido como planificador (scheduler),

encargado de ceder el CPU a cada programa durante un intervalo constante de

tiempo conocido como cuanto. También determina quién es el siguiente

programa que puede usar el CPU en base a un algoritmo de calendarización.

Además de los estados de listo y en ejecución existe el estado de bloqueado.

Un proceso se encuentra en estado de bloqueado cuando no está haciendo uso

del procesador y además está esperando información proveniente de un

Page 14: Programacion de Sistemas LINUX

14

Figura 1-3

Estados de los

procesos y

transiciones

posibles.

dispositivo o de otro proceso. Por ejemplo si un proceso requiere leer un

archivo del disco duro, es necesario que espere mucho tiempo (la lectura del

disco duro ocupa varios milisegundos). En este caso se pone al proceso en

estado de bloqueado y el planificador le cede el CPU a cualquier otro proceso

que se encuentre en estado de listo. Al llegar los datos provenientes del disco

duro se interrumpe al sistema operativo y este cambia el estado del proceso de

bloqueado a listo. Un diagrama de estados de los procesos se muestra en la

figura 1-3, así como las transiciones posibles entre ellos.

El código más importante de un sistema operativo UNIX se conoce como

núcleo (kernel). Este es el encargado de permitir o impedir a los programas el

acceso al hardware. Cualquier programa que inicia su ejecución se encuentra

en el modo usuario. Si dicho programa desea manipular el hardware (por

ejemplo leer archivos del disco duro o leer la información proveniente de la

tarjeta de red) será necesario incluir la llamada al sistema correspondiente.

Esta llamada al sistema se ejecutará en modo kernel y es el código del kernel

quien permitirá o no, el acceso al hardware del que se trate. Este control es

necesario por la seguridad del sistema de cómputo, sobre todo considerando

que existen muchos usuarios dentro del mismo y la información de cada uno

de ellos, así como la exclusividad en el uso de los recursos (CPU, RAM,

archivos, dispositivos de E/S) es totalmente necesaria.

En la figura 1-4 podemos observar un gráfico del uso de CPU por parte de

procesos de usuario y del sistema operativo, así como los conceptos

anteriormente explicados.

Page 15: Programacion de Sistemas LINUX

15

Figura 1-4

Concurrencia de

procesos de

usuario y del

sistema

operativo.

La implementación de seguridad en los sistemas UNIX implica que exista un

control en el acceso de los usuarios al sistema. También la existencia de

permisos de acceso a los archivos, los cuales se dividen en tres categorías:

permisos de usuario, permisos de grupo y permisos para el resto de usuarios.

Estos atributos junto con algunos mas como tamaño, fecha de creación,

nombre, grupo, etc., se utilizan también para todos los dispositivos en el

sistema. Por esta razón podemos decir que en los sistemas UNIX todo se

representa como un archivo. Ganándose con esta generalización mayor

sencillez y una interfaz de llamadas al sistema pequeña en comparación con la

que ofrecen otros sistemas operativos.

La capacidad de multiprocesamiento tiene amplios beneficios para los

programadores de sistemas. Uno de ellos es que en lugar de tener un solo

programa grande, se pueden tener varios programas pequeños que interactúen

entre sí. Esto puede disminuir de manera drástica la complejidad de un

proyecto y por consiguiente hacerlo menos propenso a errores. También

fomenta la modularidad y flexibilidad así como la reutilización de código. En

consecuencia se puede elaborar código más robusto y estable.

Page 16: Programacion de Sistemas LINUX

16

1

Paso de argumentos

Introducción

Cuando se desarrolla un programa bajo un sistema operativo basado en UNIX®

como es el caso de LINUX, se debe tener en consideración que se estará en un

ambiente multiproceso. Esto significa que en un momento dado, se estará

ejecutando nuestro programa de manera concurrente (o paralela en el caso de

que el sistema de computo cuente con más de un procesador) con muchos otros

programas. Inclusive podrían estarse ejecutando varias instancias de nuestro

programa.

De modo que es importante para el programador que sus programas no

interfieran con otros programas en el momento de estar haciendo uso

simultáneo de un recurso. Dicho recurso puede ser memoria, algún archivo en

disco, o inclusive el teclado.

Ejemplo práctico

Programa 2-1

Imprime

argumentos y

opciones.

Introduzca en un archivo con ayuda de un editor como vi, pico, o alguno otro de

su preferencia, el programa 2-1 y guárdelo como programa2-1.c

2

#include <stdio.h>

#include <stdlib.h>

int main(int argc, char *argv[])

{

int tokens;

for(tokens = 0; tokens < argc; tokens++) {

if(argv[tokens][0] == '-')

printf("opción: %s\n", argv[tokens]+1);

else

printf("argumento %d: %s\n", tokens, argv[tokens]);

}

exit(0);

}

Page 17: Programacion de Sistemas LINUX

17

Pregunta 2-1

Posteriormente construya el programa ejecutable con la siguiente instrucción en

la línea de comandos:

gcc programa2-1.c –o programa2-1

gcc es el compilador más utilizado en los sistemas UNIX, la opción –o indica al

compilador que el nombre del archivo ejecutable será el que se especifica a

continuación (en este caso programa2-1). Se recomienda darle el mismo

nombre al ejecutable que al código fuente para evitar confusiones. Es también

común dejar al archivo ejecutable sin una extensión.

Quite la extensión .c al programa e intente compilar, posteriormente cambie la

extensión por otra de su agrado. ¿Qué sucede?

Se puede ver el manual del compilador gcc mediante el comando de ayuda man.

Solo debemos teclear en la línea de comandos:

man gcc

Este comando es muy útil para ver el manual de cualquier llamada al sistema,

función o comando.

Ejecute el programa anteponiendo “./” al nombre del programa ejecutable.

./programa2-1

Agregue otras palabras en la línea de comandos, estas se conocen como

argumentos del programa. Un argumento que inicia con el signo menos “-” se

conoce como opción del programa.

Como podrá observar nuestro programa detecta los argumentos y/o opciones

que se le envían en la línea de comandos.

Descripción del funcionamiento

En su forma general un programa que se elabora en LINUX puede tener el

siguiente prototipo para su función principal:

int main(int argc, char *argv[])

Esta función devuelve un entero y recibe dos argumentos, el número entero

que devuelve es capturado por el sistema operativo. De modo que el sistema

operativo puede saber cuál es el estado de terminación del programa.

Page 18: Programacion de Sistemas LINUX

18

Ejercicio 2-1

Ejercicio 2-2

Por convención un programa que termina de manera normal debe devolver un

cero, lo cual se logra con la instrucción:

exit(0);

En el caso de que exista un fallo se recomienda devolver un valor negativo.

El sistema operativo a través del intérprete de comandos (shell), puede enviarle

información a nuestro programa cuando inicia. Esto se logra con ayuda de los

parámetros en la función principal. El sistema operativo va a colocar en la

variable argc el número de parámetros que introduzca el usuario en la línea

de comandos. La variable argv almacena un arreglo de cadenas de caracteres,

donde cada una de las cadenas contiene un argumento, comenzando por el

nombre del programa el cual se almacena en argv[0], el siguiente

argumento en argv[1] y así sucesivamente. La última cadena en el arreglo

tendrá siempre un apuntador a NULL. Y como es normal en C, cada cadena va

a terminar con el carácter fin de cadena '\0'.

Suponga que no se dispone del argumento argc en la función principal, de

modo que no se conoce el numero de argumentos que el usuario introdujo en la

línea de comandos. Modifique el programa 2-1 para que realice el mismo

trabajo sin utilizar argc.

Modifique el programa 2-1 para que imprima también, el número de caracteres

que conforma a cada uno de los argumentos.

Para que un programa pueda ejecutarse en segundo plano concurrentemente

con otros, o para conectar la salida de un proceso con la entrada de otro, es

necesario pasarle al programa toda la información que necesite, a través de la

línea de comandos. Esta información se transmite en forma de opciones o con

argumentos. De otro modo tendrían que programarse menús interactivos, que

evitarían a otros procesos compartir el teclado y la pantalla.