99
Ing. en Automática y Electrónica Industrial ETSI de Bilbao Dept. Ingeniería de Sistemas y Automática Isidro Calvo y Fabián López ISBN: 978-84-693-3720-2

Labratorio trabajando con c

  • Upload
    soicrut

  • View
    241

  • Download
    15

Embed Size (px)

DESCRIPTION

Ejercicios de programacion en C

Citation preview

Page 1: Labratorio trabajando con c

Ing. en Automática y Electrónica Industrial

ETSI de Bilbao

Dept. Ingeniería de Sistemas y Automática

Isidro Calvo y Fabián López

ISBN: 978-84-693-3720-2

Page 2: Labratorio trabajando con c

Ejercicios de programación en

Departamento de Ingeniería de Sistemas y Automática

Page 3: Labratorio trabajando con c

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática

INDICE

1. Variables y operadores básicos 1

2. Sentencias condicionales 3

3. Sentencias repetitivas 6

4. Funciones 10

5. Arrays 14

6. Punteros 18

7. Cadenas 20

8. Estructuras 25

9. Ficheros 30

Page 4: Labratorio trabajando con c

Ejercicios programación en C - Variables y operadores básicos 1 de 33

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática UPV/EHU

1. Programa que pida un valor en pesetas y lo convierta en euros y otro programa que

lleve a cabo la operación inversa.

Nota 1 : La solución en euros deberá tener 2 decimales. Nota 2 : Utilizar #define para definir la relación entre euros y pesetas (1 euro = 166.386 pts)

2. Pedir un carácter por teclado y mostrar un mensaje que muestre el carácter

introducido así como su código ASCII tanto en formato decimal como hexadecimal. 3. Programa que pida la temperatura en grados Celsius y la convierta a grados

Fahrenheit (y viceversa) mostrando en pantalla un mensaje del tipo “xxx.xx grados Celsius son yyy.yy grados Fahrenheit”

4. Crear un programa que pida el radio de una circunferencia y que calcule la longitud

de la misma así como el área incluida dentro. 5. Crear un programa que calcule la fuerza de atracción gravitacional entre dos masas,

M1 y M2 situadas a una distancia R.

donde las masas se expresan en kilogramos y la distancia en metros y la constante de gravitación universal vale:

Nota: Utilizar #define para definir la constante G.

6. Escribir un programa que pregunte el año actual y la edad de una persona y calcule

la edad de esa persona en el año 2010. 7. Escribir un programa que calcule el número de billetes de 10.000, 5.000, 1,000, así

como de monedas de 500, 100, 25, 5 y 1 pesetas para desglosar una cantidad, C, de pesetas (menor de 2.147.483.647), de forma que se necesite la menor cantidad de monedas y billetes de cada tipo.

8. Crear un programa que pida un numero real y muestre la tabla de multiplicar

correspondiente a dicho número de tal manera que tanto los valores de los factores como del producto se presenten encolumnados y con una precisión de 2 dígitos.

5932 CF

=−

)(2*12 Nw

RMMGF =

2211 /*1067.6 KgmNwxG −=

Variables y operadores básicos

Page 5: Labratorio trabajando con c

Ejercicios programación en C - Variables y operadores básicos 2 de 33

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática UPV/EHU

Ejemplo: Programa que muestra la tabla de multiplicar de un número Escribe un número: 5 (Valor introducido por el usuario) TABLA DE MULTIPLICAR DEL NUMERO 5.00 5.00 * 1 = 5.00 5.00 * 2 = 10.00 ... 5.00 * 10 = 50.00

9. Mostrar en forma de tabla, el cuadrado y el cubo de los 5 primeros números enteros que siguen a uno introducido por teclado.

Los datos deben aparecer ajustados a la derecha siguiendo el siguiente formato: Numero Cuadrado Cubo ------ -------- ---- xxx xxxx xxxxxx Nota: Ejecutar el programa utilizando variables de tipo int e introduciendo el número base 30 y utilizando variables de tipo unsigned int e introduciendo el número base 40. ¿Qué sucede? ¿Cómo se puede explicar lo que sucede?

10. Crear un programa que muestre en pantalla el tamaño en bytes (8 caracteres) de las variables más frecuentes: char, int, short int, long int, float y double. (Nota: Para calcular el tamaño de una variable se puede usar el operador sizeof.)

11. Escribir un programa que tras preguntar el número de almacén asociado a un determinado tipo de pieza, la cantidad pedida de esa pieza y el precio por unidad, efectúe el cálculo del precio total de las piezas pedidas. El programa deberá escribir toda la información de la pieza en la pantalla, además del importe total del pedido.

12. Escribir un programa que lea el valor de un ángulo en radianes y muestre su valor en

grados, minutos y segundos 13. Programa que tras pedir por teclado un número lo multiplique por 4 y divida por 2

utilizando los operadores de rotación.

Page 6: Labratorio trabajando con c

Ejercicios programación en C – Sentencias repetitivas 3 de 33

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática UPV/EHU

1. Ejecutar el siguiente código fuente (Declarando valor_logico como entero y

luego declarándolo como float):

printf("Valores logicos de las siguientes expresiones\n");

valor_logico=(3>5);

printf(" (3 > 5) es %d\n", valor_logico);

valor_logico=(5 > 3);

printf(" (5 > 3) es %d\n", valor_logico);

valor_logico=(15 > 3*5);

printf(" (15 > 3*5) es %d\n", valor_logico);

valor_logico=!(5 == 3);

printf("!(5 == 3) es %d\n", valor_logico); Nota: No confundir el operador ‘==’ de comparación (para comprobar si dos

valores son iguales) con el operador ‘=’ de asignación que escribe un valor en una variable.

2. Escribir un programa que tras pedir 2 números por la pantalla muestra cuál es el

mayor número. (Hágase con la sentencia if y con el operador condicional: expresión ? valor1 : valor2 )

3. Leer tres números enteros y, si el primero de ellos es negativo, calcular el producto

de los tres, en caso contrario calcular la suma de ellos. 4. Crear un programa que calcule la caída de potencial producida por una resistencia

según la ley de Ohm (V = I * R) a partir de la resistencia y la intensidad que pasa a su través.

Nota: El programa no debe aceptar resistencias negativas, dado que no tienen

sentido físico, ni resistencias mayores que 1000Ω (requerimiento adicional del problema). En ambos casos el programa debe escribir un mensaje de error en pantalla diciendo que el valor de la resistencia está fuera de límites aceptables indicando la causa por la que dicho valor para la resistencia ha sido rechazado.

5. Sea un sistema de ecuaciones de la forma:

que puede resolverse usando las siguientes fórmulas:

fyexdcybxa

=+=+

bdaebfcex

−−

=bdaecdafy

−−

=

Sentencias condicionales

Page 7: Labratorio trabajando con c

Ejercicios programación en C – Sentencias repetitivas 4 de 33

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática UPV/EHU

Escribir un programa que lea los coeficientes (a, b, c, d, e, f) y resuelva el sistema. El programa deberá indicar los casos en los que el sistema de ecuaciones no tenga solución.

6. Escribir un programa que calcule las raíces, bien reales o imaginarias, de una

ecuación de segundo grado. El programa también debe ser capaz de operar con valores nulos para el coeficiente de orden dos (es decir, deberá de ser capaz de resolver ecuaciones de primer grado)

7. Dada la función U = f (x, y) tal que:

10 si x * y < 1 y2 si x * y ≥ 1

y dada la función V = f (x, y) tal que:

1 si x * y < 1 y2 si x * y ≥ 1

Escribir un programa que calcule los valores de las funciones U y V, una vez conocidas las coordenadas de un punto (x, y).

8. Escribir un programa que pida un año y diga si es bisiesto o no.

Nota: Un año es bisiesto si es múltiplo de 4 salvo el caso en que sea múltiplo de 100, que no es bisiesto, y no sea múltiplo de 400. Por ejemplo, el año 1900 no fue bisiesto, el 2000 sí y el 2100 no lo es.

9. La fecha de cualquier Domingo de Pascua se calcula de la siguiente forma:

Sea X el año para el que se quiere calcular la fecha.

Sea A el resto de la división de X entre 19

Sea B el resto de la división de X entre 4

Sea C el resto de la división de X entre 7

Sea D el resto de la división de (19 * A + 24) entre 30

Sea E el resto de la división de (2 * B + 4 * C + 6 * D + 5) entre 7 La fecha para el Domingo de Pascua es el día (22 + D + E) de Marzo (obsérvese que puede dar una fecha en mes de Abril) Escribir un programa que pida como entrada un año y saque por pantalla la fecha del Domingo de Pascua para ese año.

Page 8: Labratorio trabajando con c

Ejercicios programación en C – Sentencias repetitivas 5 de 33

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática UPV/EHU

10. Leer desde el teclado las coordenadas (x, y) de un punto y, mediante un menú, elegir una entre las siguientes opciones:

• Comprobar si el punto pertenece a una circunferencia de radio 10 y centro

(0,0) • Averiguar el cuadrante en el que se encuentra el punto. • Pasar las coordenadas cartesianas (x, y) a polares (r, arg).

11. Escribir un programa que permita efectuar el cálculo del área de un cuadrado, un

círculo o un triángulo equilátero según la opción seleccionada por el usuario a través de un menú.

• Crear una primera versión con la estructura de control if ... else • Y una segunda versión con la estructura de control switch... case...

12. Dada la longitud de una circunferencia, averiguar si dicha longitud corresponde, con

una determinada precisión, a una circunferencia de radio R. El programa deberá leer la longitud de la circunferencia, el radio y la precisión e indicará si es cierto o no que esa circunferencia tiene ese valor del radio.

13. Escribir un programa que pida dos caracteres por pantalla, los ordene alfabéticamente, y los imprima ordenados.

X

r arg

y

Page 9: Labratorio trabajando con c

Ejercicios programación en C – Sentencias repetitivas 6 de 33

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática UPV/EHU

1. Escribir un programa que escriba los números del 1 al 100 en líneas de 10

números. Después de 100 el programa debe escribir “Fin del programa” en una línea nueva.

2. Programa que calcule el valor de elevar un número real, a, a un exponente

entero, b, ab, multiplicando b veces el número a.

Nota: Mejorar el programa para que compruebe que el exponente es mayor que 0 y si no lo es dar un mensaje de error y pedir otro exponente.

3. Programa que calcule el factorial ( n! ) de un número entero positivo leído por

teclado.

Nota: Probar el programa con los números 6, 7, 8, 9... 4. Crear un programa que pida un numero real y muestre la tabla de multiplicar

correspondiente a dicho número de manera que tanto los valores de los factores como del producto se presenten encolumnados y con una precisión de 2 dígitos.

Ejemplo: Programa que muestra la tabla de multiplicar de un número Escribe un número: 5 (Valor introducido por el usuario) TABLA DE MULTIPLICAR DEL NUMERO 5.00 5.00 * 1 = 5.00

... 5.00 * 10 = 50.00

5. Escribir un programa que calcule el sumatorio:

21

1*)1(i

S

i

i∑=

donde S es un número entero positivo introducido por teclado.

Solución: El límite de esa expresión cuando S tiende a infinito es: -0.822467.

6. Programa que escriba en pantalla una tabla con cuadrados y cubos a partir de un número base hasta otro tope, ambos pedidos por teclado.

Nota: El programa utilizará sólo variables de tipo short int y deberá evitar errores de overflow.

Sentencias repetitivas

Page 10: Labratorio trabajando con c

Ejercicios programación en C – Sentencias repetitivas 7 de 33

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática UPV/EHU

Ejemplos de ejecución:

Tabla de cuadrados y cubos Escribe el número menor: 30 el número mayor: 34 Número Cuadrado Cubo ====== ======== ======== 30 900 27000 31 961 29791 32 1024 33 1089 34 1156

Tabla de cuadrados y cubos Escribe el número menor: 179 el número mayor: 183 Número Cuadrado Cubo ====== ======== ======== 179 32041 180 32400 181 182 183

Nota: en negrita se han indicado los valores introducidos por el usuario durante

la ejecución del programa. 7. Escribir un programa que ayude a aprender las tablas de multiplicar.

Para ello se irá pidiendo la tabla de multiplicar de un número (pedido por teclado con anterioridad) y comprobando que los valores introducidos son correctos. Si es así el programa escribirá “correcto” y en caso contrario deberá escribir “Lo siento, se ha equivocado. La respuesta correcta era número” La última línea mostrará el número de aciertos. A continuación se muestra un ejemplo de ejecución:

Programa para aprender las tablas de multiplicar Con qué número quieres practicar? 5 (Introducido por usuario)

5 * 1 = 5 (Introducido por el usuario) Valor correcto 5 * 2 = 11 (Introducido por el usuario) Lo siento se ha equivocado. La respuesta correcta era 10 ... Has acertado 9 veces de 10 números.

8. Hacer un programa que lea caracteres desde teclado hasta que lea 10 veces la letra

'a'. Por cada carácter leído que no sea una 'a' debe mostrar un mensaje indicándolo. Cuando lea las 10 letras 'a' el programa terminará.

9. Hacer un programa que lea caracteres desde teclado y vaya contando las vocales

que aparecen. El programa terminará cuando lea el carácter # y entonces mostrará un mensaje indicando cuántas vocales ha leído (cuántas de cada una de ellas).

10. Repetir el ejercicio leyendo caracteres hasta que se lea el carácter final de fichero

EOF (^Z) en lugar del carácter #.

Page 11: Labratorio trabajando con c

Ejercicios programación en C – Sentencias repetitivas 8 de 33

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática UPV/EHU

11. Programa que simule que se deja caer una pelota desde un edificio de X metros de altura (donde X se pide por teclado) mostrando en cada 0.1 segundos tanto la altura de la pelota como su velocidad.

Mostrar para cada instante de tiempo (cada 0.1 segundos) una línea del estilo: t=xx.x distancia al suelo=xx.xx metros velocidad=xx.xx m/s

12. Programa que calcule los nºs primos del 1 al 100 y los saque por pantalla.

13. Escribir un programa que primero pida por pantalla con cuántos números se va a

trabajar digamos que sean X) y luego pida los X números por pantalla.

Después de introducir los X números se mostrará un mensaje por pantalla indicando cuál es el mayor y menor valor introducido, así como el valor medio de todos los números introducidos.

14. Programa que pida números de cuatro cifras e indique si los números son

capicúas o no. El programa deberá ir pidiendo números hasta que el usuario introduce ‘-1’ por teclado. El número –1 indicará la finalización de la ejecución del programa.

Nota1: Un número capicúa es simétrico p.e. 1221 ó 25752 Nota2: Cuando el número no es de cuatro cifras se deberá mostrar un mensaje de

error por pantalla y se pedirá otro número menor que 10000. En caso de que el número sea menor de cuatro cifras se completará con ceros a la izquierda.

Nota3: El único número negativo que se aceptará es ‘-1’ que indicará la finalización del programa. Cualquier otro número negativo, se mostrará un mensaje de error.

15. Escribir un programa que calcule los números perfectos entre 1 y 10000.

Nota: Un número perfecto es aquél tal que la suma de sus divisores menos el propio número es el propio número.

Ejemplos:

6 ⇒ Divisores(6) = {1, 2, 3, 6} Suma = 1 + 2 + 3 + 6 – 6 = 6 ⇒ N.º Perfecto

10 ⇒ Divisores(10) = {1, 2, 5, 10} Suma = 1 + 2 + 5 + 10 – 10 ≠ 10 ⇒ No perfecto

Solución: 6, 28, 496, 8128

16. Escribir un programa que muestre el siguiente menú y que permita pasar

magnitudes de grados a radianes y de radianes a grados.

1. Pasar de grados a radianes

2. Pasar de radianes a grados

Page 12: Labratorio trabajando con c

Ejercicios programación en C – Sentencias repetitivas 9 de 33

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática UPV/EHU

3. Salir del programa

17. Escribir un programa que muestre una tabla con los caracteres ASCII mostrados en decimal, octal y hexadecimal. El programa mostrará la información con el siguiente formato:

Dec: xx Octal: xx Hex: xx Car: x El programa pedirá el primer carácter y los últimos caracteres que marcarán los límites de la tabla.

18. Escribir un programa que calcula el producto de los dígitos de un número entero

leído desde teclado.

Page 13: Labratorio trabajando con c

Ejercicios programación en C – Funciones 10 de 33

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática UPV/EHU

1. Escribir un programa que permita convertir grados Fahrenheit a Celsius y grados

Celsius a Fahrenheit. El programa presentará el siguiente menú:

1. Conversión de Celsius a Fahrenheit 2. Conversión de Fahrenheit a Celsius 0. Salir del programa.

Nota: Cada conversión se efectuará por medio de funciones, una que convertirá de grados Celsius a grados Fahrenheit y otra que haga justo lo contrario.

2. Realizar un programa que escriba todos los números enteros menores que un cierto

entero N y que a su vez sean múltiplos de dos números enteros A y B introducidos por teclado. Utilizar para ello una función que admita dos parámetros I, J e indique si I es múltiplo de J.

3. Escribir una función (con su correspondiente programa de prueba) que tome un

valor entero y devuelva el número con sus dígitos en reversa. Por ejemplo, dado el número 7631 la función deberá devolver 1367.

4. Escribir un programa que calcule masa radioactiva de carbono 14 que queda

después de t años. La fórmula que determina la masa restante en el tiempo t es:

donde: t es el tiempo en años Mt es la masa que permanece en el tiempo t m es la masa original h es la vida media en años Para el carbono 14 la vida media es de 5700 años; si la masa original es de 300 gramos, imprimir una tabla de la masa para t=500, 1000, 1500, 2000, ..., 10000 años. Se deberá utilizar un subprograma que permita evaluar la expresión (1/2)t/h para los diferentes valores de t. Nota: En TurboC existe la función double pow(double x, double y) que devuelve el valor xy.

5. Escribir una función que escriba tantas líneas en blanco como se haya pedido con

anterioridad al usuario en el programa principal.

ht

t mM ⎟⎠⎞

⎜⎝⎛=

21*

Funciones

Page 14: Labratorio trabajando con c

Ejercicios programación en C – Funciones 11 de 33

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática UPV/EHU

6. Escribir una función que tome el tiempo introducido por el usuario en el formato (horas:minutos:segundos) y lo convierta en segundos. El programa utilizará esta función para calcular la diferencia en segundos entre dos tiempos introducidos por el usuario.

7. Escribir un programa que calcule el número combinatorio

)!(!!

NMNM

NM

−=⎟

⎠⎞

⎜⎝⎛

Utilizar para ello una función que calcule el factorial de un número. Nota: La función para calcular el factorial de un número puede ser iterativa o recursiva. (Una función recursiva es una función que se llama a sí misma)

8. Escribir una función que calcule el factorial de un número y utilizar ésta en un programa que muestre el siguiente menú.

1. Factorial de un número 2. Cálculo de e 3. Cálculo de e^x 0. Salir

Nota 1: El cálculo de e debe hacerse con la siguiente expresión matemática:

...!3

1!2

1!1

11 ++++=e

Nota 2: xe puede calcularse mediante la fórmula:

...!3!2!1

132

++++=xxxe x

Nota 3: La precisión con la que se obtiene el resultado (e o xe ) depende del último valor añadido en la correspondiente serie.

9. El desarrollo en serie de Taylor de la función coseno es:

...!6

6

!4

4

!2

21)(cos +−+−=

xxxx donde el ángulo x viene expresado en radianes. Escribir un programa que calcule el valor aproximado de coseno (x), utilizando para ello los N primeros términos de la serie de Taylor. El número de términos N de la serie dependerá del valor del último, es decir, se añadirán términos a la serie hasta que el valor absoluto del último término añadido sea menor que 0.0005.

10. Se desea realizar un programa que permita hacer cálculos con polinomios de

segundo grado.

Page 15: Labratorio trabajando con c

Ejercicios programación en C – Funciones 12 de 33

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática UPV/EHU

El programa deberá presentar un menú en pantalla que facilite las siguientes opciones:

1. Leer un polinomio 2. Escribir un polinomio en su forma habitual 3. Evaluar un polinomio en un punto 4. Calcular el polinomio derivado 0. Salir

Se deberán utilizar los siguientes subprogramas:

LEER mediante este subprograma se introducen los números enteros que representan los coeficientes del polinomio.

ESCRIBIR es un subprograma que permite la escritura de un polinomio en la forma: Ax^2 + Bx + C

Ejemplos válidos: 5x^2+3x+5 5x^2-3x+5 5x^2-5

Ejemplos no válidos: 5x^2+ -3x+5 5x^2-0x+5

EVALUAR es un subprograma que retorna el valor de un polinomio para un número real que es introducido como parámetro.

DERIVAR es un subprograma que calcula el polinomio derivada de uno dado.

Nota: No está permitido el uso de variables globales.

11. Escribir un programa que realice la descomposición en factores primos de un

número introducido por teclado.

El programa deberá ir escribiendo la tabla de los factores primos, a medida que los va calculando, tal como muestra el ejemplo siguiente: Introduce un Nº entero -> 84 Nº | Factores primos -- | --------------- 84 | 2 42 | 2 21 | 3 7 | 7 1 |

Ayuda: Se deberá utilizar una función que nos diga si un número es primo o no.

12. Escribir un programa que cuente de un texto introducido por teclado:

• N.º de caracteres en blanco • N.º de dígitos • N.º de letras • N.º de líneas • N.º de otros caracteres

Page 16: Labratorio trabajando con c

Ejercicios programación en C – Funciones 13 de 33

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática UPV/EHU

Nota 1: Se deben crear sendas funciones para comprobar si un carácter es numérico o alfanumérico.

Nota 2: La función getchar() permite leer un carácter de teclado.

Nota 3: Para marcar el final de lectura del texto, el usuario deberá introducir un carácter que marque fin de fichero. Este carácter es ^D en Linux y ^Z en DOS / Windows.

13. Escribir un programa que lea dos números complejos y permita realizar con ellos las siguientes operaciones aritméticas: suma, resta, multiplicación y división

Nota 1: Se debe crear una función de permita leer un número complejo (su parte

real y su parte imaginaria). Nota 2: Se debe crear una función de permita pasar un número complejo en

forma parte real y parte imaginaria a módulo y argumento.

Se debe crear una función que permita pasar un número complejo en forma módulo y argumento a parte real y parte imaginaria.

Nota 3: La suma y resta de números complejos se obtiene sumando, o restando,

las partes reales y las partes complejas.

El producto de dos números complejos se obtiene multiplicando sus módulos y sumando sus argumentos.

El cociente de dos números complejos se obtiene dividiendo sus módulos y restando sus argumentos.

Page 17: Labratorio trabajando con c

Ejercicios programación en C - Arrays unidimensionales / multidimensionales 14 de 33

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática UPV/EHU

1. Escribir un programa que calcule el producto escalar y vectorial de dos vectores de

3 elementos cuyos valores se introducen por pantalla con el programa principal. 2. Realizar un programa que lea 20 números (entre el 1 y el 10) y muestre aquel o

aquellos que hayan aparecido más veces.

El programa preguntará si se quieren introducir los 20 números y en el caso en que la respuesta sea negativa rellenará el array con números aleatorios.

Nota: Para la generación de los números aleatorios, se deberán utilizar las

funciones rand, srand, time y la constantes definida RAND_MAX.

int rand (void): retorna un valor pseudoaleatorio entre 0 y el valor de la constante RAND_MAX.

3. Escribir un programa que emplee un argumento de la línea de comandos para

realizar una conversión decimal a hexadecimal; es decir, el número decimal se introducirá en la línea de comandos, siguiendo al nombre del programa.

Ej: C:> decihex 128 111 Deci= 128 Hex= 80 Deci= 111 Hex= 6F C:>

Nota 1: Al igual que en el ejemplo, el programa deberá ser capaz de convertir varios números en una llamada.

Nota 2: En caso de que el programa no reciba argumentos deberá devolver un mensaje de error.

Nota 3: La función atoi() convierte de cadenas a enteros.

4. Escribir un programa que pida un array de caracteres por pantalla e invierta el orden de los caracteres mostrándolo por pantalla. La inversión se hará sin utilizar otro array auxiliar.

5. Escribir un programa que calcule los números primos de 0 a 100 utilizando el

llamado método de la criba de Eratóstenes. Este método consiste en definir e inicializar con todos sus elementos a True un array de 100 elementos binarios e ir “tachando” (pasando a False) en pasadas sucesivas todos los múltiplos de los números primos (2, 3, 5, 7...) hasta obtener sólo los números primos. Es decir:

En el ejemplo en gris claro se señalan los múltiplos de 2, mientras que en gris

oscuro los múltiplos de 3 (que no son múltiplos de 2).

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ...

Arrays

Page 18: Labratorio trabajando con c

Ejercicios programación en C - Arrays unidimensionales / multidimensionales 15 de 33

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática UPV/EHU

Nota: Aumentar el límite superior y comparar la velocidad de ejecución con el

programa que calcula los números primos de Sentencias Repetitivas. 6. Realizar un programa que maneje un array de enteros a través de un menú con seis

opciones: 1.- Añadir un elemento al array (comprobando que el array no esté lleno) 2.- Eliminar un elemento del array (comprobando que el array no esté vacío) 3.- Listar el contenido del array 4.- Contar las apariciones de un número en el array 5.- Calcular la media y el máximo de los elementos del array 0.- Terminar 7. Escribir un programa que permita guardar las cuentas de un banco con sus

respectivos saldos. Para ello se guardará la información en un array paralelo (dos arrays unidimensionales, uno con los números de cuenta y otro los saldos) El programa deberá mantener las cuentas ordenadas, de menor a mayor, por número de cuenta para facilitar la búsqueda de una cuenta. El programa mostrará un menú con las siguientes opciones:

1.- Dar de alta una nueva cuenta (comprobando que el array no esté lleno y colocando la cuenta en la posición correspondiente dentro del array)

2.- Eliminar una cuenta (comprobando que el array no esté vacío y reposicionando las cuentas en el array)

3.- Mostrar una cuenta (mostrará el número de cuenta y el saldo correspondiente)

4.- Mostrar información (Número de cuentas dadas de alta y dinero total de todas ellas)

5.- Calcular el saldo medio, máximo y mínimo de las cuentas del array.

6.- Mostrar todas las cuentas (1 línea por cuenta con su número y su saldo).

0.- Terminar 8. Escribir un programa que rellene automáticamente una matriz 4x7 con la suma de

sus índices (Es decir, el elemento a11 = 1+1=2, a47 = 4+7=11). El programa mostrará la matriz resultante por pantalla.

9. Escribir un programa que pida una matriz de orden 3x3 y calcule y muestre por

pantalla su matriz traspuesta. 10. Crear un programa que permita reservar asientos de una sala de cine (8 filas x 20

columnas). La posición de cada asiento se definirá con una letra (A-H) para la fila y un número (1-20) para la columna. El programa deberá visualizar qué sitios están disponibles para que el cliente pueda decidir dónde sentarse. Antes de hacer la

Page 19: Labratorio trabajando con c

Ejercicios programación en C - Arrays unidimensionales / multidimensionales 16 de 33

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática UPV/EHU

reserva, el programa deberá comprobar que el asiento está libre, en caso contrario devolverá un mensaje de error.

Ej. de visualización:

1...5....0 1...5....0 _____________________

A ** A B **** *** B C ** **** ** **** C D *** * ** *** ** *** D E ***** **** ** ** E F ******** *** * ** F G ** **** **** ** G H ******* *** H

1...5....0 1...5....0

11. Un histograma es un gráfico que muestra la frecuencia con que aparecen en una

array dado valores dentro de subintervalos especificados de su intervalo. Por ejemplo, si un array unidimensional de enteros tiene elementos de tipo 0..9 y contiene los siguientes valores:

6 4 4 1 9 7 5 6 4 2 3 9 5 6 4

Su histograma sería:

4 * Frecuencia 3 * * 2 * * * *

1 * * * * * * * * Valor 0 1 2 3 4 5 6 7 8 9

Esto indica que los valores 0 y 8 no aparecen en el array, los valores 1, 2, 3 y 7 aparecen una vez, el valor 5 aparece dos veces, el valor 6 tres veces y el valor 4 aparece 4 veces. Escribir un programa que, tras leer las notas de los alumnos en una asignatura, genere y visualice el histograma de las notas redondeadas a valores enteros: 0, 1, 2,...10 Las notas leídas desde el teclado son valores de tipo real y el número de alumnos no es fijo aunque siempre es menor de 300. Nota: Para la realización del histograma se tendrán en cuenta las dimensiones de la pantalla no permitiéndose más de 22 filas, por tanto si la máxima frecuencia es mayor de 22 se deberá mostrar el histograma a escala.

12. Escribir un programa que rellene un array con números aleatorios de tipo float. El

programa, primero pedirá la cantidad de números aleatorios (máximo 50) y el rango de los números aleatorios (valor_min .. valor_max) y posteriormente mostrará todos los números aleatorios en el orden en que se han generado y finalmente en orden de menor a mayor.

Page 20: Labratorio trabajando con c

Ejercicios programación en C - Arrays unidimensionales / multidimensionales 17 de 33

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática UPV/EHU

Nota: Para la generación de los números aleatorios, se deberán utilizar las funciones rand, srand, time y la constantes definida RAND_MAX.

Variación 1: Repetir el programa generando números de tipo entero. Variación 2: Repetir el programa recibiendo los valores (cantidad de números, valor_min y valor_max) como argumentos de la línea de comandos.

13. Escribir un programa que calcule las suma de dos matrices A y B. El programa preguntará por las dimensiones de las matrices (dimensiones máximas

5 x 5) y a continuación, si se puede efectuar la suma, introducirá los elementos de ambas matrices y realizará la suma, mostrando finalmente el resultado.

14. Escribir un programa que calcule el producto de dos matrices A y B:

)()()( nxppxmnxmBxAC =

El programa leerá las dimensiones y los elementos de cada una de las matrices (dimensiones máximas 5 x 5) y a continuación, si se puede efectuar el producto, realizará lo calculará y mostrará el resultado en forma matricial. Nota: Los elementos de la matriz productos se obtienen de la siguiente forma:

∑=

=p

kkjikij bac

1*

Page 21: Labratorio trabajando con c

Ejercicios programación en C – Punteros 18 de 33

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática UPV/EHU

1. Escribir un programa que efectúe las siguientes operaciones.

a) Declarar las variables enteras largas value1 y value2 e inicializar value1 a 200000

b) Declarar la variable lPtr como apuntador a un objeto de tipo long.

c) Asignar la dirección de la variable value1 a la variable de apuntador lPtr.

d) Imprima el valor del objeto al que apunta lPtr.

e) Asígnele a la variable value2 el valor del objeto al que apunta lPtr.

f) Imprima el valor de value2.

g) Imprima la dirección de value1.

h) Imprima la dirección almacenada en lPtr. ¿Es igual el valor impreso que la dirección de value1?

Nota: %p muestra el valor de la variable como puntero

2. Crear un programa que calcule el valor de la intensidad que pasa a través de una resistencia dada, cuando se le aplica un voltaje determinado. El programa deberá estar dividido en las siguientes funciones:

• explicar_programa ()

Esta función mostrará una introducción del programa por la pantalla.

• obtener_valores ()

Esta función pedirá los valores para la resistencia y voltaje los cuales se pasarán por referencia al programa principal.

• calcular ()

Esta función efectuará el cálculo de la intensidad a partir de la resistencia y el voltaje aplicado.

• imprimir_respuesta ()

Esta función se encargará de mostrar un mensaje con los resultados.

3. Crear una función que intercambie el contenido de dos variables. Para ello se pasarán como parámetros las direcciones de las variables. Para probar la función escribir un programa que pida los datos por pantalla y muestre los contenidos después de llamar a la función.

4. Crear un programa que lea un número determinado (<100) de números reales

introducidos por teclado los almacene en un vector para mostrarlos luego en orden inverso.

Punteros

Page 22: Labratorio trabajando con c

Ejercicios programación en C – Punteros 19 de 33

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática UPV/EHU

Nota: Para recorrer el array se deberá usar aritmética de punteros en lugar de usar los índices del array.

5. Escribir una función que tras pedir un día de la semana (de 1 a 7) devuelva un puntero a cadena con el nombre del día. La función contendrá un array de apuntadores a cadena. Para probar la función se realizará un programa que pida un día de la semana en número y escriba el día de la semana en letra.

6. Escribir un programa que inicialice una cadena con una palabra cualquiera. El programa deberá obtener la dirección de la primera letra de la cadena. Una vez sabida esta dirección la mostrará por pantalla y realizará un bucle dando 3 oportunidades para que el usuario introduzca la dirección de la tercera letra de la cadena. En caso de no introducirla bien después de los 3 intentos, deberá sacar un mensaje indicando cuál es la dirección correcta.

Page 23: Labratorio trabajando con c

Ejercicios programación en C – Cadenas 20 de 33

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática UPV/EHU

1. 1. Escribir un programa que pida una cadena de caracteres (de longitud máxima 80

caracteres) y devuelva la cadena escrita al revés.

Ayuda: Para saber la longitud de la cadena se puede usar la función strlen() de la librería string.h.

2. Realizar un programa que lea una cadena de caracteres de una longitud menor de 80 y visualice los caracteres de la siguiente forma: primero, último, segundo, penúltimo, tercero, antepenúltimo, ...

3. Escribir una función que cambie las letras mayúsculas de una cadena a minúsculas

y viceversa. El programa principal pedirá una cadena por pantalla y se la pasará a dicha función esperando el resultado correcto que se mostrará por pantalla.

4. Escribir un programa que pida primero un carácter por teclado y que luego pida una

cadena. El programa calculará cuántos caracteres tiene la cadena hasta que lea el carácter introducido primero. Se deberá mostrar un mensaje en pantalla con el número de caracteres introducidos hasta llegar al carácter primero.

5. Escribir un programa que cuente el número de letras, dígitos y signos comunes de

puntuación de una cadena introducida por teclado.

Ayuda: Para saber si un carácter es numérico comparar que su valor es mayor que ‘0’ y menor que ‘9’, para saber si es alfabético comprobar que está entre ‘a’ y ‘z’ y considerar signos de puntuación el resto de los caracteres.

Nota: No considerar ni la ñ ni las letras acentuadas, ya que tienen códigos ASCII fuera del rango a-z

6. Realizar un programa que lea una cadena de caracteres con espacios en blanco

excesivos: elimine los espacios en blanco iniciales y finales y sólo deje uno entre cada dos palabras.

7. Crear un programa que pida una cadena de caracteres y devuelva otra sin signos de

puntuación ni números. La cadena devuelta debe tener todos los caracteres en mayúsculas.

Ayuda:

Se pueden usar las siguientes funciones estándar de C: ispunct(), islower(), gets() En TurboC también existe la función: strupr()

Código ASCII de ‘A’ 65

‘a’ 97

Cadenas

Page 24: Labratorio trabajando con c

Ejercicios programación en C – Cadenas 21 de 33

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática UPV/EHU

8. Crear un programa que pida por pantalla una cadena de 80 caracteres de longitud máxima y que calcule el número de veces que aparece otra cadena determinada, también pedida por teclado. Como salida el programa debe escribir un mensaje con el número de veces que aparece la palabra dada. Ayuda: Se pueden usar las funciones siguientes: strstr(), gets()

Escribir un programa que compruebe si una cadena pedida por teclado es un palíndromo o no. El programa no tendrá en cuenta si la palabra está escrita con mayúsculas o minúsculas.

Nota: Un palíndromo es una palabra que se lee igual al derecho que al revés. Ej: radar, 11011011, Ana, Otto

9. Escribir una función que compare 2 cadenas de caracteres devolviendo –1 si son iguales y 0 si son distintas.

10. Escribir un programa que pida dos cadenas (de longitud máxima 10 caracteres) y

muestre por pantalla el resultado de las siguientes operaciones: • Obtener la longitud de ambas cadenas • Comparar alfabéticamente ambas cadenas indicando si son iguales o bien cuál es la

mayor y cuál la menor. • Concatenar la segunda cadena al final de la primera, dejando un espacio blanco

entre ambas. • Copiar el contenido de la segunda cadena en la primera.

11. Escribir un programa con un menú que permita las siguientes opciones:

• Introducir una cadena de 40 caracteres de longitud máxima • Pasar a mayúsculas una cadena leída desde teclado. Para ello, escribir un

procedimiento que transforme caracteres de letras minúsculas a mayúsculas dejando como están las letras mayúsculas. Nota: Para llevar a cabo esta operación tener en cuenta la representación de los caracteres en ASCII. (‘A’ – 65, ‘a’ – 97)

• Pasar a minúsculas una cadena desde teclado. Para ello, escribir un

procedimiento que transforme caracteres de letras minúsculas a mayúsculas. Dejando como están las letras minúsculas.

• Dada la cadena de caracteres introducida en el punto 1, obtener otra, de forma

que la cadena resultante tenga sus caracteres a una distancia d (en el código ASCII) de los caracteres de la cadena original. Se considerará el alfabeto circular, es decir que tras la letra ‘z’ viene la letra ‘A’. La distancia d se introducirá desde teclado.

Page 25: Labratorio trabajando con c

Ejercicios programación en C – Cadenas 22 de 33

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática UPV/EHU

Nota: Antes de traducir la cadena se convertirá en una cadena de letras minúsculas, tal y como se hace en el punto 2.

• Salir del programa Nota común: En todos los casos si se intenta efectuar alguna operación antes de introducir la cadena se deberá mostrar un mensaje de error comunicando al usuario que la cadena está vacía.

12. Julio Cesar enviaba mensajes a sus legiones encriptando los mensajes mediante el

siguiente algoritmo:

Se escogía un número n como clave y se sumaba a cada letra en el alfabeto n posiciones. Así, si la clave escogida fuese 5, la ‘a’ pasaría a ser la ‘f’, mientras que la ‘f’ pasaría a ser la ‘k’. Para las últimas letras del abecedario se seguiría desde el principio. Así, con la clave de 5 la ‘y’ pasaría a ser la ‘d’. Se pide crear un programa que encripte una frase mediante este algoritmo.

13. Construir un programa que implemente una calculadora para números enteros: El programa pedirá primero la operación y luego los operandos. Las operaciones válidas serán: sumar, restar, multiplicar, dividir, salir. Si la operación es distinta de salir se pedirán los operandos y luego se mostrará el resultado. Si la orden es distinta de las anteriores se mostrará un error diciendo que se trata de una orden desconocida. Los operandos se recogerán como cadenas de caracteres y se convertirán en números enteros con la función atoi() Otras funciones que se pueden usar serán: gets() y strcmp().

14. Realizar un programa que permita calcular el NIF., conocido el DNI. de una

persona. El programa deberá leer, sobre una cadena de caracteres, el número del DNI. del

interesado. Seguidamente deberá averiguar si es un valor válido (todos los caracteres deben ser numéricos y representar un valor entre 100.000 y 99.999.999). Si la entrada es válida se deberá calcular el NIF. y representar el número completo con los puntos de millares y millones en las posiciones correspondientes, así como la letra del NIF al final de la cadena de caracteres separada por un espacio en blanco.

Page 26: Labratorio trabajando con c

Ejercicios programación en C – Cadenas 23 de 33

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática UPV/EHU

Cálculo de la letra del NIF: Se obtiene el resto de la división del número del DNI, entre 23, y en función del resultado se asigna un carácter según la siguiente tabla:

0 = ’T’ 7 = ’F’ 14 = ’Z’ 21 = ’K’ 1 = ’R’ 8 = ’P’ 15 = ’S’ 23 = ’E’ 2 = ’W’ 9 = ’D’ 16 = ’Q’ 3 = ’A’ 10 = ’X’ 17 = ’V’ 4 = ’G’ 11 = ’B’ 18 = ’H’ 5 = ’M 12 = ’N’ 19 = ’L’ 6 = ’Y 13 = ’J’ 20 = ’C’ 15. Tal vez el esquema de codificación más famoso de todos es el código Morse,

desarrollado por Samuel Morse en 1832 para el sistema telegráfico. El código Morse asigna una serie de puntos y rayas a cada letra del abecedario, a cada dígito y a algunos caracteres especiales (punto, coma, dos puntos y punto y coma). Ver tabla adjunta.

Escribir un programa que lea una frase y la codifique en código Morse. También escriba un programa que lea una frase en código Morse y la convierta en su equivalente en castellano. La separación entre letras se indicará mediante un espacio, mientras que la separación entre palabras se indicará mediante 3 espacios.

Carácter Código Carácter Código

A .- T -

B -.. U ..-

C -.-. V ...-

D -.. W .--

E . X -..-

F ..-. Y -.--

G --. Z --..

H ….

I .. Dígitos

J .--- 1 .----

K -.- 2 ..---

L .-.. 3 ...--

M -- 4 ....-

N -. 5 .....

O --- 6 -....

P .--. 7 --...

Q --.- 8 ---..

R .-. 9 ----.

S … 0 -----

Page 27: Labratorio trabajando con c

Ejercicios programación en C – Cadenas 24 de 33

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática UPV/EHU

16. Escribir un programa que permita al usuario realizar las siguientes operaciones:

1. Mostrar la fecha y hora por pantalla 2. Sacar por pantalla el contenido de un fichero ASCII. 3. Sacar por pantalla el contenido de un directorio 4. Limpiar la pantalla 5. Salir del programa

Para ello se hará uso de los comandos del sistema operativo: En Linux: date, cat, ls, clear En DOS: date, time, type, dir, cls

Page 28: Labratorio trabajando con c

Ejercicios programación en C - Estructuras y arrays de estructuras 25 de 33

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática UPV/EHU

1. Realizar un programa que permita realizar las operaciones básicas (sumar, restar,

multiplicar y dividir) números complejos. El programa deberá utilizar una variable que represente el número complejo en su forma polar, con sus dos componentes módulo y argumento.

2. Crear un programa que lea las siguientes variables proporcionadas desde teclado con el siguiente formato:

Posición de los caracteres Campo

1-8 Matricula 9-13 Cilindrada 14-16 Potencia 17-27 Modelo 28-38 Marca

Ej: BI6755CC1400 75FIESTA FORD

Y las introduzca en la correspondiente estructura. El programa deberá mostrar la estructura obtenida para comprobar que la conversión ha sido correcta. Nota: Construir una función que muestre por pantalla la estructura recibida. La estructura deberá pasarse por referencia para no malgastar espacio en la pila.

3. Disponemos de la información correspondiente a una jaula de un Zoo en una

variable de tipo registro con los siguientes campos:

Numero de jaula Entero Especie del animal Cadena de caracteres Nombre del animal Cadena de caracteres Edad Entero Peso Real Kilogramos de comida diaria Real Frecuencia de limpieza de jaula Entero (veces al día) Estado de la salud del animal Carácter (B, R, M -> Buena, Regular

o Mala) Descendencia Sí o No Peligroso Sí o No

Por motivos de transferencia de información a otros organismos necesitamos descomponer la información contenida en esa variable en dos variables diferentes: Una va a contener los datos de mantenimiento de la jaula del animal:

Estructuras

Page 29: Labratorio trabajando con c

Ejercicios programación en C - Estructuras y arrays de estructuras 26 de 33

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática UPV/EHU

Numero de jaula Entero Kilogramos de comida diaria Real Frecuencia de limpieza de jaula Entero (veces al día) Peligroso Sí o No

Otra, los datos del animal:

Especie del animal Cadena de caracteres Nombre del animal Cadena de caracteres Edad Entero Peso Real Estado de la salud del animal Carácter (B, R, M -> Buena, Regular o

Mala) Descendencia Sí o No

Escribir un programa que lea una variable de información global y la descompongan en dos variables, una de información de mantenimiento y otra de información del animal y visualice ambas variables. Nota: Dentro de los subprogramas que considere necesarios deberá haber uno, llamado descomponer, que tome un registro y lo descomponga en dos.

4. Crear un programa que permita introducir cierta información relativa a los vuelos diarios que parten de un aeropuerto en un array formado por registros. Cada registro contendrá la siguiente información sobre el vuelo correspondiente:

a) Número de vuelo (No tiene por qué coincidir con el índice del array) b) Hora de partida (En dos campos):

1. Hora: 0..23 2. Minutos: 0..59

c) Origen del vuelo: Cadena de caracteres d) Destino del vuelo: Cadena de caracteres e) Número de pasajeros: Entero

Una vez introducidos los datos de todos los vuelos se preguntará si se desea obtener información de algún vuelo. En caso de que el usuario responda afirmativamente se pedirá el número de vuelo. El programa buscará el vuelo en al array y accederá a la información que contiene a partir de su número de vuelo, mostrando por pantalla todos sus datos.

El programa se ejecutará repetitivamente hasta que el usuario indique que no desea obtener más información de ningún vuelo.

Nota: Se deben diseñar las funciones que visualicen un vuelo, busquen un vuelo en el array, introduzcan la información de un vuelo en el array, etc...

5. Una compañía utiliza aviones para fumigar las cosechas contra una gran variedad de

plagas. Lo que la compañía cobra a los granjeros depende de contra qué es lo que

Page 30: Labratorio trabajando con c

Ejercicios programación en C - Estructuras y arrays de estructuras 27 de 33

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática UPV/EHU

desean fumigar, y de cuantos m2 de tierra quieren que se fumiguen de acuerdo con la siguiente tabla:

Tipo1: Fumigación contra malas hierbas 18 € / m2

Tipo2: Fumigación contra langostas 36 € / m2

Tipo3: Fumigación contra gusanos 54 € / m2

Tipo4: Fumigación contra todo lo anterior 90 € / m2

Además, si el área a fumigar es mayor que 10.000 m2, el granjero goza de un descuento del 7%.

Se trata de escribir un programa que lea los datos de un conjunto de granjeros y al final calcule, para cada uno de ellos, la factura correspondiente. De cada granjero se tendrá la siguiente información:

Nombre Tipo de fumigación (código entre 1 y 4) Número de m2 que se van a fumigar. Fecha de factura (a su vez, con los componentes: minutos, hora, día, mes y año)

Nota: Los componentes de la fecha de la factura deben ser leídos en el sistema (utilizando funciones de la librería time.h)

6. Escriba un programa que genere un array de 50 números enteros entre 1 y 1000 de forma aleatoria. A continuación, partiendo de ese array genere otro array de 50 estructuras tal que cada estructuras tenga un campo para el número y otro (cadena de caracteres) para indicar si dicho número es primo o no. Por ejemplo:

203 672 23 319 426 1 ........ 862 373 273 203

203 672 23 319 426 1 ........ 862 373 273 203

NO NO SI NO NO SI ........ NO SI NO NO

Finalmente muestre en pantalla la suma de todos los números del array que sean primos.

7. Escribir un programa que cree una base de datos temporal sobre el personal de

agentes de policía. La base de datos almacenará cuatro datos acerca de cada persona:

• Nombre (Array de caracteres) • Apellido (Array de caracteres) • Código (Entero) • Categoría (Entero: 0: detective, 1: ayudante, 2: director)

Page 31: Labratorio trabajando con c

Ejercicios programación en C - Estructuras y arrays de estructuras 28 de 33

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática UPV/EHU

El programa preguntará acerca de cuántos datos se añadirán a la base de datos y luego mostrará los datos de todos los agentes introducidos.

8. Programa que implemente una agenda.

Se guardarán los siguientes datos por persona: • Nombre: Máximo 15 caracteres. • Apellidos: Máximo 35 caracteres. • Sobrenombre: Máximo 10 caracteres. • Teléfono: Máximo 10 caracteres. • Fecha de nacimiento: 8 caracteres (con el formato dd/mm/aa, pudiendo

ser espacios los dígitos del año

Se creará un menú con las siguientes opciones: 1. Alta de una nueva persona a la agenda con los correspondientes datos. 2. Eliminar a una persona de la agenda. 3. Búsqueda de un nombre en particular (La búsqueda se hará por

sobrenombre) 4. Listado de todas las personas empezando por la primera introducida (Para

pasar a la siguiente se deberá pulsar intro). 5. Guardar agenda en disco. 0. Salir

9. Se deberá escribir un programa que permita introducir y consultar la tabla periódica

de los elementos químicos. Para ello, se construirá un menú con las siguientes opciones: 1. Introducir elementos de la tabla periódica 2. Listar todos los elementos de tabla periódica 3. Mostrar elemento de la tabla periódica por número

atómico 4. Mostrar elemento de la tabla periódica por símbolo 5. Salir

La opción 1 preguntará cuántos elementos de la tabla periódica se quieren introducir e irá preguntando sucesivamente por ellos. Evidentemente, no es necesario rellenar el array con todos los elementos de la tabla periódica. La opción 2 listará la información acerca de todos los elementos químicos introducidos ordenados por número atómico. La opción 3 pedirá el número atómico del elemento que se quiere consultar y mostrará por pantalla la información correspondiente a dicho elemento.

Page 32: Labratorio trabajando con c

Ejercicios programación en C - Estructuras y arrays de estructuras 29 de 33

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática UPV/EHU

La opción 4 pedirá el símbolo del elemento que se quiere consultar y mostrará por pantalla la información correspondiente a dicho elemento. Se guardará la siguiente información sobre cada elemento. 1. Símbolo del elemento 2. Nombre completo 3. Peso Atómico

El número atómico vendrá indicado por la posición en el array de elementos que representa la tabla periódica, y por tanto no será necesario almacenar esta información en el registro correspondiente. Nota: Se puede mejorar el programa añadiendo una opción que permita guardar los datos en un fichero de disco.

Page 33: Labratorio trabajando con c

Ejercicios programación en C – Ficheros 30 de 33

A. Fabián López Valencia Informática Industrial Dpto. Ingeniería de Sistemas y Automática

1. Crear un programa que abra un fichero y escriba números enteros y otro programa calcule el valor máximo (si hay varios basta con uno de ello) y la media de todos los números contenidos en el fichero anterior:

Ayuda: Utilícense las funciones fprintf y fscanf.

2. Leer completamente un fichero de texto, carácter a carácter (o en cantidades mayores, para que sea más rápido). El programa debe contar las vocales, los caracteres alfabéticos y los dígitos que hay en el fichero.

3. Crear un programa que abra un fichero y escriba en él dos cadenas, cada una acabada con el carácter de nueva línea y otro programa que lea la segunda cadena escrita en el mismo fichero. Comprobar que el fichero existe y visualizar su contenido con un editor de textos (p.e. el Block de Notas de Windows)

Nota: Escribir una cadena con espacios intercalados. Ayuda: Utilícense las funciones fputs y fgets. Consultar la ayuda.

4. Escribir un programa que tome caracteres de teclado y, de uno en uno, los escriba en un

fichero cuyo nombre es previamente pedido por pantalla. 5. Escribir un programa que saque por pantalla el contenido de un fichero cuyo nombre es

pedido por pantalla.

Nota: El nombre del fichero debe proporcionarse mediante la línea de argumentos al llamar al fichero. Es decir: C:> MostrFic fichero.txt

6. Escribir un programa que comprueba que un fichero de código contiene el mismo número

de “{“ que de “}” en su código. En caso de que no sea así el programa mostrará un mensaje indicando que el número de “{“ es distinto que el número de “}”.

7. Escribir un programa que use dos ficheros: uno de lectura y otro de escritura. El programa

leerá los caracteres de un fichero, y tras una operación de cambio de mayúsculas a minúsculas y viceversa, escogida por el usuario, los escribirá en un segundo fichero.

8. Escribir el código necesario en el programa de la agenda de la lección de estructuras

(Ejercicio 8) para que se añadan cuatro opciones más. De esta forma, el menú quedará de la siguiente manera:

Ficheros

Page 34: Labratorio trabajando con c

Ejercicios programación en C – Ficheros 31 de 33

A. Fabián López Valencia Informática Industrial Dpto. Ingeniería de Sistemas y Automática

1. Alta de una nueva persona a la agenda con los correspondientes datos.

2. Eliminar a una persona de la agenda.

3. Búsqueda de un nombre en particular (La búsqueda se hará por sobrenombre)

4. Listado de todas las personas empezando por la primera introducida (Para pasar a la siguiente se deberá pulsar intro).

5. Leer la agenda desde el disco (formato binario). El nombre del fichero será agenda.bin.

6. Guardar la agenda en el disco (formato binario). El nombre del fichero será agenda.bin.

7. Guardar la agenda en el disco para imprimir (en modo texto). El nombre del fichero será agenda.txt.

8. Guardar en un fichero de texto información de las personas que cumplen años en un determinado mes (cuyo número se leerá desde teclado). El nombre del fichero será el número del mes seguido de la extensión txt. Se guardará la fecha de nacimiento, el sobrenombre y el teléfono, ocupando la información de cada persona una línea. La información deberá estar encolumnada debajo de una cabecera, tal como se muestra en el ejemplo:

FECHA DE NACIMIENTO SOBRENOMBRE TELEFONO 13/12/85 Koldo 946478383 09/12/90 Ana 653765432

0. Salir 9. Escribir un programa que permita visualizar el contenido de un fichero pasado desde la

línea de comando en formatos hexadecimal y carácter, siguiendo el esquema del ejemplo:

C:> Ver Fichero.txt 48 6F 6C 61 2C 20 73 6F-79 20 75 6E 61 20 63 61 Hola, soy una ca 64 65 6E 61 0D 0A 59 20-79 6F 20 6F 74 72 61 0D dena..Y yo otra. 0A EB 11 80 3E AF D2 00-74 03 E8 B2 E8 E8 FC E6 ....>...t....... Ayuda: Para averiguar si un carácter se puede imprimir existe la función isprint().

10. Escribir un programa que pida el nombre de un fichero y lo borre de disco.

Ayuda: Usar la función remove().

11. Crear una base de datos almacenada en un fichero para personal universitario. Cada elemento de la base de datos constará de 3 campos: Nombre, apellido y edad. Adicionalmente, será necesario crear otro programa que lea los registros de la base de datos y los muestre secuencialmente por pantalla.

12. Escribir un programa que haga una conversión de un tipo de formato de fichero a otro. El

formato de partida será el siguiente:

Page 35: Labratorio trabajando con c

Ejercicios programación en C – Ficheros 32 de 33

A. Fabián López Valencia Informática Industrial Dpto. Ingeniería de Sistemas y Automática

Posición de los caracteres Campo

1-9 Matricula 9-14 Cilindrada 14-17 Potencia 17-28 Modelo 28-38 Marca

Ej: BI6755CC1400 75FIESTA FORD y el formato de destino serán las correspondientes estructuras, es decir: Matrícula 8 caracteres Cilindrada entero Potencia entero Modelo 10 caracteres Marca 10 caracteres

Nota: Los datos de partida pueden introducirse con el programa 2.

13. Una entidad bancaria posee en un fichero la siguiente información para un conjunto de personas:

• Nombre. • Número de cuenta. • Crédito solicitado.

El programa funcionará basándose en un menú con las siguientes operaciones:

1.- Añadir un crédito al archivo 2.- Visualizar en pantalla la información correspondiente al crédito mayor 3.- Copiará en otro fichero el conjunto de personas que hayan solicitado un crédito

superior a cierta cantidad establecida por el banco (la cual deberá ser introducida por teclado).

4.- Visualizar todo el contenido de un archivo 14. Se necesita construir un programa que a partir de la fórmula de un compuesto químico

(supuestamente puro) y su peso en gramos obtenga la cantidad que dicho compuesto contiene de cada uno de los elementos químicos que lo forman.

Para ello se escribirán dos programas:

El primero de ellos escribirá en disco la tabla periódica. Por cada elemento de la tabla periódica se guardará la siguiente información:

• Símbolo del elemento

Page 36: Labratorio trabajando con c

Ejercicios programación en C – Ficheros 33 de 33

A. Fabián López Valencia Informática Industrial Dpto. Ingeniería de Sistemas y Automática

• Nombre completo • Peso Atómico

El número atómico de cada elemento vendrá representado por su posición en la tabla periódica.

El segundo de ellos leerá el fichero con la tabla periódica introducido con el programa anterior y presentará un menú con las siguientes opciones.

1. Listar tabla periódica 2. Mostrar elemento de la tabla periódica 3. Obtener la composición de un compuesto químico 0. Salir

La opción 1 mostrará un listado con todos los elementos de la tabla periódica, parando la ejecución cuando se llene una pantalla para permitir verlos todos.

La opción 2 pedirá el símbolo de un elemento químico, lo buscará en la tabla periódica y mostrará toda la información relativa. Es decir, su número atómico, el símbolo del mismo, su nombre completo y su peso atómico.

La opción 3 permitirá introducir la fórmula del compuesto químico. Para ello irá preguntará primero por el número de átomos constitutivos y luego por el nombre y número de átomos del elemento en el compuesto. Posteriormente, se pedirá el peso en gramos del compuesto a analizar. Una vez calculada con la tabla periódica, a partir de las proporciones obtenidas de la fórmula, la cantidad en gramos de cada uno de los elementos se mostrará el informe con la composición en gramos del compuesto.

Finalmente, la opción 4 permite salir del programa.

Page 37: Labratorio trabajando con c

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática UPV/EHU

Introducción a Tornado

Informática Industrial (Ingeniería en Electrónica y Automática)

Departamento de Ingeniería de Sistemas y Automática

Page 38: Labratorio trabajando con c

Isidro Calvo y A. Fabián López Informática Industrial Dpto. de Ingeniería de Sistemas y Automática UPV/EHU

INDICE

1. Introducción .............................................................................................................. 1

2. Ejecutar Tornado ...................................................................................................... 2

3. Crear un proyecto descargable para VxWorks ......................................................... 3

4. Añadir código fuente al proyecto ............................................................................. 6

5. Generar el módulo objeto del proyecto .................................................................... 7

6. Descargar el módulo objeto del proyecto en el Simulador del target de VxWorks . 9

7. Ejecutar el módulo objeto desde la Shell de Tornado ............................................ 11

7.1 Algunos comandos de la Shell de Tornado .................................................... 14

8. Explorador de objetos del sistema: Browser .......................................................... 17

9. Descripción de una sesión de depuración ............................................................... 19

10. Crear una imagen de VxWorks configurada o customizada .................................. 22

10.1 Añadir código fuente al proyecto ................................................................... 24

10.2 Configurar los componentes de VxWorks...................................................... 24

11. Examinar la actividad de las tareas......................................................................... 27

Page 39: Labratorio trabajando con c

Introducción a Tornado 1 de 30

Isidro Calvo y A. Fabián López Informática Industrial Dpto. de Ingeniería de Sistemas y Automática UPV/EHU

2. Introducción

Tornado es un entorno integrado para el desarrollo cruzado de software. Proporciona un modo muy eficiente para el desarrollo de aplicaciones, o módulos objeto, de tiempo real embebidas, con mínima intrusión en el target. Tornado incluye los siguientes elementos:

• VxWorks, un sistema operativo de tiempo real de alto rendimiento.

• Herramientas de desarrollo de aplicaciones (compiladores y programas asociados).

• Un entorno integrado de desarrollo (IDE) que facilita la gestión y el desarrollo de proyectos, estableciendo y gestionando la comunicación entre el host y el target y la ejecución, depuración y monitorización de aplicaciones VxWorks.

Las características principales del IDE son:

• Editor de código fuente integrado.

• Facilidades para la gestión de proyectos.

• Compiladores integrados de C y C++ y make.

• Browser: colección de visualizaciones que ayudan a monitorizar el target.

• CrossWind: depurador gráfico a nivel de código.

• WindSh: shell de comandos en lenguaje C que controla el target.

• VxSim: versión integrada de un simulador de target VxWorks.

• Versión integrada de WindView, el analizador lógico para el target.

• Opciones de configuración para muchas de las características, incluyendo integración de editor alternativo y de herramientas de gestión de la configuración (CM), así como todo el GUI de Tornado.

El entorno de Tornado está diseñado para suministrar el rango completo de características, independientemente de si los recursos del target son muchos o pocos. Las principales capacidades se ejecutan principalmente en un host con acceso compartido a una tabla de símbolos del sistema target remoto. La Figura muestra las relaciones entre los principales componentes interactivos de Tornado en el host y en el sistema target. La comunicación entre las herramientas del host y VxWorks está arbitrada por el server target y el target agent.

Editor

Project

Debugger

Browser

Shell

WindView

TargetServer

TargetAgent

VxWorksAgent

Simulator

Application

VxWorks

Target Agent

TARGET SYSTEM HOST SYSTEM

Page 40: Labratorio trabajando con c

Introducción a Tornado 2 de 30

Isidro Calvo y A. Fabián López Informática Industrial Dpto. de Ingeniería de Sistemas y Automática UPV/EHU

Con Tornado, el ciclo entre el desarrollo de una idea y la posibilidad de observar su implementación es extremadamente corto. Se pueden efectuar descargas incrementales del código objeto de los módulos que son enlazadas dinámicamente con el sistema operativo VxWorks en un tiempo mínimo.

El lenguaje de macros, llamado Tcl, proporciona un medio consistente para la configuración de todo el entorno de las herramientas de Tornado.

3. Ejecutar Tornado Para ejecutar Tornado basta con hacer clic sobre el icono de la aplicación, mediante la secuencia: botón Inicio > Programas > Tornado2 > Tornado

NOTA: Se puede mover las barras de herramientas y situarlas donde queramos: en los

lados, arriba o abajo (o una junto a otra).

Si, durante el arranque, Tornado no se ha podido conectar al registro de Tornado, preguntará si se quiere ejecutar el registro.

Al ejecutar Tornado por primera vez, aparece abierta la caja de dialogo Create Project, existiendo la posibilidad de crear dos tipos de aplicaciones o proyectos:

o Donwlable application

Un módulo objeto descargable, o downlable, consiste en uno o más módulos objetos relocalizables, que pueden ser descargados y enlazados dinámicamente al sistema operativo VxWorks, y después se pueden ejecutar desde la shell o desde el debugger de Tornado. Una característica nueva del entorno de desarrollo de Tornado es la carga dinámica, que permite cargar objetos en un sistema en ejecución. Esto proporciona ciclos de depuración mucho más rápidos, comparándolos con el proceso de tener que volver a generar y reenlazar el sistema operativo completo. Un módulo objeto descargable puede consistir en un único fichero, conteniendo una simple rutina “hola mundo”, o una aplicación compleja consistente en muchos ficheros y módulos que están parcialmente enlazados como un único objeto (que es creado automáticamente

Page 41: Labratorio trabajando con c

Introducción a Tornado 3 de 30

Isidro Calvo y A. Fabián López Informática Industrial Dpto. de Ingeniería de Sistemas y Automática UPV/EHU

por la herramienta de proyectos). El módulo objeto tendrá el mismo nombre que el proyecto, y la extensión out, tal como se describe en este documento.

o Bootable application

Una aplicación arrancable, o bootable, consiste en un modulo objeto enlazado a un kernel, o imagen, de VxWorks. La imagen VxWorks se puede configurar para incluir o excluir componentes del sistema operativo, mediante la activación/desactivación de parámetros del sistema operativo. Una aplicación arrancable comienza su ejecución cuando el target es arrancado.

4. Crear un proyecto descargable para VxWorks

Si la caja de dialogo de Create Project in New/Existing Workspace no está abierta se puede abrir mediante la secuencia de opciones de menú: File > New Project.

Al seleccionar la opción: Create downloadable applications for VxWorks, se lanza el asistente (Wizard), que nos ayuda a seguir los pasos necesarios para crear un nuevo proyecto.

En el primer paso nos pregunta:

• Nombre del proyecto

• Camino y nombre del directorio que se quiere utilizar para guardar el proyecto

• Una descripción del proyecto (es opcional)

• El nombre y la localización del fichero del workspace, el cual contiene información acerca de espacio de trabajo, incluyendo los proyectos que pertenecen a él.

Un proyecto consiste en código fuente, la configuración de la generación del módulo objeto (Building settings) y los archivos binarios que se utilizan para generarlo.

Un espacio de trabajo, o workspace, es simplemente la agrupación de uno o más proyectos. Esto proporciona una forma muy útil de trabajar con material relacionado, compartir código entre proyectos y asociar módulos objeto relacionados. Una vez que se ha creado un proyecto en un worksapce, la ventana del workspace muestra información de todos los proyectos que contiene.

Se puede utilizar el directorio y los nombres por defecto indicados por el asistente, pero es preferible situarlos en un directorio que no esté colgado del árbol de directorios de la instalación de Tornado (para que no se borren si se desinstala Tornado).

Page 42: Labratorio trabajando con c

Introducción a Tornado 4 de 30

Isidro Calvo y A. Fabián López Informática Industrial Dpto. de Ingeniería de Sistemas y Automática UPV/EHU

NOTA: El directorio base para el proyecto y el directorio para el workspace deben existir antes de crear los ficheros del proyecto y de workspace.

En el segundo paso se presenta una caja de dialogo en la que se debe indicar la toolchain que construirá el módulo objeto.

Una toolchain es un conjunto de herramientas de desarrollo cruzado, que permiten construir módulos objeto para un target específico. Las toolchain suministradas con Tornado están basadas en el preprocesador, compilador, ensamblador y enlazador de GNU. Los nombres por defecto de las toolchain para simuladores de target tienen la forma SIMhostOSgnu (por ejemplo SIMNTgnu).

Page 43: Labratorio trabajando con c

Introducción a Tornado 5 de 30

Isidro Calvo y A. Fabián López Informática Industrial Dpto. de Ingeniería de Sistemas y Automática UPV/EHU

En nuestro caso seleccionaremos la toolchain SIMNTgnu y pulsaremos el botón Next para continuar. Tras ello, se muestran las opciones seleccionadas en los pasos anteriores, para que sean confirmadas:

Tras lo cual aparece la ventana del workspace. El título de la ventana incluye el nombre del workspace y la ventana contiene una carpeta para cada uno de los proyectos del workspace.

NOTA: El menú contextual correspondiente a un objeto se muestra pulsando el botón derecho del ratón, después de haber seleccionado dicho objeto. Nos permite acceder a todos los comando que se pueden utilizar sobre el objeto seleccionado.

Page 44: Labratorio trabajando con c

Introducción a Tornado 6 de 30

Isidro Calvo y A. Fabián López Informática Industrial Dpto. de Ingeniería de Sistemas y Automática UPV/EHU

5. Añadir código fuente al proyecto

Programa fuente:

El programa ejemplo que se va a utilizar crea una array de números enteros, los ordena y luego crea otro array de estructuras con dos campos. Uno de los campos de la estructura contiene el número correspondiente del array de números y en el otro campo una cadena de caracteres que indica si dicho número es primo o no.

Si tenemos el código fuente ya editado, con un editor del tipo ASCII puro, para añadir el código, basta con seleccionar Add Files desde el menú contextual en la vista File del workspace y seleccionar dicho fichero.

Tras seleccionar el archivo Arr_num.c y podemos abrir la carpeta de Object Modules, en la vista de Files, para mostrar los nombres de los ficheros fuente y de los ficheros objeto que se van a crear a partir de ellos.

Al crear un proyecto, Tornado facilita la creación automática del fichero projectName.out como un único módulo, parcialmente enlazado.

El fichero projectName.out, comprende todos los módulos objeto individuales del proyecto de la aplicación descargable y facilita la descarga de todos ellos en el target de manera simultánea.

NOTA: También se puede crear el fichero del código fuente, utilizando el editor integrado en Tornado. Para ello habría que seleccionar el submenú New, del menú Files, o el

icono ; tras lo cual se abriría una nueva ventana donde escribir el código del nuevo archivo.

Page 45: Labratorio trabajando con c

Introducción a Tornado 7 de 30

Isidro Calvo y A. Fabián López Informática Industrial Dpto. de Ingeniería de Sistemas y Automática UPV/EHU

6. Generar el módulo objeto del proyecto

Para revisar la configuración que se va a utilizar para generar el módulo objeto, debemos seleccionar la hoja Builds de la ventana del workspace. Seguidamente se debe abrir en ella la carpeta Ejemplo_Vx Builds y hacer doble-click sobre el nombre por defecto del generador del módulo objeto (SIMNTgnu).

Mediante el menú contextual de Properties... se pueden ver, y modificar, las reglas del makefile y las macros, así como las opciones que van a utilizar el compilador, el ensamblador y el enlazador para generar el módulo objeto.

NOTA: Durante el proceso de desarrollo de un proyecto, es importante seleccionar la opción de incluir información para la depuración (include debug info, en la hoja C/C++ compiler).

Para generar el proyecto hay que seleccionar, en el menú contextual:

Build 'Ejemplo_Vx.out'

La opción Build 'Ejemplo_Vx.out' genera la aplicación, con todos los módulos del proyecto como un único y parcialmente enlazado módulo que está optimizado para descargarlo al target.

Antes de generar la aplicación se muestra la caja de dialogo Dependencies, en el que se indican los ficheros fuente relacionados con la aplicación.

Page 46: Labratorio trabajando con c

Introducción a Tornado 8 de 30

Isidro Calvo y A. Fabián López Informática Industrial Dpto. de Ingeniería de Sistemas y Automática UPV/EHU

En el ejemplo, antes de generar el módulo objeto, la caja de dialogo Dependencies nos informa de que las dependencias para el fichero makefile todavía no han sido calculadas para Ejemplo_Vx.c.

Tras pulsar el botón de OK, Tornado calcula las dependencias para el fichero makefile, y procede a generar el módulo objeto del proyecto. Si se encuentra alguna dependencia externa, se incluye automáticamente en el proyecto y es listada en la carpeta External Dependencies, en la hoja Files de la ventana del workspace.

La ventana Build Output muestra los errores y los avisos. En este caso el compilador ha detectado una extraña variable, longitud, que se define pero que no se utiliza posteriormente.

Haciendo doble-click sobre la línea del mensaje de error o de aviso se abre, en el editor de Tornado, el fichero del código fuente con un puntero señalando la línea origen del mensaje:

Page 47: Labratorio trabajando con c

Introducción a Tornado 9 de 30

Isidro Calvo y A. Fabián López Informática Industrial Dpto. de Ingeniería de Sistemas y Automática UPV/EHU

Tras eliminar la definición de la variable longitud se debe salvar el fichero, pulsando CTRL+S o mediante la opción del menú File > Save, y volver a generar el módulo objeto.

El editor de Tornado es un editor orientado a lenguaje (por ejemplo, dispone del reconocimiento y coloreado de los diversos elementos sintácticos) e incluye las capacidades estándar de Windows para la manipulación de texto.

Finalmente se debe cerrar la ventana Build Output.

7. Descargar el módulo objeto del proyecto en el Simulador del target de VxWorks

En este punto, desde la hoja Files de la ventana de workspace, se puede, descargar el módulo objeto y lanzar el simulador integrado, todo ello como parte del mismo proceso.

Se debe seleccionar la carpeta con el nombre del proyecto y en el menú contextual (mostrado con el botón derecho de ratón) elegir la opción Download 'Ejemplo_Vx.out'.

Tornado pregunta si se quiere comenzar a ejecutar el simulador:

Al pulsar el botón de Yes para continuar, aparecerá la caja de dialogo de VxSIM-Lite Launch:

Page 48: Labratorio trabajando con c

Introducción a Tornado 10 de 30

Isidro Calvo y A. Fabián López Informática Industrial Dpto. de Ingeniería de Sistemas y Automática UPV/EHU

Se debe dejar seleccionado el Standard Simulator y pulsar OK para continuar.

La ventana del simulador de target (VxWorks Simulator for Windows) se abre, y Tornado pregunta si se quiere ejecutar el target server. Pulsando OK, en la caja de dialogo del VxSIM-Lite Launch, se continúa con el proceso.

NOTA: En cada instante, sólo se puede ejecutar una instancia del simulador integrado del

target VxWorks,(VxSim-Lite (Para terminar la simulación bastará con cerrar la ventana del VxWorksSimulator).

Un target server gestiona todas las comunicaciones entre las herramientas del host Tornado, tales como la shell o el debugger, y el target. La convención para los nombres del server target es targetName@hostName. En el ejemplo el nombre del target es vxsim (el nombre por defecto del simulador integrado) y el nombre del PC host es badger.

El nombre del target server se muestra en la barra de herramientas de Tornado:

Browser Shell Debugger Simulator

WindView Wind

Navitagor Triggering

La barra de herramientas incluye botones para ejecutar las herramientas de Tornado tales como Browser, Shell y Debugger. Los botones se activan cuando se lanza la ejecución del target server.

NOTA: Tanto el botón del Browse como el de la Shell tienen la letra i en ellos, lo cual puede llevar a confusión. La i en el botón de la Shell va seguido del indicador de la Shell: ->

Page 49: Labratorio trabajando con c

Introducción a Tornado 11 de 30

Isidro Calvo y A. Fabián López Informática Industrial Dpto. de Ingeniería de Sistemas y Automática UPV/EHU

8. Ejecutar el módulo objeto desde la Shell de Tornado

Antes de ejecutar el módulo objeto, es útil configurar y ejecutar el depurador de Tornado, de tal forma que el depurador pueda responder automáticamente a cualquier excepción del programa.

El depurador o debugger de Tornado (CrossWind) combina características de los depuradores con interfaz gráfica y los de interfaz de línea de comandos. Las operaciones más comunes tales como visualizar la traza y otros objetos del programa, poner puntos de ruptura (breakpoints) y controlar la ejecución de la aplicación están disponibles desde la barra de herramientas de depuración:

Para configurar el depurador o debugger hay que seleccionar la opción de menú Tools > Options > Debugger desde la ventana principal de Tornado. En la caja de dialogo que aparece se debe seleccionar Always en la característica Auto attach to tasks, para que el depurador se acople automáticamente a la tarea cuando ocurra una excepción.

Pulsando el botón en la barra de herramientas comienza la ejecución del depurador. Tras unos segundos, la línea de estado, en el pie de la ventana principal, anunciará que el depurador se está ejecutando:

La shell de Tornado (conocida como WindSh) es un intérprete de comandos de lenguaje C que permite invocar, desde la línea de comandos de la shell, cualquier rutina que haya sido cargada en el target. La shell también incluye su propio conjunto de comandos para manipular tareas, acceder a la información del sistemas, depurar, ...

Page 50: Labratorio trabajando con c

Introducción a Tornado 12 de 30

Isidro Calvo y A. Fabián López Informática Industrial Dpto. de Ingeniería de Sistemas y Automática UPV/EHU

Para comenzar una shell hay que hacer clic en el botón: .

Cuando se abra la ventana de la shell, para ejecutar el programa bastará con poner en la línea de comandos el nombre de la rutina principal del programa (ej. main) o de cualquier otro subprograma o tarea de los módulos cargados.

Desde la shell, se puede llamar a rutinas para mostrar datos en la salida estándar, o para aceptar datos desde la entrada estándar. Por defecto, la salida estándar y la entrada estándar se dirigen a la ventana de la Shell de Tornado.

-> printf("Hello World\n") Hello World! value = 13 = 0xd ->

Este comportamiento se puede modificar dinámicamente, utilizando el procedimiento shConfig, tal como se ve en el siguiente ejemplo:

-> ?shConfig SH_GET_TASK_IO off -> -> printf("Hello World!\n") value = 13 = 0xd ->

La shell muestra el resultado del comando printf( ), indicando que ha mostrado 13 caracteres. La salida, sin embargo, ha sido redirigida a la salida estándar del target, no a la shell.

La shell muestra los datos de tipo entero y los de tipo carácter en formato decimal y hexadecimal, y si es posible, como una constante carácter o una dirección simbólica más un offset.

-> 68 value = 68 = 0x44 = 'D' -> 0xf5de value = 62942 = 0xf5de = _init + 0x52 -> 's' value = 115 = 0x73 = 's'

Page 51: Labratorio trabajando con c

Introducción a Tornado 13 de 30

Isidro Calvo y A. Fabián López Informática Industrial Dpto. de Ingeniería de Sistemas y Automática UPV/EHU

Se pueden utilizar casi todos los operadores de C para realizar cálculos, e incluso el operador paréntesis para forzar el orden de precedencia.

-> (14 * 9) / 3 value = 42 = 0x2a = '*'

Al asignar, mediante una sentencia de asignación, un valor a un identificador no definido (uno que no esté ya en la tabla de símbolos) la shell crea automáticamente un nueva variable. La shell reserva espacio para la nueva variable, le asigna el valor indicado en la expresión de la derecha (de la sentencia de asignación) y muestra un mensaje indicando que se ha creado una nueva variable y se le ha asignado el valor que se especifica. El tipo de la variable creada es el correspondiente al tipo del valor asignado.

-> x = 100 new symbol "x" added to symbol table. x = 0x49aefec: value = 100 = 0x64 = 'd' -> -> saludo = "Hello world" new symbol " saludo" added to symbol table. saludo = 0x49aefac: value = 77262772 = 0x49aefb4 = saludo + 0x8 ->

Ejemplo de uso de la shell como intérprete de comandos de C:

Crear dos variables, iUno e iDos, asignarles un valor (11 y 22 respectivamente) y utilizar la función IntercambiarEnteros, del módulo objeto cargado, para intercambiar sus valores: -> iUno = 11 /* crear variable y asignarle valor */ new symbol "iUno" added to symbol table. iUno = 0x49aeff4: value = 11 = 0xb -> iDos = 22 /* crear variable y asignarle valor */ new symbol "iDos" added to symbol table. iDos = 0x49aefec: value = 22 = 0x16 -> iUno /* mostrar el valor de la variable */ iUno = 0x49aeff4: value = 11 = 0xb -> iDos /* mostrar el valor de la variable */ iDos = 0x49aefec: value = 22 = 0x16 -> IntercambiarEnteros (&iUno, &iDos) /* llamar a la función */ value = 77262828 = 0x49aefec = iDos -> iUno /* mostrar el valor de la variable */ iUno = 0x49aeff4: value = 22 = 0x16 -> iDos /* mostrar el valor de la variable */ iDos = 0x49aefec: value = 11 = 0xb ->

Para finalizar la ejecución de la shell se puede ejecutar el comando quit o bien cerrar la ventana de la shell.

Page 52: Labratorio trabajando con c

Introducción a Tornado 14 de 30

Isidro Calvo y A. Fabián López Informática Industrial Dpto. de Ingeniería de Sistemas y Automática UPV/EHU

Algunos comandos de la Shell de Tornado help Muestra una sinopsis de algunos comandos.

HTML Help

Escribiendo cualquier nombre de comando, un espacio, y CTRL+W se abre el browser y se muestra la página HTML de referencia de dicho comando.

-> i [CTRL+W] quit o exit Cierra la shell (WindSh). reboot Rearranca el target y el servidor se conecta de nuevo con él. Al cabo de

un segundo se reinicia la shell. version Muestra información de la version de VxWorks. h [size] Muestra el histórico de la shell o modifica su tamaño.

El valor inicial de size es 20. pwd Muestra el directorio por defecto actual. cd "path" Cambia el directorio por defecto. ls ["path"[, long] ] Lista el contenido del directorio (1 listado largo y 0 listado corto). lkup "substr" Lista símbolos.

Lista todos los símbolos, de la tabla de símbolos del sistema, cuyos nombres contienen la subcadena indicada en la línea de comandos, substr. Si substr es una cadena vacía (""), se muestran todos los símbolos de la tabla de símbolos.

period secs, funct, args… Crea y arranca una tarea que ejecuta una función periódicamente.

Crea y arranca una tarea que repetidamente llama a una determinada función, funct, residente en el target, a la que se le pueden pasar hasta 8 parámetros (arg1, arg2, arg3,…), con un retardo, entre llamadas, igual al número de segundos indicado en la línea de comandos, secs.

-> period 2, main repeat n, funct, args, … Crea y arranca una tarea que ejecuta una función repetidamente.

Crea y arranca una tarea que llama a una determinada función, funct, residente en el target, un número determinado de veces, n. A la función functr se le pueden pasar hasta 8 parámetros (arg1, arg2, arg3,…). Si n es 0, la función se ejecuta continuamente o hasta que la tarea sea eliminada.

-> repeat 2, main

-> repeat 1, IntercambiarEnteros, &iUno, &iDos i [task] Muestra un resumen del TCB de cada una de las tareas. ti [task] Muestra la información completa del TCB de cada una de las tareas.

Estos comandos (y el siguiente) muestran información de todas las tareas del sistema, o de la tarea especificada en la línea de comando.

Page 53: Labratorio trabajando con c

Introducción a Tornado 15 de 30

Isidro Calvo y A. Fabián López Informática Industrial Dpto. de Ingeniería de Sistemas y Automática UPV/EHU

iStrict [task] Muestra un resumen del TCB de cada una de las tareas, tomada como en una instantánea. El resultado de la ejecución de este comando es idéntico al del comando i, pero se garantiza la consistencia de los datos al tomarse todos los datos en una única transacción del target.

Estos comandos (i, ti, iStrict) se deberían utilizar únicamente como ayuda a la depuración, puesto que la información ya es obsoleta en el instante de ser mostrada.

-> i NAME ENTRY TID PRI STATUS PC SP ERRNO DELAY ---------- ---------- -------- --- --------- ------- -------- ----- -- tExcTask _excTask 20fcb00 0 PEND 200c5fc 20fca6c 0 0 tLogTask _logTask 20fb5b8 0 PEND 200c5fc 20fb520 0 0 tRlogind _rlogind 20f3f90 2 PEND 2038614 20f3db0 0 0 tTelnetd _telnetd 20f2124 2 PEND 2038614 20f2070 0 0 tNetTask _netTask 20f7398 50 PEND 2038614 20f7340 0 0 value = 57 = 0x39 = '9'

NOTA: Los argumentos especificados como task pueden ser tanto el nombre como el ID de la tarea.

sp funct, args, … Crea y lanza una tarea, con parámetros por defecto. sps funct, args, … Crea y lanza una tarea, con parámetros por defecto, y la deja suspendida.

Este comando crea y lanza una determinada tarea (que ejecuta una función, funct) con los siguiente valores por defecto:

Prioridad: 100

Tamaño de la pila o stack: 20,000 bytes

Identificador de la tarea (taskID): el número más alto de los no utilizados

Opciones de la tarea: VX_FP_TASK ( ejecuta con soporte para el coprocesador de punto flotante)

Nombre de la tarea: El nombre es de la forma sXuN, donde X es el número de la shell y N un numero entero que se incrementa para cada tarea creada. Por tanto los nombres de las tareas serán: s1u1, s1u2, s5u3, etc.

El identificador de la tarea (task ID) es mostrado tras crearse y lanzarse la tarea.

-> sp main

-> sp IntercambiarEnteros, &iUno, &iDos

Cargada sólo la imagen de VxWorks

Cargado el debugger y el módulo o aplicación main

Page 54: Labratorio trabajando con c

Introducción a Tornado 16 de 30

Isidro Calvo y A. Fabián López Informática Industrial Dpto. de Ingeniería de Sistemas y Automática UPV/EHU

td task Elimina una tarea. tr task Reactiva una tarea. ts task Suspende una tarea.

NOTA: Los argumentos especificados como task pueden ser tanto el nombre como el ID de la tarea.

? shConfig Muestra o cambia el comportamiento de una sesión específica de la shell

Mostrar la configuración actual de la shell: -> ? shConfig DSM_HEX_MODE = off LD_CALL_XTORS = target LD_COMMON_MATCH_ALL = on LD_PATH = . LD_SEND_MODULES = on SH_GET_TASK_IO = on

Mostrar la configuración actual de un parámetro:

-> ?shConfig SH_GET_TASK_IO SH_GET_TASK_IO = on

Cambiar la salida y la entrada. Poner la entrada y salida estándar del target, en lugar de que sea la shell:

-> ? shConfig SH_GET_TASK_IO off

Page 55: Labratorio trabajando con c

Introducción a Tornado 17 de 30

Isidro Calvo y A. Fabián López Informática Industrial Dpto. de Ingeniería de Sistemas y Automática UPV/EHU

9. Explorador de objetos del sistema: Browser

El Borwser es un visor de objetos del sistema. Es un componente gráfico de la shell que proporciona facilidades para monitorizar el estado del target, incluyendo resúmenes de las tareas activas del sistema y de la aplicación, asignación y uso de la memoria, resumen del actual mapeo de la memoria del target,…

Utilizando el browser también se puede examinar:

• Información detallada de las tareas

• Semáforos

• Colas de mensajes

• Particiones de la memoria

• Timers de tipo Watchdog

• Uso de la pila por parte de todas las tareas del target

• Uso de la CPU del target por parte de las tareas

• Información de los módulos: estructura y símbolos

• Vectores de interrupción

Hay dos formas de ejecutar el browser: Desde el icono de la barra de herramientas o desde la opción Browser del menú Tools.

Cuando se abre la ventana del browse, se debe seleccionar, en la lista desplegable, la información que se desea mostrar (Memory Usage, Target Information, …). La información mostrada se obtiene en un instante determinado y único, pero se puede actualizar

interactivamente, pulsando el botón , o se puede configurar el browser, pulsando el botón

, para que la información mostrada automáticamente se actualice en intervalos determinados. Para que la información se refresque automáticamente o interactivamente basta

con pulsar el botón

Memory Usage:

Page 56: Labratorio trabajando con c

Introducción a Tornado 18 de 30

Isidro Calvo y A. Fabián López Informática Industrial Dpto. de Ingeniería de Sistemas y Automática UPV/EHU

Target Information

Module Information:

Stack Check

Spy Chart

Tasks

Page 57: Labratorio trabajando con c

Introducción a Tornado 19 de 30

Isidro Calvo y A. Fabián López Informática Industrial Dpto. de Ingeniería de Sistemas y Automática UPV/EHU

10. Descripción de una sesión de depuración

Para comenzar un sesión de depuración, en primer lugar hay que descargar el modulo que se quiere depurar, tal como se ha descrito en el apartado 6, “Descargar el módulo objeto del proyecto en el Simulador del target de VxWorks”.

Seguidamente se debe comenzar la ejecución del depurador o debugger desde el menú

Debbug > Run (F6) o desde el botón . Tras lo cual se activa la barra de herramientas del depurador:

Ejecutar una rutina bajo el control del depurador.

Parar el depurador.

Poner/quitar punto de ruptura (Toggle breakpoint).

Interrumpir la ejecución del módulo.

Continuar con la ejecución.

Ejecutar la siguiente línea de código. Si es la llamada a una subrutina pasa a ejecutar la primera línea de la misma.

Ejecutar la siguiente línea de código. Si es la llamada a una subrutina la ejecuta por completo.

Terminar la ejecución de la actual subrutina.

• Ejecutar hasta la línea actual del código fuente (donde se coloca el cursor): mediante menú contextual

Watch. Mostrar el valor de una variable determinada.

Mostrar todas las variables locales.

Mostrar los registros del target.

Mostrar la traza del programa, desde el módulo inicial hasta la subrutina actual (muestra la información de la pila).

Mostrar la memoria del target.

Al pulsar el botón se muestra el cuadro de dialogo para seleccionar la rutina que se quiere depurar (por ejemplo main).

NOTA: Se debe activar la opción de que se detenga la ejecución al inicio de la misma.

Page 58: Labratorio trabajando con c

Introducción a Tornado 20 de 30

Isidro Calvo y A. Fabián López Informática Industrial Dpto. de Ingeniería de Sistemas y Automática UPV/EHU

Seguidamente se muestra el código del módulo:

Se puede abrir la ventana de la traza del programa pulsando el botón :

Y la ventana de las variables locales, pulsando :

Siguiente línea del módulo que se ejecutará

Page 59: Labratorio trabajando con c

Introducción a Tornado 21 de 30

Isidro Calvo y A. Fabián López Informática Industrial Dpto. de Ingeniería de Sistemas y Automática UPV/EHU

Por ejemplo, se pueden poner puntos de ruptura al inicio de cada llamada a subprograma para ir viendo la ejecución del mismo, así como los valores que van tomando las variables locales a main:

En el ejemplo, la variación de los valores de las variables locales a main en los sucesivos puntos de ruptura:

Al inicio de la ejecución:

Tras la llamada a LlenarListaNumeros:

Tras la llamada a OrdenarListaNumeros:

Tras la llamada a LlenarListaEstructuras:

Puntos de ruptura

Page 60: Labratorio trabajando con c

Introducción a Tornado 22 de 30

Isidro Calvo y A. Fabián López Informática Industrial Dpto. de Ingeniería de Sistemas y Automática UPV/EHU

La traza del programa en el instante en que se comienza a ejecutar el subprograma LlenarListaNumeros es:

En la ventana del simulador de target (VxWorks Simulator for Windows) se puede ir viendo el resultado de la ejecución del programa (simula la consola del target1):

11. Crear una imagen de VxWorks configurada o customizada

Si la caja de dialogo de Create Project in New/Existing Workspace no está abierta se puede abrir mediante la secuencia de opciones de menú:

File > New Project.

Se ejecuta entonces el asistente de Tornado, que nos ayuda a seguir los pasos necesarios.

1 Para redireccionar la salida a la consola se debe ejecutar el comando:? shConfig SH_GET_TASK_IO off

Page 61: Labratorio trabajando con c

Introducción a Tornado 23 de 30

Isidro Calvo y A. Fabián López Informática Industrial Dpto. de Ingeniería de Sistemas y Automática UPV/EHU

Page 62: Labratorio trabajando con c

Introducción a Tornado 24 de 30

Isidro Calvo y A. Fabián López Informática Industrial Dpto. de Ingeniería de Sistemas y Automática UPV/EHU

Añadir código fuente al proyecto

Se añade el código fuente al proyecto, tal como se describe en el apartado 4 “Añadir código fuente al proyecto” Pero, en este caso, al seleccionar la hoja Files de la ventana del workspace, automáticamente se han añadido una serie de ficheros relacionados con la imagen de VxWorks.

Configurar los componentes de VxWorks

Al seleccionar la hoja VxWorks de la ventana del workspace se muestran todos los componentes de VxWorks disponibles para este target.

• Los nombres de los componentes que

están seleccionados para su inclusión aparecen en negrita.

• Los nombres de los componentes que están excluidos aparecen en texto plano.

• Los nombres de los componentes que no han sido instalados aparecen en cursiva.

• Los nombres de las carpetas aparecen en negrita si alguno (no necesariamente todos) de sus componentes están incluidos.

Desplegando los componentes:

operating system components ANSI C components (libc)

Se puede seleccionar un componente directamente (o buscarlo mediante el menú contextual) y tras ello incluirlo, excluirlo, configurarlo, ...

Page 63: Labratorio trabajando con c

Introducción a Tornado 25 de 30

Isidro Calvo y A. Fabián López Informática Industrial Dpto. de Ingeniería de Sistemas y Automática UPV/EHU

Eliminando la librería POSIX clocks:

Se nos informa de que se va a excluir otro/s componentes:

Añadiendo la librería POSIX semaphores:

Se nos informa de que se va a incluir otro/s componentes:

Page 64: Labratorio trabajando con c

Introducción a Tornado 26 de 30

Isidro Calvo y A. Fabián López Informática Industrial Dpto. de Ingeniería de Sistemas y Automática UPV/EHU

Si se incluyen componentes que potencialmente presentan un conflicto entre ellos, Tornado informa de ello mostrando un mensaje e iluminando el camino completo hasta la fuente del conflicto.

Ejemplo:

En: development tool components symbol table components

1º incluimos: built-in symbol table

2º incluimos: downloaded symbol

Seleccionando el nombre del proyecto, en cualquiera de las vistas del workspace, y seleccionando Properties, en el menú contextual, se puede ver el tamaño total de los componentes del kernel, o imagen, de VxWorks.

Posteriormente se debe seleccionar el tipo de kernel, o imagen, VxWorks que se desea:

• vxWorks

• vxWorks-rom

• vxWorks-romCompress

• vxWorks-romResident

Page 65: Labratorio trabajando con c

Introducción a Tornado 27 de 30

Isidro Calvo y A. Fabián López Informática Industrial Dpto. de Ingeniería de Sistemas y Automática UPV/EHU

Finalmente se genera el módulo objeto, del mismo modo que las aplicaciones descargables (tal como se ha descrito en el apartado 5, “Generar el módulo objeto del proyecto”), mediante la opción correspondiente del menú contextual.

12. Examinar la actividad de las tareas

WindView es un analizador de Tornado para aplicaciones de Tiempo Real. Es una herramienta de visualización dinámica que suministra información de los cambios de contexto y los eventos que los originan, así como información de objetos tales como semáforos, colas de mensajes y watchdog times.

Para mostrar la actividad de las tareas se va a utilizar el programa cobble.c que está situado en el directorio: c:\tornado\target\src\demo\start y que contiene rutinas tales como progStart (que lanza la ejecución de 4 tareas: tCosmos, tSchlep, tMonitor, tCrunch), progStop, ...

Tras descargar en el simulador el código y una vez lanzada la ejecución de la rutina progStart

Page 66: Labratorio trabajando con c

Introducción a Tornado 28 de 30

Isidro Calvo y A. Fabián López Informática Industrial Dpto. de Ingeniería de Sistemas y Automática UPV/EHU

Basta con pulsar el botón de WindView , en la barra de Tornado, para abrir la ventana de control de WindView:

Se puede seleccionar los eventos que se desean capturar para posteriormente mostrarlos:

Pulsando botón GO , en la ventana de control de WindView, se comienza a guardar datos.

Tras unos segundos, se debe pulsar el botón de

actualizar, , para actualizar la información mostrada:

Una vez alcanzado aproximadamente un porcentaje del 50%, se pulsa el botón de STOP para detener el almacenamiento de datos.

Antes de cargar los datos de WindView desde el simulador del target al host, hay que parar el programa, ejecutando progStop en la línea de comandos de la Shell.

Page 67: Labratorio trabajando con c

Introducción a Tornado 29 de 30

Isidro Calvo y A. Fabián López Informática Industrial Dpto. de Ingeniería de Sistemas y Automática UPV/EHU

Finalmente, mediante el botón para se cargan los datos en WindView. Cuando la carga se haya completado se mostrará una ventana gráfica similar a la siguiente:

Se activa, entonces, la barra de tareas de WindView: Zoom in Zoom out Zoom 100% Factor de Zoom

Analyze

Filter events Hide nonexecuting status Track incoming events

Se puede filtrar la información mostrada, y , realizar búsquedas de eventos, ,

realizar análisis del uso de la CPU o del memoria, , utilizar los botones de zoom para

aumentar o disminuir el tamaño de lo mostrado, , realizar mediciones entre instantes, …

Se puede configurar WindView (por ejemplo el color del fondo, mediante la secuencia de opciones de menú: Tools > WindView > Option

Page 68: Labratorio trabajando con c

Introducción a Tornado 30 de 30

Isidro Calvo y A. Fabián López Informática Industrial Dpto. de Ingeniería de Sistemas y Automática UPV/EHU

Por ejemplo, seleccionando como eventos a capturar Task State Transition, configurando el fondo de la pantalla como blanco, Tools > WindView > Option > White Background, y aumentado el zoom…

Los eventos se muestran mediante símbolos. Por ejemplo las banderas indican los semáforos, las líneas el estado de ejecución de las tareas...

Para obtener información acerca del significado de los iconos de WindView se debe seleccionar la opción de menú:

Help > WindView Help > Legend

Page 69: Labratorio trabajando con c

- I -

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática

Sockets UDP

Informática Industrial (Ingeniería en Electrónica y Automática)

Departamento de Ingeniería de Sistemas y Automática

Page 70: Labratorio trabajando con c

- II -

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática

INDICE

1. Práctica final ............................................................................................................. 1

1.1. Introducción ...................................................................................................... 1

1.2. Objetivos ........................................................................................................... 2

1.3. Se pide: ............................................................................................................. 3 1.3.1. Empezar a registrar datos ......................................................................... 3 1.3.2. Parar de registrar datos ............................................................................. 3 1.3.3. Estado del sistema .................................................................................... 4 1.3.4. Análisis de los datos ................................................................................. 4 1.3.5. Visualizar fichero de alarmas ................................................................... 4 1.3.6. Cambiar la hora del sistema...................................................................... 4 1.3.7. Salir ........................................................................................................... 4

2. Apéndices ................................................................................................................. 5

2.1 Estructura para enviar los datagramas .............................................................. 5

2.2 Código del servidor .......................................................................................... 5

2.3 Conceptos de sockets ........................................................................................ 6

2.4 Funciones a utilizar ........................................................................................... 8 2.4.1 Funciones relacionadas con comunicaciones ........................................... 8 2.4.2. Funciones relacionadas con tareas .......................................................... 10 2.4.3. Funciones relacionadas con ficheros ...................................................... 11 2.4.4. Funciones relacionadas con el tiempo .................................................... 11

Page 71: Labratorio trabajando con c

Comunicaciones en VxWorks – Sockets UDP 1 de 12

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática

13. Práctica final

Introducción En la presente práctica se va a implementar un sistema de adquisición de datos compuesto por varios ordenadores. Uno de ellos, el concentrador, actúa como servidor de una serie datos que se recogen, con tarjetas de adquisición de datos, de una planta química de dinámica lenta. Los datos recogidos de la planta se distribuyen a través de una red Ethernet en la que, cada uno de los ordenadores de los alumnos de prácticas actúa como un registrador de datos. Estos datos se guardan en un fichero que se utilizará para su posterior análisis con paquetes del tipo MATLAB o EXCEL.

El siguiente dibujo ilustra el proceso seguido para analizar los datos.

TCP/IP sobre Ethernet

Planta: Generación de

datos

Servidor: Envía los datagramas UDP

Cliente: Registra los datos recibidos como datagramas en un fichero de disquete.

Fichero de texto con los datos

Análisis de los datos con paquetes MATLAB / EXCEL

Un ejemplo simplificado del código que ejecuta el servidor encargado de distribuir los datos recogidos puede encontrarse al final del guión en el apéndice correspondiente (Sección 2.2). Los datos obtenidos por el servidor se envían a través de una red Ethernet habiéndose escogido el protocolo UDP de TCP/IP para distribuirlos. Las razones por las que en esta práctica se ha escogido el protocolo UDP, basado en datagramas, frente al protocolo TCP, orientado a conexión, hay que buscarlas en que el rendimiento es mejor, ya que no exige el mantenimiento de circuitos virtuales (como en el caso del protocolo TCP) además de que es más sencillo de utilizar. Por otro lado, este protocolo puede ocasionar la pérdida de algún paquete sin que ningún nodo sea notificado de ello. Sin embargo, en caso de que así suceda, el funcionamiento del sistema es aceptable ya que al tratarse de un sistema de dinámica lenta, las variaciones de los datos del sistema serán lentas con lo que la pérdida de algún paquete no afectará de forma substancial al análisis de los datos.

Page 72: Labratorio trabajando con c

Comunicaciones en VxWorks – Sockets UDP 2 de 12

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática

Los datagramas que se enviarán consistirán la siguiente estructura que habrá que definir en el fichero “udp.h”: struct trgDato { long int lNumSec ; /* Numero de secuencia */ float rTemp ; /* Valor de la temperatura */ float rPresion ; /* Valor de la presión */ } ;

Los datos recibidos por el cliente se guardarán en un fichero de texto cuyo nombre se pedirá previamente por teclado con el formato: Numero Secuencia Fecha Hora Temp. Presión

Donde: El número de secuencia xxxxxxxx La fecha tendrá el formato dd/mm/aa La hora tendrá el formato hh:mm:ss La temperatura tendrá el formato xx.xxx La presión tendrá el formato xxxx.x

Cuando el programa registre una temperatura mayor de 50 grados o una presión mayor que 2000 milibares, se producirá una alarma. Los mensajes de alarma se registrarán en el fichero alarmas.txt y consistirán en un mensaje que contendrá la siguiente información: Tipo Alarma Fecha Hora Temp. Presión

El tipo de alarma consistirá en una de los siguientes magnitudes. 1-> Alarma de temperatura 2-> Alarma de presión La fecha tendrá el formato dd/mm/aa La hora tendrá el formato hh:mm:ss La temperatura tendrá el formato xx.xxx La presión tendrá el formato xxxx.x

Nota: Aunque puede haber varios ficheros con los datos recogidos con diferentes nombres, el fichero de alarmas será único, alarmas.txt.

Objetivos Los objetivos principales de esta práctica son los siguientes:

• Poner en funcionamiento un sistema simplificado de adquisición de datos.

• Ilustrar cómo usar las comunicaciones con los protocolos TCP/IP.

• Escribir datos en ficheros bajo el S.O. VxWorks

Page 73: Labratorio trabajando con c

Comunicaciones en VxWorks – Sockets UDP 3 de 12

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática

• Utilizar las funciones de hora del sistema

Se pide: Desarrollar el programa que ejecutará en ordenador cliente. Este programa deberá disponer de un menú con las siguientes opciones:

1) Empezar a registrar datos 2) Parar de registrar datos 3) Estado del sistema 4) Análisis de los datos 5) Visualizar alarmas 6) Cambiar la hora del sistema 7) Salir

A continuación se pasará a definir qué se deberá hacer en cada una de las opciones:

1.3.1 Empezar a registrar datos

Este es el apartado más extenso del menú.

Primero, se escogerá el nombre que se utilizará para guardar los datos recogidos. Si el fichero existe dará un mensaje de error diciendo que ya existe.

Además, lanzará la tarea udpCliente (con taskSpawn) que hará lo siguiente:

• Rellenar la estructura sockaddr_in con los datos de la dirección local. (Nota: Previamente a rellenar la estructura es conveniente rellenarla con ceros usando la función bzero)

• Se creará el socket UDP

• Se hará el correspondiente bind con los datos de la estructura sockaddr_in rellenada previamente.

• Se “montará” la disquetera para poder escribir ficheros en el disquete.

• Se abrirá un archivo para escritura en modo texto con el nombre especificado previamente.

• Se abrirá el archivo de alarmas para escribir alarmas en caso de que tenga lugar alguna alarma.

• Se leerán los datagramas recibidos del concentrador por el correspondiente puerto, hasta que el usuario seleccione la opción 2 (Parar de registrar temperaturas). Para recibir los datagramas se utilizará la función recvfrom.

• Dentro del lazo se escribirán los datos en el fichero determinado

• En caso de que se mida una temperatura mayor de 50 grados o la presión supere los 2000 milibares, se escribirá en el fichero de alarmas el correspondiente mensaje de alarma, tal y como se describe en la introducción.

Tipo Alarma Fecha Hora Temp. Presión

• Al pulsar la opción 2 se cerrarán los ficheros y sockets abiertos.

1.3.2 Parar de registrar datos

Page 74: Labratorio trabajando con c

Comunicaciones en VxWorks – Sockets UDP 4 de 12

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática

Esta opción parará el registro de datos de forma controlada.

1.3.3 Estado del sistema

Esta opción indicará si el sistema está actualmente registrando datos o no. Para ello tendrá que comprobar si se está ejecutando la tarea de registro de datos.

1.3.4 Análisis de los datos

A pesar de que el análisis exhaustivo de los datos se llevará a cabo off-line esta opción permite hacer un análisis mínimo. Por cada fichero a procesar esta opción debe mostrar un informe con las temperaturas y presiones máximas, mínimas y medias. Para ello, se pedirá el nombre del fichero a procesar y tras comprobar previamente que el fichero no está en uso, procesará el fichero para obtener los datos mínimos, máximos y medios, así como la fecha y hora de inicio de registro de los datos y de fin de datos.

1.3.5 Visualizar fichero de alarmas

Esta opción permite visualizar off-line las alarmas producidas. No se permitirá ver las alarmas mientras se están registrando temperaturas. Se permitirá filtrar las alarmas por tipo, mostrando sólo las alarmas de temperatura, presión o todas.

1.3.6 Cambiar la hora del sistema

Esta opción permitirá visualizar la hora del sistema y cambiar la hora del sistema en caso de que así se desee. No se podrá ejecutar mientras se están recogiendo datos.

1.3.7 Salir

Permitirá salir del programa de control de la aplicación. En caso de que la tarea de registrar datos se esté ejecutando se mostrará un mensaje indicando que primero es necesario parar de registrar temperaturas.

Page 75: Labratorio trabajando con c

Comunicaciones en VxWorks – Sockets UDP 5 de 12

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática

14. Apéndices

Estructura para enviar los datagramas #define PUERTO_SERVIDOR 5002 #define TAMANO_MAX_MENSAJE 1024 /* Estructura enviada en los datagramas */ struct trgTemp { long int lNumSec; /* Numero de secuencia */ float rTemp; /* Valor de la temperatura */ float rPresion; /* Valor de la presion */ };

Código del servidor /* *udpServidor.c * *Envia datagramas a traves del puerto determinado en el udp.h *a un ordenador especifico pasado como argumento *Los datagramas seran una estructura con un numero de secuencia *y un valor de temperatura. * *DEVUELVE: OK si todo bien o ERROR si ha habido problemas. */ /* includes */ #include "vxWorks.h" #include "sockLib.h" #include "inetLib.h" #include "stdioLib.h" #include "strLib.h" #include "hostLib.h" #include "ioLib.h" #include "taskLib.h" #include "sysLib.h" #include "udp.h" /* Variables globales */ int giContinuar; STATUS udpServidor (char * sDireccionCliente) /* direccion IP del cliente */ { struct trgTemp rgTemp; /* Estructura trgTemp definida en "udp.h" con los valores a enviar en el datagrama */ struct sockaddr_in rgClienteAddr; /* Estructura sockaddr con la direccion del cliente */ int iSockAddrSize; /* Tamanyo de la estructura sockaddr_in */ int sFd; /* Descriptor del socket */ /* Crea el socket UDP en el cliente */ /* AF_INET hace referencia a los protocolos de Internet. Otros valores: AF_ISO...*/ /* SOCK_DGRAM indica que se enviaran DATAGRAMAS a traves del socket. Otros valores: SOCK_STREAM...*/ if ((sFd = socket (AF_INET, SOCK_DGRAM, 0)) == ERROR) { perror ("Error en la creacion del socket en la funcion \"udpServidor\""); return (ERROR); }

Page 76: Labratorio trabajando con c

Comunicaciones en VxWorks – Sockets UDP 6 de 12

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática

/* No se requiere hacer bind cuando se envian datagramas, sólo cuando se reciben */ /* Rellenado de la estructura que contiene la direccion del socket a la que se envian datagramas*/ iSockAddrSize = sizeof (struct sockaddr_in); bzero ((char *) &rgClienteAddr, iSockAddrSize); rgClienteAddr.sin_family = AF_INET; /* Cambia el formato del numero de puerto */ rgClienteAddr.sin_port = htons (PUERTO_SERVIDOR); /* inet_addr convierte una direccion IP en un entero largo. P.e. convierte "158.227.67.161" en 0x9EE343A1 */ /* hostGetByName convierte un nombre en un entero largo P.e. convierte "bipz61.bi.ehu.es" en 0x9EE343A1 */ if (((rgClienteAddr.sin_addr.s_addr=inet_addr (sDireccionCliente)) == ERROR) && ((rgClienteAddr.sin_addr.s_addr=hostGetByName (sDireccionCliente))==ERROR)) { perror ("Error en \"udpServidor\": Direccion del cliente desconocida\n"); close (sFd); return (ERROR); } /* giContinuar se cambia desde la funcion PararServidor */ giContinuar=-1; while(giContinuar) { /* Rellena la estructura con las temperaturas adquiridas*/ rellenarDatos(&rgTemp); /* Envia un dato al cliente */ if (sendto (sFd, (char *) &rgTemp, sizeof (rgTemp), 0, (struct sockaddr *) &rgClienteAddr, iSockAddrSize) == ERROR) { perror ("Error en el sendto de \"udpServidor\""); close (sFd); return (ERROR); } printf("Mensaje %ld enviado\n", rgTemp.lNumSec); taskDelay(sysClkRateGet()*10); } printf("Saliendo de \"udpServidor\"\n"); close (sFd); return (OK); } /* Esta funcion para el lazo infinito para que el servidor deje de enviar datagramas */ int PararServidor(void) { giContinuar=0; }

Conceptos de sockets

Page 77: Labratorio trabajando con c

Comunicaciones en VxWorks – Sockets UDP 7 de 12

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática

Los sockets son parte de los protocolos TCP / IP y originariamente se diseñaron para posibilitar la comunicación entre sistemas UNIX. VxWorks, hereda de UNIX el uso de los sockets, de hecho, la forma de utilizarlos en VxWorks es totalmente paralela al método seguido en UNIX. Para poder trabajar con sockets hay que conocer algunos conceptos relacionados con las capas inferiores de TCP/IP. Estos conceptos son la familia o dominio de conexión, así como su tipo. • Familia: Agrupa los sockets que comparten una serie de características comunes como

convenios para formar direcciones de red o para nombrar los objetos de la red. Las familias más comunes en los sistemas Unix son:

o AF_UNIX: Utiliza protocolos internos de Unix. Se suele usar para comunicar

procesos que se ejecutan en una misma máquina ya que no realiza accesos a la red.

o AF_INET: Que usa protocolos de Internet, como el TCP orientado a conexión

o UDP no orientado a conexión. Esta familia de sockets se usa para comunicar procesos entre máquinas distintas a través de la red.

o Otras familias: AF_CCITT, AF_NS, AF_SNA, AF_DECnet, AF_APPLETALK

• Tipo de conexión: Se refiere al tipo de circuito que se establece entre los dos procesos que se van a comunicar. Hay 2 tipos de circuitos.

o Virtual ( SOCK_STREAM ):

En la familia AF_INET usan el protocolo TCP.

Orientado a conexión: exigen una etapa previa a la conexión (transmisión de mensajes entre enmisor y receptor que garanticen el éxito de la comunicación posterior de los datos.

Protocolo fiable: comprueba si existen errores en la transmisión retransmitiendo aquellos mensajes incorrectos.

Con control de flujo: evita que un receptor lento quede desbordado con la llegada de mensajes de un emisor más rápido.

Permite circuitos virtuales: se conoce como STREAM o corriente de datos.

o Datagrama ( SOCK_DGRAM ):

En la familia AF_INET usan el protocolo UDP

Orientado a no conexión: no exige ningún proceso previo a la comunicación.

Sin garantía de secuencia: los datos pueden llegar desordenados

Sin garantía de fiabilidad: los datos pueden contener errores o perderse

Sin control de flujo: no controla si el receptor es capaz de aceptar datos a la misma velocidad que el emisor los envía

Page 78: Labratorio trabajando con c

Comunicaciones en VxWorks – Sockets UDP 8 de 12

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática

Mejora las prestaciones del sistemas: la red está menos tiempo ocupada • Direcciones de red: Las direcciones de red distinguen biunívocamente a cada nodo de la

red. Para hacer referencia a los nodos origen y destino de la conexión, algunas llamadas a los sockets necesitan usar un puntero a una estructura de dirección de socket. Esta estructura depende de la familia, en el caso de la familia AF_INET (los protocolos de Internet) sigue el siguiente formato:

o struct in_addr {

u_long s_addr ; /*32 bits con la identificación de la red */ }; /*y el host (en binario)*/

o struct sockaddr_in { short sin_family ; /* En este caso AF_INET*/ u_short sin_port ; /*16 bits con el número de puerto */ in_addr sin_addr ; /*id. red y host*/ char sin_zero [8] ; /*8 bytes sin usar*/ } ;

Funciones a utilizar

Este apartado no pretende ser sustituir a los manuales de Tornado (disponibles en el entorno de Tornado en versión electrónica desde la opción de Menú Help->Manual Index), sino que sólo pretende proporcionar una guía mínima con las funciones disponibles en VxWorks para realizar la práctica. Se recomienda la consulta a los manuales de Tornado para más información sobre ellas.

Funciones relacionadas con comunicaciones

socket

Descripción: Abre un descriptor para un socket.

Parámetros: domain (int): familia de protocolos. Ej: AF_INET para TCP/IP.

AF_ISO para ISO.

type (int): Tipo de socket. Ej: SOCK_STREAM – basado en conexión, SOCK_DGRAM – datagramas.

protocol (int): Protocolo del socket (normalmente 0)

bind

Page 79: Labratorio trabajando con c

Comunicaciones en VxWorks – Sockets UDP 9 de 12

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática

Descripción: Asocia un nombre a un socket. Se utilizar una estructura de tipo sockaddr. Sólo es necesario utilizarla en las operaciones que involucran lecturas de datos a través de un socket y no en los envíos.

Parámetros: s (int): Socket al que se le asociará una estructura

de tipo sockaddr.

name (struct sockaddr *): Estructura sockaddr con los datos del socket, incluyendo dirección IP, puerto...

namelen (int): Tamaño de la estructura sockaddr.

sendto

Descripción: Envía un mensaje a través de un socket.

Parámetros: s (int): Socket al que se envían los datos.

buf (caddr_t): Apuntador al buffer de datos.

bufLen (int): Longitud del buffer de datos.

flags (int): flags usados por protocolos de capas inferiores.

to (struct sockaddr *): Estructura sockaddr con la dirección del receptor

tolen (int): Tamaño de la estructura sockaddr.

recvfrom

Descripción: Recibe un mensaje de un socket.

Parámetros: s (int): Socket por el que se reciben los datos.

buf (caddr_t): Apuntador al buffer de datos.

bufLen (int): Longitud del buffer de datos.

flags (int): flags usados por protocolos de capas inferiores.

from (struct sockaddr *): Estructura sockaddr con la dirección del emisor.

pFromLen (int): Tamaño de la estructura sockaddr.

close

Descripción: En la práctica se usará para cerrar un socket.

Parámetros: fd (int): Identificador del socket a cerrar.

bzero

Descripción: Pone a ceros un buffer de memoria.

Parámetros: buffer (char *): Apuntador al buffer que se pondrá a ceros.

Page 80: Labratorio trabajando con c

Comunicaciones en VxWorks – Sockets UDP 10 de 12

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática

nbytes (int): Número de bytes que contiene el buffer.

inet_addr

Descripción: Convierte una dirección IP en un entero largo

Parámetros: inetString (char *): Cadena con la dirección IP. P.e. 158.227.67.63

hostGetByName

Descripción: Busca una dirección en la tabla de hosts.

Parámetros: inetString (char *): Cadena con el nombre del host.

P.e. bipa63.bi.ehu.es

htons

Descripción: Macro que cambia de formato un short para poder usarse en determinadas funciones de comunicaciones.

Parámetros: number (short): Número cuyo formato será cambiado.

2.4.2. Funciones relacionadas con tareas

2.4.2.1. taskSpawn

Descripción: Lanza una tarea.

Parámetros: name (char *): Nombre de la nueva tarea.

prioriry (int): Prioridad de la nueva tarea

options (int): Opciones. Utilizar 0x100.

stackSize (int): Tamaño en bytes de la pila utilizada. Utilícese 2000 bytes.

entryPt (FUNCPTR): Punto de entrada a la nueva tarea.

arg1 (int): Primero de 10 argumentos que se pasarán a la tarea.

arg2 (int)

arg10 (int)

2.4.2.2. taskDelay

Descripción: Suspende la ejecución de una tarea durante un determinado número de ciclos de reloj.

Parámetros: ticks (int): Número de ticks que se retrasa una tarea.

2.4.2.3. sysClkRateGet

Page 81: Labratorio trabajando con c

Comunicaciones en VxWorks – Sockets UDP 11 de 12

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática

Descripción: Devuelve el número de ticks del reloj del sistema que hay en un segundo.

Parámetros: No tiene.

2.4.3. Funciones relacionadas con ficheros

2.4.3.1. usrFdConfig

Descripción: monta un sistema de archivos de DOS en un disquete

Parámetros: drive (int): Número de unidad de disquete (de 0 a 3)

type (int): Tipo de disquete

0- 3.5” 1.44MB 1- 5.25” 1.2MB

fileName (char *): Punto de montaje. En VxWorks para montar en la raíz del disquete este valor debe valer “/fd0”.

2.4.4. Funciones relacionadas con el tiempo

2.4.4.1. time()

Descripción: Determina la hora del sistema en segundos desde el 1/1/1970 a las 00:00:00 en Universal Time.

Parámetros: time_t (long int): Numero de segundos devuelto desde el 1/1/1970 a las

00:00:00

2.4.4.2. localtime()

Descripción: Convierte un entero largo con los segundos desde el 1/1/1970 a las 00:00:00 en UTC (Universal Time Coordinated) en una estructura predefinida con el tiempo local: struct tm { int tm_sec; /* Segundos 0-59*/ int tm_min; /* Minutos 0:59*/ int tm_hour; /* Horas 0-23*/ int tm_mday; /* Día del mes 1-31*/ int tm_mon; /* Mes 0-11*/ int tm_year; /* Años desde 1900*/ int tm_wday; /* Día de la semana 0-6*/ int tm_yday; /* Día del año 0-365*/ int tm_isdst; /* Cambio horario*/

Parámetros: time_t (long int): Numero de segundos devuelto desde el

1/1/1970 a las 00:00:00

Page 82: Labratorio trabajando con c

- I -

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática

Sockets TCP

Informática Industrial (Ingeniería en Electrónica y Automática)

Departamento de Ingeniería de Sistemas y Automática

Page 83: Labratorio trabajando con c

- II -

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática

INDICE

1. Introducción .............................................................................................................. 1

2. Objetivos ................................................................................................................... 2

3. Se pide: ..................................................................................................................... 2

4. Apéndices ................................................................................................................. 2

4.1. Estructuras para enviar y recibir datos en las tramas TCP ............................... 3

4.2. Algunos includes y defines a utilizar ................................................................ 3

4.3. Código para montar la disquetera ..................................................................... 4

4.4. Conceptos de sockets ........................................................................................ 5

4.5. Funciones a utilizar ........................................................................................... 7 4.5.1. Funciones relacionadas con el manejo de direcciones (inetLib.h) ........... 7 4.5.2. Funciones relacionadas con el manejo de sockets (sockLib.h) ................ 9 4.5.3. Esquemas de comunicación Cliente Servidor ........................................ 13 4.5.4. Funciones relacionadas con tareas (taskLib.h) ....................................... 14 4.5.5. Funciones relacionadas con ficheros ...................................................... 15 4.5.6. Funciones relacionadas con el tiempo (time.h) ...................................... 15

Page 84: Labratorio trabajando con c

Comunicaciones en VxWorks – Sockets TCP 1 de 16

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática

15. Introducción

En la presente práctica se va a implementar un sistema de control distribuido compuesto por varios ordenadores. Uno de ellos, el control de planta, actúa como supervisor de los controladores de célula. Los controladores de célula recogen, con tarjetas de adquisición de datos, una serie de valores que envían al supervisor de planta el cual retorna un número de secuencia y una nueva referencia. Los datos de la planta se envían entre los diferentes componentes del sistema distribuido, a través de una red Ethernet basándose en el modelo Cliente-Servidor.

Para un posterior análisis de los datos, los controladores de célula registran, en un fichero de texto, tanto los datos de los sensores como la nueva referencia recibida desde el controlador de planta, junto con el instante en que se ha recibido la nueva referencia.

El siguiente dibujo ilustra el proceso seguido para analizar los datos.

TCP/IP sobre Ethernet

Servidor: Recibe datos de los sensores, calcula el valor de la nueva referencia y lo envía al cliente.

Cliente: Envía datos leídos por sensores y recibe el nuevos valor de referencia.

Registra en un fichero de texto tanto unos como otros.

Fichero de texto con los datosAnálisis de los datos

Cliente

Fichero de texto con los datos

Cliente

Fichero de texto con los datos

TCP/IP sobre Ethernet

Servidor: Recibe datos de los sensores, calcula el valor de la nueva referencia y lo envía al cliente.

Cliente: Envía datos leídos por sensores y recibe el nuevos valor de referencia.

Registra en un fichero de texto tanto unos como otros.

Fichero de texto con los datosAnálisis de los datos

Cliente

Fichero de texto con los datos

Cliente

Fichero de texto con los datos

Cliente

Fichero de texto con los datos

Tanto los datos de los controladores de célula (Cliente) como los del controlador de planta (Servidor) se envían a través de una red Ethernet habiéndose escogido el protocolo TCP/IP para distribuirlos.

Para la realización de esta práctica se ha escogido el protocolo TCP, orientado a conexión, en lugar del protocolo UDP, basado en datagramas, es por su mayor fiabilidad.

Los datos que se enviarán en las tramas TCP consistirán en las siguientes estructuras, que habrá que definir en el fichero “DatosTCP.h”:

typedef struct { int iDia, iMes, iAnyo, iHora, iMinutos, iSegundos ; } t_rgFechaHora ; typedef struct { t_rgFechaHora rgInstante ; long int lNumSecEnv ; /* Numero de secuencia */ short int iSensor_1 ; float rSensor_2 ; } trgDatoEnviado ; typedef struct {

Page 85: Labratorio trabajando con c

Comunicaciones en VxWorks – Sockets TCP 2 de 16

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática

long int lNumSecRec ; /* Numero de secuencia */ float rNuevaReferencia ; } trgDatoRecibido ;

La información que el cliente (controlador de célula) guardará en un fichero de texto, cuyo nombre se pedirá previamente por teclado, tendrán el siguiente formato: Fecha Hora nº sec. Envio Sensor1 Sensor2 nº sec. Rec. Referencia Donde los formatos de cada uno de los datos son: Fecha dd/mm/aa

Hora hh:mm:ss Nº de secuencia xxxx Valores del sensor 1 xx Valores del sensor 2 xxx.xx Valores de la referencia xxx.xxx

16. Objetivos Los objetivos principales de esta práctica son los siguientes:

• Simular el funcionamiento un sistema simplificado de control distribuido.

• Ilustrar cómo usar las comunicaciones con los protocolos TCP/IP.

• Escribir datos en ficheros bajo el S.O. VxWorks.

• Utilizar las funciones de hora del sistema.

17. Se pide:

Desarrollar el programa que ejecutará en ordenador cliente.

El programa en primer lugar preguntara si se ha montado la disquetera y si la respuesta es negativa procederá a “montarla”.

Seguidamente, preguntará el nombre del fichero donde guardar los datos.

Posteriormente, y de modo continuo, preguntará si se quiere recibir una nueva referencia:

• Si la respuesta es afirmativa leerá la fecha y la hora del sistema, leerá los valores de los sensores y enviará los datos al servidor. El número de secuencia es un número entero que se va incrementando con cada envío

Nota: Para simular la lectura de las tarjetas de adquisición de datos se generarán de manera aleatoria el valor de los dos sensores (el rango de valores del sensor 1 es entre 10 y 15, y el del sensor 2 entre 100.0 y 125.0).

Esperará la llegada de la trama de datos del servidor con el nuevo valor de referencia

Escribirá los datos en el fichero, de acuerdo con el formato descrito anteriormente.

• Si la respuesta es negativa se finalizará la ejecución del programa.

18. Apéndices

Page 86: Labratorio trabajando con c

Comunicaciones en VxWorks – Sockets TCP 3 de 16

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática

Estructuras para enviar y recibir datos en las tramas TCP /************** Contenido del fichero DatosTCP.h ****************/ #define PUERTO_SERVIDOR 5002 #define DIRECCION_SERVIDOR "158.227.64.52" /* Estructura para almacenar la información temporal de un instante */ typedef struct { int iDia, iMes, iAnyo, iHora, iMinutos, iSegundos ; } t_rgFechaHora ; /* Estructura enviada desde los clientes */ typedef struct { t_rgFechaHora rgInstante ; long int lNumSecEnv ; /* Numero de secuencia */ short int iSensor_1 ; float rSensor_2 ; } trgDatoEnviado ; /* Estructura recibida desde el servidor */ typedef struct { long int lNumSecRec ; /* Numero de secuencia */ float rNuevaReferencia ; } trgDatoRecibido ;

Algunos includes y defines a utilizar /******************************* includes ********************************/ #include "inetLib.h" #include "ioLib.h" #include "sockLib.h" #include "stdioLib.h" #include "strLib.h" #include "sysLib.h" #include "string.h" #include "fioLib.h" #include "taskLib.h" #include "time.h" #include "usrLib.h" #include "vxWorks.h" #include "DatosTCP.h" /* Contiene la declaracion de estructuras de datos, el PUERTO_SERVIDOR y DIRECCIÓN_SERVIDOR */ ... /*************** definiciones para la compilacion condicionada ************/ #define ESCRIBIR_EN_FICHERO ...

Page 87: Labratorio trabajando con c

Comunicaciones en VxWorks – Sockets TCP 4 de 16

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática

/********************** definicion de constantes globales ****************/ #define TRUE 1 #define FALSE 0 #define MIN_SENSOR_1 10 #define MAX_SENSOR_1 15 #define MIN_SENSOR_2 100.0 #define MAX_SENSOR_2 125.0 #define DISQUETERA_A "/fd0/" #define EXTENSION_FICHEROS ".txt" /* ejemplo de nombre fichero: "/fd0/datos.txt” */ ...

Código para montar la disquetera /*************************************************************************/ /* MontarDisco */ /*************************************************************************/ void MontarDisco (void) { printf("Montando Disco...") ; /* Unidad 0, disquete 3,5", montar en directorio raiz */ if ( usrFdConfig (0, 0, "/fd0") == ERROR ) { perror ( "Error en funcion: \"MontarDisco\"" ) ; perror ( "Error montando la disquetera" ) ; } else printf ( "...Disco montado\n" ) ; } /* MontarDisco */

Page 88: Labratorio trabajando con c

Comunicaciones en VxWorks – Sockets TCP 5 de 16

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática

Conceptos de sockets Los sockets son parte de los protocolos TCP/IP y originariamente se diseñaron para posibilitar la comunicación entre sistemas UNIX. VxWorks, hereda de UNIX el uso de los sockets, de hecho, la forma de utilizarlos en VxWorks es totalmente paralela al método seguido en UNIX.

Para poder trabajar con sockets hay que conocer algunos conceptos relacionados con las capas inferiores de TCP/IP. Estos conceptos son la familia o dominio de conexión, así como su tipo.

• Familia: Agrupa los sockets que comparten una serie de características comunes como

convenios para formar direcciones de red o para nombrar los objetos de la red. Las familias más comunes en los sistemas UNIX son:

o AF_UNIX: Utiliza protocolos internos de UNIX. Se suele usar para comunicar procesos que se ejecutan en una misma máquina ya que no realiza accesos a la red. Utilizan manejadores de ficheros.

o AF_INET: Utiliza protocolo de Internet, como el TCP orientado a conexión o UDP no orientado a conexión. Esta familia de sockets se usa para comunicar procesos entre máquinas distintas a través de la red.

o Otras familias: AF_CCITT, AF_NS, AF_SNA, AF_DECnet, AF_APPLETALK • Tipo de conexión: Se refiere al tipo de circuito que se establece entre los dos procesos

que se van a comunicar.

o Virtual ( SOCK_STREAM ):

En la familia AF_INET usan el protocolo TCP.

Orientado a conexión: exigen una etapa previa a la conexión (transmisión de mensajes entre emisor y receptor que garanticen el éxito de la comunicación posterior de los datos).

Protocolo fiable: comprueba si existen errores en la transmisión retransmitiendo aquellos mensajes incorrectos.

Con control de flujo: evita que un receptor lento quede desbordado con la llegada de mensajes de un emisor más rápido.

Permite circuitos virtuales: se conoce como STREAM o corriente de datos.

o Datagrama ( SOCK_DGRAM ):

En la familia AF_INET usan el protocolo UDP.

Orientado a no conexión: no exige ningún proceso previo a la comunicación.

Sin garantía de secuencia: los datos pueden llegar desordenados.

Sin garantía de fiabilidad: los datos pueden contener errores o perderse.

Sin control de flujo: no controla si el receptor es capaz de aceptar datos a la misma velocidad que el emisor los envía.

Mejora las prestaciones del sistema: la red está menos tiempo ocupada.

o SOCK_SEQPAQUET, SOCK_RDM, SOCK_RAW…

Page 89: Labratorio trabajando con c

Comunicaciones en VxWorks – Sockets TCP 6 de 16

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática

• Direcciones de red: Las direcciones de red distinguen biunívocamente a cada nodo de la red. Para hacer referencia a los nodos origen y destino de la conexión, algunas llamadas a los sockets necesitan usar un puntero a una estructura de dirección de socket.

Las estructuras de datos y las funciones a utilizar están definidas en los ficheros de cabecera:

#include "sockLib.h" #include "inetLib.h" #include "hostLib.h"

La mayoría de las funciones suelen utilizar como parámetro una estructura genérica para especificar los datos de un socket:

o struct sockaddr { sa_family_t as_family ; /* familia de sockets */ char sa_data [14] ; /* hasta 14 bytes con la dirección */ } ;

Es tan genérica que sirve para cualquier tipo de socket, normalmente utilizaremos estructuras específicas que ocupan el mismo número de bytes y que podremos forzar con un cast o molde al tipo base struct sockaddr cuando tengamos que pasarla como parámetro. El primer campo, as_family, especifica la familia (AF_UNIX o AF_INET) y el segundo, sa_data, la dirección adecuada para cada familia. Las estructuras específicas dependen de la familia. En el caso de la familia AF_INET (los protocolos de Internet) siguen el siguiente formato:

o struct in_addr {

u_long s_addr ; /* 32 bits con la identificación de la red */ } ; /* y el host (en binario) */

o struct sockaddr_in { short sin_family ; /* en este caso AF_INET */ u_short sin_port ; /* 16 bits con el número de puerto */ in_addr sin_addr ; /* id. red y host – dirección IP */ char sin_zero [8] ; /* 8 bytes sin usar */ };

NOTA: Antes de rellenar la estructura sockaddr_in, con la información de la familia, la dirección y el puerto, es aconsejable rellenarla con ceros usando la función bzero.

Ejemplo: struct sockaddr_in rgDatosSocket ; int iDatosSocketSize ; ... iDatosSocketSize = sizeof (struct sockaddr_in) ; bzero ( (char *) &rgDatosSocket, iDatosSocketSize) ;

Page 90: Labratorio trabajando con c

Comunicaciones en VxWorks – Sockets TCP 7 de 16

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática

Funciones a utilizar Este apartado no pretende ser sustituir a los manuales de Tornado (disponibles en el entorno de Tornado en versión electrónica desde la opción de Menú Help->Manual Index o en el fichero vxWorks reference's manual.pdf), sino que sólo pretende proporcionar una guía mínima con las funciones disponibles en VxWorks para realizar la práctica. Se recomienda la consulta a los manuales de Tornado para más información sobre ellas.

Funciones relacionadas con el manejo de direcciones (inetLib.h)

Conversión de dirección con formato IP a entero largo

u_long inet_addr (const char * inetString ) ;

inetString puntero a cadena con una dirección en formato IP. Por ejemplo: “90.0.0.2”

Descripción: Retorna al dirección intenet como entero largo (por ejemplo,

0x5a000002) o la constante ERROR.

Conversión de entero largo a dirección con formato IP

char * inet_ntoa (struct in_addr inetAddress ) ;

inetAddress estructura con el valor de una dirección IP expresada como entero largo. Por ejemplo: 0x5a000002

Descripción: Retorna un puntero a una cadena de caracteres que

representan una dirección IP (por ejemplo, “90.0.0.2”) o la constante ERROR.

Ejemplo:

char inetString [20] ; struct in_addr inetAddress ; ... iaddr.s_addr = 0x5a000002; ... strcpy (inetString, inet_ntoa (inetAddress)) ;

Conversión de direcciones de host y números de puerto a direcciones de red y viceversa

Cuando se programa una aplicación distribuida debemos tener en cuenta que puede correr sobre distintas máquinas, que puede codificar los números de forma distinta: algunos utilizan codificación big-endian y otros little-endian. Para evitar los errores el intercambio de datos numéricos a través de una red (entre ellos direcciones IP y

Page 91: Labratorio trabajando con c

Comunicaciones en VxWorks – Sockets TCP 8 de 16

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática

puertos) es necesario utilizar una codificación estándar. Esta codificación se denomina codificación de red.

Hay cuatro macros que permiten la conversión entre diferentes formatos (long y short a codificación de red y viceversa):

htonl - Entero largo (dirección IP) a codificación de red: in_addr_t htonl (in_addr_t hostLong ) ;

htons - Entero corto (nº de puerto) a codificación de red: in_port_t htons (in_port_t hostShort ) ;

ntonl - Codificación de red a entero largo (dirección IP) : in_addr_t ntohl (in_addr_t netLong ) ;

ntohs - Codificación de red a entero corto (nº de puerto): in_addr_t ntohs (in_addr_t netLong ) ;

Ejemplo :

#define PUERTO_DEL_SERVIDOR 5002 ...

• El cliente TCP ( va a enviar el número de puerto ): struct sockaddr_in datosSocket ; /* declarar variable */ ... /* rellenar el campo: número de puerto*/ datosSocket.sin_port = htons (PUERTO_DEL_SERVIDOR)

• El servidor TCP ( va a recibir el número de puerto ): /* declarar variables */ int socketServidor, newSocket ; struct sockaddr_in datosSocketCliente ; int datosSocketSize ; ... /* aceptar peticiones */ newSocket = accept (socketServidor, (struct sockaddr *) &datosSocketCliente, &datosSocketSize) ;

/*Recibido los datos de socket que ha establecido conexión*/ printf ("\Recibida peticion de conexion: \n\tdireccion: %s" "y\n\t puerto: %d", inet_ntoa (datosSocketCliente.sin_addr), ntohs (datosSocketCliente.sin_port)) ;

Page 92: Labratorio trabajando con c

Comunicaciones en VxWorks – Sockets TCP 9 de 16

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática

Funciones relacionadas con el manejo de sockets (sockLib.h)

Creación de un socket

int socket (int domain, int type, int protocol ) ;

domain familia o dominio de protocolos: AF_UNIX, AF_INET, … type tipo de conexión: SOCK_STREAM, SOCK_DGRAM, … protocol protocolo que se desea utilizar. (0 por omisión)

Descripción: Reserva memoria y realiza las inicializaciones necesarias

para el tipo de comunicación especificada. Crea un punto terminal para conectarse a un canal bidireccional, devolviendo un manejador de tipo entero (similar a un manejador de E/S estándar). El manejador identifica al socket en el resto de funciones.

En caso de error devuelve el valor -1, y en la variable global errno queda codificado el error producido

Asignar dirección y puerto al socket. Publicar la dirección

int bind (int sfd, struct sockaddr * name , int name_len) ;

sfd descriptor del socket name puntero a la estructura que contiene los datos específicos del

socket (dirección, puerto, …). Si se utilizar una estructura sockaddr_in se debe hacer un cast al tipo struct sockaddr *

name_len tamaño de la estructura name Descripción: Asocia el descriptor del socket sfd a la estructura name

(dirección IP, puerto específico, …) y la hace pública.

Si la operación se realiza correctamente devuelve el valor 0. En caso de error devuelve el valor -1, y en la variable global errno queda codificado el error producido

Esta operación solamente es necesario realizarla en el servidor, debido a que toda comunicación es iniciada por un proceso cliente, por lo que el socket servidor es el único que debe ser público. En el cliente también se realiza pero de manera automática cuando el cliente inicia una comunicación.

Page 93: Labratorio trabajando con c

Comunicaciones en VxWorks – Sockets TCP 10 de 16

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática

Transmisión de información

Debemos distinguir entre sockets de tipo Datagrama o UDP y sockets de tipo Stream o TCP.

Transmisión de información en sockets de tipo Datagrama

El cliente inicia la transmisión enviando un mensaje al socket del servidor mediante la función sendto, que tiene como parámetros la descripción, dirección y puerto, del socket destino (servidor).

El servidor espera pasivamente la recepción de datos en su socket mediante la función recvfrom. En el momento en que recibe un mensaje dicha función devuelve el control, indicando el mensaje recibido y la descripción del socket que lo ha enviado (socket cliente). Por ello el servidor también puede responder, estableciéndose una comunicación bidireccional. int sendto (int sfd, void * message, int messsage_len, int flags,

struct sockaddr * dest_name , int dest_name_len) ; sfd descriptor del socket message puntero al buffer que contiene los datos que se envían message_len tamaño del buffer flags permite controlar ciertos aspectos de la comunicación.

Normalmente se pone a 0. dest_name puntero a la estructura que contiene los datos específicos

del socket (dirección, puerto, …). dest_name_len tamaño de la estructura dest_name Descripción: Devuelve el número de bytes enviados, o -1 en caso de error.

int recvfrom (int sfd, char * message, int messsage_len, int flags,

struct sockaddr * orig _name , int * name_len) ; sfd descriptor del socket message puntero al buffer que contiene los datos que recibidos message_len tamaño del buffer message flags permite controlar ciertos aspectos de la comunicación.

Normalmente se pone a 0. orig_name puntero a la estructura que contiene los datos específicos

del socket (dirección, puerto, …) que ha enviado el mensaje.

orig_name_len tamaño de la estructura orig_name Descripción: Devuelve el número de bytes recibidos, o -1 en caso de error.

Page 94: Labratorio trabajando con c

Comunicaciones en VxWorks – Sockets TCP 11 de 16

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática

Transmisión de información en sockets de tipo Stream

Antes de comenzar la transmisión de datos es preciso establecer un canal virtual para la conexión:

El servidor se queda a la escucha de peticiones de conexión. Mediante listen especifica el tamaño de la cola de espera para admitir peticiones de conexión. Mediante accept se queda a la escucha de peticiones de conexión (quedando el proceso en espera). A este socket se le denomina socket de escucha.- Cuando se establece la conexión, la función accept retorna el control creando un nuevo socket (socket de dialogo) por el cual puede comenzar la comunicación de datos. También devuelve la dirección del socket cliente que solicitó la conexión de forma que la transmisión pueda ser bidireccional. En el servidor, por tanto, existen más de un socket: uno que acepta conexiones (el que creamos nosotros) y otro que crea el sistema operativo por cada conexión que se establece. Se pueden aceptar tantas conexiones como se hayan indicado con la función listen. El cliente, mediante la función connet, se encarga de establecer la conexión entre el socket creado y el especificado en la estructura name.

int listen (int sfd, int max_conex) ;

sfd descriptor del socket max_conex tamaño de la cola de peticiones de conexión Descripción: Si funciona correctamente devuelve 0, y en caso de error -1.

int accept (int sfd, struct sockaddr * client_name, int * client_name_len) ;

sfd descriptor del socket client_name puntero a la estructura que contiene datos específicos

del socket (dirección, puerto, …). La función accept rellena esta estructura con la dirección del socket remoto que ha pedido la conexión.

client_name_len tamaño real de la estructura client_name leída Descripción: Si funciona correctamente devuelve el descriptor del nuevo

socket creado que corresponde al socket remoto aceptado. En caso de error devuelve -1.

Page 95: Labratorio trabajando con c

Comunicaciones en VxWorks – Sockets TCP 12 de 16

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática

int connect (int sfd, struct sockaddr * serv_name, int * serv_name_len) ;

sfd descriptor del socket serv_name puntero a la estructura que contiene datos específicos

del socket remoto (dirección, puerto, …) con el que se desea conectar

client _name_len tamaño real de la estructura serv_name leída Descripción: Intenta una conexión quedando la llamada bloqueada hasta

que se establece la conexión. Si funciona correctamente devuelve un 0 y en caso contrario devuelve -1.

Una vez establecida la conexión ambos procesos pueden comenzar la comunicación a través del socket de diálogo. En este caso, las funciones no precisan más información que el identificador del socket ya que el resto de datos están asociados a la conexión.

Se pueden utilizar las funciones específicas recv y send, o las funciones genéricas de entrada/salida estándar write/read. También se pueden utilizar las funciones recvfrom y sendto utilizadas en los sockets de tipo datagrama aunque en este caso el parámetro que especifica la dirección IP y el puerto no se utiliza. En la comunicación orientada a conexión se transmiten flujos de datos, por lo que la lectura puede corresponder a sólo una parte del mensaje enviado. Deberemos establecer por tanto un bucle de lectura que itere hasta que no existan mas datos en stream o hayamos leído el número de bytes esperados. int send (int sfd, const char * message, int messsage_len, int flags) ;

sfd descriptor del socket message puntero al buffer que contiene los datos que se envían message_len tamaño del buffer flags permite controlar ciertos aspectos de la comunicación.

Normalmente se pone a 0. Descripción: Devuelve el número de bytes enviados, o -1 en caso de error.

int recv (int sfd, void * message, size_t messsage_len, int flags) ;

sfd descriptor del socket message puntero al buffer que contiene los datos que recibidos message_len tamaño del buffer flags permite controlar ciertos aspectos de la comunicación.

Normalmente se pone a 0. Descripción: Devuelve el número de bytes recibidos, o -1 en caso de error.

int write (int sfd, char * message, size_t messsage_len) ;

sfd descriptor del socket message puntero al buffer que contiene los datos que se envían message_len tamaño del buffer flags permite controlar ciertos aspectos de la comunicación.

Normalmente se pone a 0. Descripción: Devuelve el número de bytes enviados, o -1 en caso de error.

Page 96: Labratorio trabajando con c

Comunicaciones en VxWorks – Sockets TCP 13 de 16

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática

int read (int sfd, char * message, size_t messsage_len) ;

sfd descriptor del socket message puntero al buffer que contiene los datos que recibidos message_len tamaño máximo del buffer flags permite controlar ciertos aspectos de la comunicación.

Normalmente se pone a 0. Descripción: Devuelve el número de bytes recibidos, o -1 en caso de error.

Eliminación del socket

STATUS shutdown (int sfd, int how) ;

sfd descriptor del socket how Sentido del cierre: recepción de datos (0) , envío de datos

(1) y en ambos sentidos (2) Descripción: Cierra el canal en un sentido o en ambos.

STATUS close (int sfd) ;

sfd descriptor del socket Descripción: Cierra el canal en los dos sentidos (recepción y envío).

Esquemas de comunicación Cliente Servidor

Esquema Cliente-Servidor con sockets no orientados a conexión

Devolver respuesta

Pedir servicio

Abrir canal socket ( )

bind ( )

revfrom ( )

sendto ( )

Servidor

socket ( )

bind ( )

sendto ( )

revfrom ( )

shutdown ( )

Cliente

Asociar dirección

Cerrar canal

Devolver respuesta

Pedir servicio

Abrir canal socket ( )

bind ( )

revfrom ( )

sendto ( )

Servidor

socket ( )socket ( )

bind ( )bind ( )

revfrom ( )revfrom ( )

sendto ( )sendto ( )

Servidor

socket ( )

bind ( )

sendto ( )

revfrom ( )

shutdown ( )

Cliente

socket ( )socket ( )

bind ( )bind ( )

sendto ( )sendto ( )

revfrom ( )revfrom ( )

shutdown ( )

Cliente

Asociar dirección

Cerrar canal

Page 97: Labratorio trabajando con c

Comunicaciones en VxWorks – Sockets TCP 14 de 16

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática

Esquema Cliente-Servidor con sockets orientados a conexión

socket ( )

bind ( )

listen ( )

accept ( )

recv ( )

send ( )

socket ( )

connect ( )

send ( )

recv ( )

close ( )

Devolver respuesta

Pedir servicio

Establecer conexión

Servidor

Cliente

Abrir canal

Asociar y publicardirección

Disponerse a aceptar peticiones

Aceptar peticionesAbrir canal

Pedir conexión

Cerrar canal

socket ( )socket ( )

bind ( )bind ( )

listen ( )listen ( )

accept ( )accept ( )

recv ( )recv ( )

send ( )send ( )

socket ( )socket ( )

connect ( )connect ( )

send ( )send ( )

recv ( )recv ( )

close ( )close ( )

Devolver respuesta

Pedir servicio

Establecer conexión

Servidor

Cliente

Abrir canal

Asociar y publicardirección

Disponerse a aceptar peticiones

Aceptar peticionesAbrir canal

Pedir conexión

Cerrar canal

Funciones relacionadas con tareas (taskLib.h)

Crear y lanzar una tarea

int taskSpawn (const char * nombre, int prioridad, int opciones, int stacksize, entryPt (FUNCPTR) nombreFunción, int arg1, int arg2, int arg3, ... , int arg10) ;

nombre de la nueva tarea (una cadena de caracteres ASCII).

prioridad (0-255). Siendo 0 la máxima prioridad y 255 la mínima

opciones. Es un valor hexadecimal o una constante predefinida: VX_FP_TASK (0x0008), VX_NO_STACK_FILL (0x0100), VX_PRIVATE_ENV (0x0080), VX_UNBREAKABLE (0x0002)

tamaño de la pila o stacksize en bytes (int).

dirección o nombre de la rutina principal ejecutada por la tarea. Su tipo debe ser FUNCPTR.

y 10 argumentos que se pasarán a la rutina principal como parámetros de arranque.

Page 98: Labratorio trabajando con c

Comunicaciones en VxWorks – Sockets TCP 15 de 16

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática

Ejemplo:

int LanzarTarea (void) /* funcion que crea y lanza la tarea */ { int t_taskID ; /* ID Identificador de la tarea */ char * sNombreTarea = "tTarea_1" ; /* Nombre de la tarea */ if ( (t_taskID = taskSpawn(sNombreTarea, 120, VX_NO_STACK_FILL,2000, (FUNCPTR) NombreFuncion,0,0,0,0,0,0,0,0,0,0)) == ERROR ) { printf ("\nNO SE HA PODIDO CREAR LA TAREA: %s\n", sNombreTarea) ; exit (-1) ; } return (0) ; } /* LanzarTarea */ void NombreFuncion (void) /* función ejecutada por la tarea */ { ... }

Funciones relacionadas con ficheros

Montar un sistema de archivo DOS en un disquete

int usrFdConfig (int drive, int type, char * fileName) ;

drive Número de unidad de diquete (de 0 a 3) type (0-255) Tipo de disquete: 0 - 3.5” 1.44MB

1 - 5.25” 1.2MB fileName Punto de montaje. En VxWorks para montar en la raíz del

disquete este valor debe valer “/fd0”. Descripción: monta un sistema de archivos de DOS en un disquete Ejemplo: int usrFdConfig (0, 0, “/fd0”) ;

Funciones relacionadas con el tiempo (time.h)

Determinar la fecha y la hora del sistema

time_t time (time_t * timer) ; Descripción: Devuelve el número de segundos transcurridos desde las

00:00:00 GMT del día 1 de enero de 1970.

Page 99: Labratorio trabajando con c

Comunicaciones en VxWorks – Sockets TCP 16 de 16

Isidro Calvo y A. Fabián López Informática Industrial Dpto. Ingeniería de Sistemas y Automática

Ejemplo: time_t t ; t = time(NULL) ;

Convertir un número de segundos en la fecha y hora locales correspondientes

struct tm* localtime (const time_t * timer) ; timer Números de segundos transcurridos desde las

00:00:00 GMT horas del 1 de enero de 1970. Descripción: Retorna un puntero a una estructura struct tm. Esta

estructura es estática y es sobrescrita en cada llamada a localtime.

struct tm { int tm_sec ; /* Segundos 0-59*/ int tm_min ; /* Minutos 0:59*/ int tm_hour ; /* Horas 0-23*/ int tm_may ; /* Día del mes 1-31*/ int tm_mon ; /* Mes 0-11*/ int tm_year ; /* Años desde 1900*/ int tm_wday ; /* Día de la semana 0-6*/ int tm_yday ; /* Día del año 0-365*/ int tm_isdst ; /* Cambio horario */ } ;

Ejemplo:

time_t Segundos ; struct tm * puntFechaHora ; struct tm FechaHora ; Segundos = time(NULL) ; puntFechaHora = localtime (Segundos); FechaHora = * puntFechaHora ;