Anda di halaman 1dari 57

UNIVERSIDAD NACIONAL DE INGENIERÍA

FACULTAD DE INGENIERÍA INDUSTRIAL Y DE SISTEMAS


SISTEMAS OPERATIVOS – ST324

TRABAJO DE INVESTIGACIÓN-ETAPA FINAL


“GESTIÓN DE PROCESOS, MEMORIA y E/S”

Grupo N° “1”
Nro Not
Código Apellidos y Nombres Letras
. a
1 20121142E Ramírez Ramos , Marco
2 20140061G Salcedo Tolentino, Jack Dennis

PROFESOR: RAMOS MONTES, CARLOS

12 de julio de 2017
2017-I

INDICE

I RESUMEN

II INTRODUCCIÓN

III OBJETIVO DEL TRABAJO


III.1 Objetivos Generales
III.2 Objetivos Específicos

IV DESCRIPCIÓN DEL TRABAJO


IV.1 Antecedentes y marco teórico.
IV.2 Requisitos obtenidos para el trabajo.
IV.3 Definición de supuestos y restricciones.
IV.4 Desarrollo del trabajo
IV.5 Pruebas y medidas aplicadas.
IV.6 Logros obtenidos.

V CONCLUSIONES

VI PRÓXIMAS MEJORAS E IMPLEMENTACIONES.

VII ANEXOS
VII.1 Manual de usuario.
VII.2 Código fuente del sistema.

pág. 2
I. RESUMEN

En la presentación avance de la Gestión de Procesos, Memoria y E/S


desarrollaremos los conceptos aprendidos en las sesiones elaboradas en clase.
Aplicaremos conceptos tales como:
 Los procesos se encuentra en una base de datos a la cual accedemos por
conexión por el MySQL.
 La información que guardamos de los procesos son: un código (se genera
automáticamente), la duración del proceso, el tiempo de llegada del proceso, el
estado en que se encuentre el proceso y finalmente el tamaño de memoria que
usará este proceso.
 Los procesos se pueden visualizar cómo interactúan con las interrupciones
generadas aleatoriamente.
 Asignación de memoria, con las respectivas estrategias de asignación. Para
nuestro caso en particular hemos puesto en práctica el First fit, best fit y worst
fit para ver la distribución de los procesos en cada caso.
 Hemos considerado que los procesos que ingresan a la memoria RAM lo
harán siempre y cuando exista espacio suficiente para su respectivo tamaño.
 Aplicación de la Paginación. Hemos dividido la Memoria RAM en frame para el
S.O y los demás para los procesos existentes.
 La parte de E/S se determina por interrupciones con cierto tiempo de duración.
 El sistema tiene muchas interfaces para la interacción con el usuario.

II. INTRODUCCIÓN:

pág. 3
En esta presentación trataremos el tema de Gestión de Procesos, Memoria y
E/S; de tal manera que abarcaremos todos los conceptos explicados en clase,
vale decir que hemos conectado ambos temas y lo hemos desarrollado en su
totalidad.

Este trabajo está implementado con el fin de comprender los conceptos de


Memoria mediante una simulación de un Sistema Operativo que gestiona la
asignación de memoria que se les da a los procesos, los cuales tienen un
estado y será el estado Nuevo el que le permitirá al proceso insertarse en la
Memoria RAM.

III. OBJETIVO DEL TRABAJO

III.1 OBJETIVOS GENERALES

pág. 4
Crear un simulador para la gestión de Procesos, Memoria y E/S;
utilizando interfaces gráficas para su entendimiento.

III.2 OBJETIVOS ESPECIFICOS

 Trabajar con hilos para los procesos e interrupciones y mostrar cómo


interactúan ambos en tiempo de ejecución.
 La secuencia de ejecución para nuestro simulador será el área de
procesos, memoria y finalmente las interrupciones en los procesos
debido a que se desea mostrar de forma didáctica cada función por
área.
 Usar solo un procesador y así trabajar con una programación simple
para los procesos.
 Utilizar uno de los algoritmos de planificación para la gestión de
procesos.
 Direccionar la memoria RAM por frame para la ubicación de procesos.
 Utilizar la estrategia de asignación “Best fit” para evitar el mínimo
volumen de fragmentación interna.
 Mostrar gráficamente como se van ubicando los procesos en memoria
para cada estrategia de asignación de memoria y ver su posible
comportamiento.

IV. DESCRIPCIÓN DEL TRABAJO

IV.1. Antecedentes y Marco Teórico

Un proceso es básicamente un entorno formado por todos los recursos


necesarios para ejecutar programas. Desde el punto de vista del SO, un
proceso es un objeto más que hay que gestionar y al cual hay que dar servicio
Podemos decir que un programa es una entidad pasiva, en tanto en cuanto es
un conjunto de instrucciones de código máquina y datos almacenados en un
ejecutable. Mientras que un proceso sería la ejecución de ese programa, es
decir, el programa en acción. Esto indica que los procesos son dinámicos,
están en constante cambio debido a estos recursos necesarios, ya que al
intentar realizar algún tipo de acción puede ser que tenga que permanecer a la
espera de que dicho recurso esté disponible, por ejemplo una petición de
lectura del disco duro, y que el brazo lector del disco duro lo esté utilizando
otro proceso.
Al igual que las instrucciones de programa, los procesos incluyen los
contadores de programa que indican la dirección de la siguiente instrucción
que se ejecutará de ese procesos y los registros de CPU, así como las pilas
que contienen datos temporales, como son los parámetros de subrutina, las
direcciones de retorno y variables locales. Los procesos también contienen
una sección de datos con variables globales y memoria dinámica. Todo ello

pág. 5
permite gestionar de una manera más eficaz los procesos en los sistemas
operativos multiprocesos, ya que cada proceso es independiente, por lo que el
bloqueo de uno no debe de hacer que otro proceso en el sistema se bloquee.
En estos sistemas operativos multiproceso se intenta maximizar la utilización
de la CPU, por lo que los procesos se ejecutan simultáneamente en la CPU y
sólo quedan a la espera de ejecución si requieren de algún recurso del sistema
que esté ocupado en ese momento, en cuanto obtiene dicho recurso podrá
ejecutarse de nuevo. Todo este proceso de gestión lo realiza el sistema
operativo, por lo que es el que decide si un proceso es más prioritario que
otros. Es el programador el que decide esta prioridad, por ejemplo en el caso
de Linux se utiliza un número en la programación de estrategias para
garantizar la equidad de los procesos.
Cada proceso se representa en el sistema operativo con un bloque de control
de proceso (PCB). En este PCB se guardan una serie de elementos de
información de los mismos. Estos elementos son: el identificador del proceso,
el estado del proceso, registros de CPU (acumuladores, punteros de la pila,
registros índice y registros generales), información de planificación de CPU
(prioridad de proceso, punteros a colas de planificación, etc.), información de
gestión de memoria, información de contabilidad (tiempo de uso de CPU,
números de procesos, etc.), información de estado de dispositivos E/S (lista de
archivos abiertos, etc.)

2.1.1. ESTADO DE UN PROCESO

En un sistema multiprogramado o multitarea donde existen muchos


procesos y un procesador, puede ocurrir que en un momento dado sólo se
ejecute un proceso o varios y los demás estén esperando a ser procesado o
esperen la finalización de una operación de E/S. Los pasos por los que puede
pasar un proceso se pueden representar con un diagrama de estado como el de
la figura5 4. Así se puede apreciar que a medida que un proceso se ejecuta va
cambiando de estado dependiendo de las preferencias que cada uno tengan
asignadas, por lo que será el procesador el que se encargue de ejecutar unos u
otros.
Cómo se aprecia en la imagen anterior los estados por los que puede pasar un
proceso son los siguientes:

 Nuevo
En los sistemas operativos hay varias razones por las que se crea un
proceso. Entre éstas se pueden destacar; la inicialización del sistema, cuando
se arranca el sistema se generan una serie de procesos ya bien sean para
interactuar con el usuario o procesos en segundo plano con una función

pág. 6
específica, como por ejemplo el aceptar la solicitud de una página web que está
en dicha máquina; ejecución de una llamada al sistema por parte de otro
proceso, un proceso puede requerir la descarga de ficheros, por lo que serán
otros procesos los que se encarguen de ubicar el archivo o archivos en la
ubicación específica; por medio de la acción de un usuario, por ejemplo al hacer
doble clic en un icono; mediante el inicio de un trabajo por lotes. Una vez el
proceso ha sido creado queda a la espera de ser admitido, por lo que si es así
pasaría a estado preparado o en caso contrario terminaría dicho proceso.
 Preparado (Ready o listo).
Un proceso en este estado está esperando a que se le asigne un
procesador. Como se puede apreciar en la figura 4, un proceso en este estado
puede, o bien finalizar, lo que ocurriría por la acción de otro proceso o por algún
acontecimiento externo, o bien el proceso pasa al estado ejecución, ya que el
gestor de procesos le asigna una CPU para ser ejecutado.
 Ejecución (Run).
El proceso en este estado está en la CPU ejecutando instrucciones. Puede
ocurrir tres situaciones; que el proceso ejecute todas las instrucciones hasta su
última línea de código y finaliza; pasa a estado bloqueado (wait) por que espera
una acción externa como la entrada de información por teclado; o bien el
proceso pasa a estado preparado debido a que ha agotado su tiempo de
ejecución, por lo que cede su tiempo de ejecución.
 Bloqueado (Wait, en espera)
El proceso está esperando a que se produzca un evento externo, como una
señal de E/S, y pasaría a estado ejecución. Al igual que el estado preparado, el
proceso puede finalizar debido a un acontecimiento externo. El sistema
operativo utiliza varias colas para gestionar los estados, cada cola puede tener
una política diferente. Así, podemos encontrar una cola para los estados
preparados y una cola para los estados en espera. El planificador del
procesador al examinar estas colas asigna el procesador al proceso más
conveniente.

2.1.2. BLOQUE DE CONTROL DE PROCESO (BCP)


Es una estructura de datos que permite al sistema operativo controlar
diferentes aspectos de la ejecución de un proceso. Cada proceso se representa
en el SO con un bloque de control de proceso (también llamado bloque de
control de tarea).
Estructura típica de un Proceso
El PCB se organiza en un conjunto de campos en los que se almacena
información de diversos tipos. Los campos típicamente mantenidos en el PCB
de un proceso se muestran en la figura siguiente:

pág. 7
Identifier
State
Priority
Program counter
Memory pointers
Context data

I/O status
information

Accounting
information

Bloque Central de Proceso

Posee los elementos del proceso:


 Identificador (identifier)
Es único, usado para distinguir al proceso de otros
 Estado (State)
Figure 3.1 Simplified Process Control Block
Si el proceso está actualmente corriendo, está en el estado de ejecución
 Prioridad (Priority)
Nivel de prioridad relativo al resto de procesos
 Contador de programa (Program counter)
La dirección del siguiente programa que se ejecutará
 Puntero de memoria (Memory pointers)
Incluye los punteros al código de programa y los datos asociados a dicho
proceso, además de cualquier bloque de memoria compartido con otros
procesos
 Datos de contexto (Context data)
Estos son datos que están presentes en los registros del procesador cuando el
proceso está corriendo
 Información de estado de E/S (I/O status information):
Incluye las peticiones de E/S pendientes, dispositivos E/S asignados a dicho
proceso, una lista de los ficheros en uso por el mismo

pág. 8
 Información de auditoría (Accounting information):
Puede incluir la cantidad de tiempo de procesador y de tiempo de reloj
utilizados, así como los límites de tiempo, registros contables, etc.

 Información típica mantenida en el PCB


Puede clasificarse en cuatro categorías:
 Información de identificación
Esta información está integrada básicamente por el identificador del proceso
(PID), que es un número que identifica al proceso. Este número es diferente
para todos los procesos que se encuentran en ejecución.
 Información de estado de la CPU
Se trata de un conjunto de campos que almacenan el estado de los registros
de la CPU cuando el proceso es suspendido.
 Información de control del proceso
Se trata de un conjunto de información que es utilizada por el sistema
operativo para controlar diversos aspectos de funcionamiento del proceso.
Pertenecen a esta categoría de información los siguientes campos:
 Estado del proceso: Listo, en ejecución, etc.
 Información de manejo de memoria: Como por ejemplo, la dirección física
de memoria en la que se ubica la tabla de páginas del proceso.
 Información de E/S: Lista de ficheros abiertos, ventanas utilizadas, etc.

 Información de uso de recursos


Se trata de un conjunto de información relativa a la utilización realizada por
el proceso de los recursos del sistema, como por ejemplo, el porcentaje de
utilización de la CPU, la cantidad de memoria usada o los bytes de E/S escritos
y leídos por el proceso.

PLANIFICACION DE UN NUEVO PROCESO


El sistema operativo es el encargado de decidir qué procesos entran en la
CPU cuando ésta queda libre, y en qué momento sale de la CPU el proceso que
está en ejecución. Todo ello se lleva a cabo a través de una política de
planificación de procesos.
Se pueden definir múltiples políticas de planificación de procesos: por orden de
llegada, primero la tarea más breve, por orden de prioridad, etc. En definitiva, lo
que una política de planificación debe conseguir es que los procesos obtengan
adecuadamente sus turnos de ejecución por lo que son tratados de la misma
forma, que no se produzca sobrecarga, es decir, el planificador debe responder
rápidamente ante cargas de trabajo ligera y responder de la misma forma ante

pág. 9
cargas de trabajo similares. Y obtener un buen rendimiento, por lo se debe
lograr finalizar el mayor número de procesos y maximizar el tiempo de
respuesta.
No existe una política de planificación óptima para todas las computadoras, sino
que depende de las características de los procesos. Así se puede ver cómo una
política obtiene unos resultados excelentes en un sistema, sin embargo en otro
sistema el rendimiento es mucho menor. Ello se debe a las características de los
procesos, donde cada uno puede tener una cantidad de operaciones de E/S
enorme cómo es el caso de las bases de datos, otros usan mayormente la CPU,
otros realizan una mayor lectura de datos frente a otros, hay procesos que
requieren una prioridad máxima en los turnos de ejecución, es el caso de los
procesos de tiempo real, y hay procesos que requieren más tiempo de ejecución
que otros, por lo que habrá que valorar si terminar primero los cortos o no
Existen diferentes planificadores en el sistema. Primero nos encontramos el
planificador a largo plazo, el cual es el encargado de controlar el grado de
multiprogramación en el sistema, intentando conseguir una mezcla adecuada de
trabajos en CPU y E/S. Es por tanto el encargado de suministrar los procesos a
la cola de planificación a corto plazo.
Existe también un planificador a medio plazo. Es el encargado de suspender y
posteriormente restaurar procesos de poco interés, realizando el intercambio de
los mismos entre la memoria principal y el disco o memoria secundaria. Dicho
proceso es conocido como swapping, y se ejecuta cuando hay escasez de
recursos
El planificador a corto a plazo es el encargado de asignar y desasignar la CPU.
Su trabajo es coger un proceso de la cola de procesos preparados y asignarle
una CPU. Hay dos tipos de planificadores a corto plazo; no expulsivas, el
proceso abandona la CPU cuando termina o a la espera de un suceso externo;
y expulsivas, el proceso que se está ejecutando puede pasar a estado listo
enviado por parte del sistema operativo

CREACION, IDENTIFICACION Y TERMINACION DE UN PROCESO


Los procesos se crean:
 Mediante una llamada al sistema de “crear proceso”, durante el curso de su
ejecución
 El proceso creador se denomina proceso padre, y el nuevo proceso, hijo
 Variantes en las relaciones padre/hijo

 Compartición de recursos
 Espacio de memoria
 Sincronización del padre
 Terminación

pág. 10
 Cuando un proceso crea un proceso nuevo, hay dos posibilidades en
términos de ejecución

 Padre e hijo se ejecutan concurrentemente


 Padre espera por la finalización del hijo

 En cuanto al espacio de direcciones del nuevo proceso:

 El hijo es un duplicado del padre


 Se carga un programa en el proceso hijo

Identificación de Procesos:
Todo proceso en Linux lleva asociado un identificador (nº de 16 bits que
se asigna secuencialmente en Linux por cada nuevo proceso que se crea), que
resulta único para cada proceso y se conoce como PID. Además, salvo el
proceso raiz (init), todo proceso lleva asociado un proceso padre, que también
tiene un identificador, en este caso PPID, lo que generará toda una estructura
en árbol.
Un programa puede obtener el identificador del proceso en el que se está
ejecutando por medio de la función de llamada al sistema getpid(), mientras que
el identificador del proceso padre desde el que se ejecutase puede obtener por
medio de la función de llamada al sistema getppid().
Al finalizar el fork() tanto el proceso padre como el hijo continúan su ejecución a
partir de la siguiente instrucción. Si un padre quiere esperar a que su hijo
termine deberá utilizar la llamada al sistema wait (); wait() detiene la ejecución
del proceso (lo pasa al estado bloqueado) hasta que un hijo de éste termine.
wait() regresa de inmediato si el proceso no tiene hijos. Cuando wait() regrese
por terminación de un hijo, el valor devuelto es positivo e igual al pid de dicho
proceso. De lo contrario devuelve –1 y pone un valor en errno.
Terminación de un proceso:
PROCESO ZOMBIE
Proceso que ha finalizado su ejecución pero aún no ha sido eliminado.
 Supongamos que un programa crea un proceso hijo y luego llama a la
función wait ():

 Si el proceso hijo no ha finalizado en ese punto, el proceso padre se


bloqueará en la llamada hasta que el proceso hijo finalice.
 Si el proceso hijo finaliza antes de que el proceso padre llame al wait () el
proceso hijo se convierte en un proceso zombie.

 Cuando el padre llame al wait(), captura el estado del proceso hijo


(terminación), el proceso hijo es borrado y la llamada wait() nos devuelve al
programa inmediatamente.

pág. 11
UN PROCESO FINALIZA:
 Cuando tras ejecutar su última instrucción le pide al SO que lo elimine
utilizando una llamada al sistema “exit”.
 Cuando el padre emite una llamada al sistema para abortarlo.

 Un padre podría terminar la ejecución de uno de sus hijos por diversas


razones, como:

 El hijo se excedió en la utilización de alguno de los recursos que se le


asignaron.
 La tarea que se asignó al hijo ya no es necesaria.
 El padre va a salir, y el SO no permite que un hijo continúe si su padre
termina

MATAR UN PROCESO:
 En ocasiones nos sucederá que queramos finalizar un proceso que esta
corriendo, las razones para hacer esto pueden ser múltiples, que el proceso
esté consumiendo demasiado tiempo del procesador, que esté bloqueado,
que no genere información o que genere demasiada, ...
 Para matar un proceso utilizaremos la orden kill, que resulta muy útil en el
caso de procesos que no tienen asociada ninguna terminal de control. Para
matar un proceso necesitaremos su PID de tal manera que escribiremos: kill
PID(s)

MEMORIA REAL
La memoria real o principal es en donde son ejecutados los programas y
procesos de una computadora y es el espacio real que existe en memoria para
que se ejecuten los procesos.
Por lo general esta memoria es de mayor costo que la memoria secundaria,
pero el acceso a la información contenida en ella es de más rápido acceso.

pág. 12
Los términos “memoria” y “almacenamiento” se consideran equivalentes.
Los programas y datos deben estar en el almacenamiento principal para:

 Poderlos ejecutar.
 Referenciarlos directamente

Solo la memoria cache es más rápida que la principal, pero su costo es a su


vez mayor.
Cuando no existe memoria virtual no hay diferenciación entre el espacio de
direcciones y la memoria real; el espacio de direcciones que puede ser usado
en los programas tiene idéntico tamaño al espacio de memoria real posible. Si
se utiliza memoria virtual, el espacio de direcciones disponibles para los
programas es aquel determinado por el tamaño de la memoria virtual
implementada y no el espacio de direcciones provisto por la memoria real
disponible (el espacio de la memoria virtual será mayor que el de la memoria
real).
La organización y administración de la “memoria principal”, “memoria
primaria” o “memoria real” de un sistema ha sido y es uno de los factores más
importantes en el diseño de los S. O.

MEMORIA VIRTUAL
Es una técnica de gerencia de memoria, usada por un sistema operativo, donde
memoria no contigua es presentada al software como memoria contigua. Esta
memoria contigua es llamada VAS (virtual address space) o espacio de
dirección virtual.

En términos técnicos, la memoria virtual permite a un software correr en un


espacio de memoria que no necesariamente pertenece a la memoria física
(memoria primaria) de una computadora. Para esto se debe emular un CPU que
trate a toda la memoria (virtual y principal) como un bloque igual, y determinar
cuándo se requiere de una memoria u otra.

Los programas corriendo en una computadora utilizan esta memoria como si se


tratase de la memoria RAM verdadera. Para ello se emplean las
llamadas direcciones lógicas de memoria, en lugar de las direcciones físicas.
pág. 13
La memoria virtual se utiliza cuando la memoria principal (RAM) no alcanza,
utilizando espacio en disco duro para extenderla. Generalmente el archivo
utilizado para guardar la memoria virtual es llamado "archivo de paginación

ASIGNACION DE MEMORIA CONTIGUA


El sistema operativo (S.O.) es el responsable de asignar memoria principal a los
procesos para que puedan ser ejecutados.

En un modelo de memoria con asignación contigua, todo el espacio lógico de un


proceso (Código, Datos, Pila) ha de estar ubicado de forma contigua en
memoria principal, es decir en direcciones físicas consecutivas

Cuando un proceso finaliza libera la memoria ocupada.

MEMORY MANAGEMENT UNIT (MMU)


MMU en español, La unidad de gestión de memoria, o también conocida como
unidad de administración de memoria o unidad de manejo de memoria es un
dispositivo de hardware formado por un grupo de circuitos integrados,
responsable del manejo de los accesos a la memoria por parte del procesador.
Entre las funciones de este dispositivo se encuentran la traducción de las
direcciones lógicas (o virtuales) a direcciones físicas (o reales), la protección de
la memoria, el control de cache y, en arquitecturas de computadoras más
simples (especialmente en sistemas de 8 bits).
Un beneficio fundamental de la MMU es la posibilidad de implementar
protección de memoria, evitando que los programas accedan a porciones de
memoria prohibidas. Por ejemplo, se puede evitar que un programa acceda o
modifique sectores de memoria de otros programas.
La MMU asigna memoria del sistema operativo a varias aplicaciones. En la
unidad de procesamiento central se encuentra el área de direccionamiento
virtual, la cual está compuesta de un rango de direcciones que se dividen en
páginas. Las páginas son bloques secundarios que son iguales en tamaño. El
proceso de paginación automática permite que el sistema operativo use espacio
de almacenamiento repartido en el disco duro

PARTICIONES

El sistema operativo es capaz de gestionar la coexistencia de varios programas


en memoria asignando a cada uno un espacio contiguo (partición). El
particionado puede ser fijo o variable.
Como soporte hardware para protección requiere dos registros:

pág. 14
• Registro límite inferior (base).
• Registro límite superior o registro longitud

Se requiere reubicación en tiempo de carga. El cargador puede establecer


direcciones absolutas (reubicación estática), o establecer direcciones relativas a
un registro base (reubicación dinámica). En particionado variable se requiere
obligatoriamente reubicación dinámica, como veremos.

Particionado fijo

La memoria se divide en un conjunto de particiones de tamaños


preestablecidos. Este mecanismo se denomina históricamente MFT
(multiprogramación con un número fijo de tareas).

En cada partición se ubica un único programa. Las particiones pueden ser


iguales o de diferentes tamaños. En este último caso se aprovecha mejor la
memoria, al poder almacenar un programa en la partición que mejor se ajuste a
su tamaño.
Dos consecuencias de este mecanismo son las siguientes:
• El número de programas está limitado (grado fijo de multiprogramación).
• Produce fragmentación interna en cada partición (trozo de la partición
desocupada).
Los programas se encolan para poder ser cargados en memoria. Existen dos
alternativas:
(a) Una cola por cada partición. Un programa se encola en la cola que le
corresponde por su tamaño. Tiene el inconveniente de que puede dejar fuera a
un programa habiendo memoria libre para cargarlo.
(b) Cola única. Cuando un programa encuentra ocupada la partición que
corresponde a su tamaño cabe la posibilidad de asignarle una partición libre de
tamaño mayor, permitiendo incrementar el grado de multiprogramación a costa
de introducir fragmentación interna. El sistema puede utilizar heurísticos que
maximicen el grado de multiprogramación minimizando la fragmentación,
consistentes en alterar la disciplina de la cola buscando en ella los programas

pág. 15
que se adapten mejor a los huecos disponibles, para minimizar la fragmentación
interna.
Para la gestión del espacio libre es adecuado el mapa de bits.

Particionado variable
Como ya sabemos, MFT presenta problemas de fragmentación interna. La
alternativa es el particionado variable de la memoria, que se denomina MVT
(multiprogramación con un número variable de tareas).

Ya es conocido que el particionado variable introduce fragmentación externa al ir


quedando huecos entre particiones a medida que finalizan programas. En estos
huecos sólo se pueden ubicar programas de menor tamaño que el hueco, que
cuando acaben dejarán un hueco aún menor, y así sucesivamente (degradación
de la memoria). La necesidad de compactar implica reubicar dinámicamente el
programa, requiriendo el soporte adecuado para ello.

La carga de programas se gestiona mediante una única cola. La memoria libre


se representa bien con una lista de huecos, bien mediante un mapa de bits,
aunque en este caso es conveniente definir una unidad de asignación de
memoria mayor que el byte para mantener el tamaño del mapa en unas
dimensiones razonables.

La elección del hueco donde ubicar el programa puede hacerse siguiendo las
diferentes políticas de asignación.

ESTRATEGIA DE ASIGNACIÓN
Ahora podemos preguntarnos: ¿Cómo elige el SO en que porción de memoria
colocaremos un proceso?
Existen varias estrategias:
•First fit: Asigna el primer “agujero” de memoria libre que satisface la
necesidad.
•Best fit: Asigna el mejor “agujero” de memoria libre que exista en la memoria
principal.
•Worst fit: Asigna en el “agujero” más grande que exista en la memoria
principal.

Estudios de simulación han mostrado que first-fit y best-fit lograron mejores


rendimientos en tiempo de asignación y utilización de la memoria que la
estrategia worst-fit.

FIRST FIT

pág. 16
BEST FIT

WORST FIT

pág. 17
Periférico de Entrada y Salida

En informática, un periférico de
entrada/salida o E/S (en inglés: input/output o I/O) es un dispositivo que permite
la comunicación entre un sistema de procesamiento de información, tal como
la computadora y el mundo exterior, y posiblemente un humano u otro sistema
de procesamiento de información.

Los periféricos de Entrada/Salida son utilizados por una persona (o sistema)


para comunicarse con computadoras.

Funciones Básicas del sistema E/S

 Direccionamiento: Selección del dispositivo correspondiente de entre todos los


dispositivos presentes en el sistema. „

 Sincronización: Permitir que la CPU y la memoria (alta velocidad transferencia


de datos) se puedan comunicar con los dispositivos de E/S (baja velocidad)
sincronizando los envíos de datos entre ambos. (Inicio de la transferencia). „

 Transferencia: El sistema de E/S debe tener toda la circuitería y señales de


comunicación apropiadas para llevar a cabo la comunicación con cada uno de
los dispositivos del sistema. (Método de transferencia).

Comunicación CPU- Periféricos

La E/S se implementa mediante periféricos.

Periférico:

pág. 18
 Elemento que permite la transferencia de información entre la CPU y el
mundo exterior.

 Interfaz que traduce la información asíncrona y analógica del mundo exterior


a la información síncrona y codificada del computador.

 Dos partes: módulo de E/S (controlador) y dispositivo externo.

Módulo de E/S

Funciones

Elemento que permite la conexión de un dispositivo externo al bus del sistema.

1. Control y Temporización:

Coordina el tráfico entre dispositivos internos (memoria, CPU) y externos


(impresora, monitor,…).

2. Comunicación con la CPU:

Reconocer la dirección de la CPU que identifica al dispositivo externo

Recepción y decodificación de mandatos (comandos) desde la CPU

Transferencia de datos entre la CPU y el dispositivo externo

Información sobre el estado del periférico

3. Comunicación con el/los dispositivo/s (órdenes, estado, datos).

4. Almacenamiento temporal de datos.

5. Detección de errores.

Métodos de programación de E/S

 E/S Programada (Encuesta o pooling). „

 E/S por interrupciones. „

pág. 19
 Acceso directo a memoria (DMA)

E/S por interrupciones

La E/S le indica a la CPU cuando está preparada para transferir datos (genera
una interrupción a la CPU), activando una línea especial conectada a la CPU
(línea de interrupción).

Funcionamiento

1. El procesador ejecuta instrucciones de un programa. Al finalizar cada


instrucción comprueba si se ha producido una interrupción.

2. En caso afirmativo se salva el estado actual del programa (contador del


programa y registros) y se salta a ejecutar la rutina de servicio
correspondiente.

3. La rutina de servicio efectúa las operaciones apropiadas en la E/S para


realizar la transferencia de datos solicitada.

4. Al finalizar la rutina de servicio se recupera el estado de la CPU y se


continúa ejecutando el programa que se estaba ejecutando antes de la
interrupción.

Clasificación de Interrupciones

-Según FUENTE que produce la interrupción:


 Interrupciones HARDWARE

pág. 20
INTERNAS (producidas por la CPU)
EXTERNAS (producidas por los dispositivos de E/S)
-Vectorizadas
-No vectorizadas
 Interrupciones SOFTWARE (producidas por la ejecución de instrucciones
de la CPU).
-Según MODO DE CONOCER el VECTOR DE INTERRUPCIÓN (la dirección
donde se encuentra la rutina de servicio de la interrupción):
-Interrupciones AUTOVECTORIZADAS: el vector de interrupción es FIJO.
-Interrupciones VECTORIZADAS: el vector de interrupción lo suministra el
propio periférico

Interrupciones Vectorizadas
Con el vector de interrupción se indexa una tabla de vectores en memoria principal para
obtener la dirección de la rutina de servicio a la que hay que saltar.

Conexión de varios periféricos

pág. 21
-Generalmente existen VARIOS PERIFÉRICOS conectados (y no uno sólo) que
pueden realizar interrupciones.

-Es necesario:

 Decidir cómo se conectan los periféricos a la CPU.

Una sola línea de interrupción.

Varias líneas de interrupción.

 Establecer prioridades.

 Determinar para cada periférico su vector de interrupciones

Una sola línea de interrupción

Todos los periféricos interrumpen por la misma línea.

El vector de interrupción es fijo y común a todos los periféricos.

Mediante polling (Consulta software del Registro de Estado) la CPU identifica el


periférico y desactiva la interrupción.

La prioridad viene determinada por el orden de la encuesta.

IV.2. Requisitos obtenidos para el trabajo

pág. 22
Código Requerimiento Descripción
RF1 Lenguaje de Uso del lenguaje de
programación Java programación Java para
implementar el código,
utilizando el entorno de
desarrollo Netbeans.
RF2 Base de datos mySQl Uso de la base de datos
mySQL para almacenar
los atributos de los
procesos.

IV.3. Definición de supuestos y restricciones

 Los procesos pueden ser ingresados manualmente y a través de la base


de datos.
 El número de proceso es ilimitado.
 El algoritmo de planificación es FIFO.
 Los procesos tienen un código incremental que se genera
automáticamente al momento de crear un nuevo proceso.
 Las interrupciones son creada aleatoriamente mediante un intervalo de
tiempo.
 Las interrupciones están clasificada por duración, tales como: TECLADO,
MOUSE y TIMER.
 Los procesos e interrupciones se pueden listar en una misma matriz
considerando el tiempo de llegada.
 Se ha considerado dos técnicas para la gestión de memoria, particiones y
número de páginas.
 Uso de First fit, best fit y worst fit para la asignación de memoria a los
procesos y visualizarlos a la vez.
 Nuestros procesos a trabajar emplean el método de asignación best fit.
 Cada proceso será asignado en memoria, mientras su número de página
sea menor o igual a 8.
 La capacidad de la memoria RAM es de 4GB, pero se puede variar en el
código del proyecto.
 La capacidad de memoria para el sistema operativo es de 1GB.
 Los procesos que no tienen espacio en la memoria, serán listados para
visualizarlos como no procesados.

IV.4.- Desarrollo del trabajo

pág. 23
A continuación mostraremos la funcionalidad de nuestro proyecto-
simulación.
Imagen 1: Nos muestra el panel inicial de la simulación para procesos,
interrupciones y memoria.

Imagen 2: Se obtiene del botón “Ingresar Procesos” que se encuentra en el


panel inicial, en la cual tenemos dos opciones, “NuevoProceso” - para crear un
proceso con sus respectivos parámetros + datos y “VerProceso”, el cual sirve
para visualizar todos los procesos creados.

“NuevoProceso” (Imagen 2.1): Aquí nosotros crearemos un nuevo proceso


considerando su duración (Rafa_cpu), tiempo de llegada del proceso-se
refiere al tiempo que el proceso es creado (Time_llegada), Prioridad- Es el
nivel de nivel de importancia del proceso (Prioridad), tamaño se refiere el
tamaño del proceso en MB (tamaño).
El proceso se considera creado una vez que ha sido registrado.

pág. 24
“VerProceso” (Imagen 2.2): Esta opción nos permite mostrar los procesos
creado hasta el momento, indicando a su vez el número de procesos
existentes. Para ver solo es necesario presionar el botón “Cargar Datos”.

Imagen 3: Una vez creado los procesos, nos dirigimos a la gestión de memoria, el
cual se ubica en la parte izquierda superior del panel principal, con el rotulo de
“Memoria”, allí encontraremos dos opciones, “Información” – nos detalla sobre
nuestro proceso, memoria y S.O, “Partición Fija” – nos mostrará su respectivo
graficador.
Algoritmo de Planificación: FIFO

pág. 25
“Información” (Imagen 3.1): Nos muestra la capacidad de memoria y del
S.O , el tamaño del frame es valor fijo, con un Nº de frame calculado
automáticamente.

“Partición Fija” (Imagen 3.2): Tendremos las opciones de mostrar los


datos por particiones y procesos (“Ingresar Datos”), visualizar gráficamente
la distribución de los procesos y la asignación de estos para cada frame.

pág. 26
(Imagen 3.2.1)

Imagen 3.2.2
Aquí se muestra la forma de asignación, “Primer Ajuste”, ”Mejor
Ajuste”, “Peor Ajuste”, además se puede visualizar los procesos
pendientes, a aquellos que no ocuparon una frame por superar el
tamaño permitido.

pág. 27
Imagen 4: Dentro del panel de “Partición Fija” tenemos la opción “MATRIX” en
la cual mostraremos como los procesos se ubican en una frame en caso de su
tamaño ser menor o igual al tamaño frame, y como quedan libres.

Imagen 4.1: Con el botón “Ver”, podemos ir cargando uno por uno los
procesos y ubicándolo en cada frame de ser posible, además tenemos una
lista de (proceso, Mb) el cual indica el orden de la carga por procesos.
Leyenda:
Amarillo: Proceso ocupado sin especificar la frame.
Rojo: Proceso ocupando la frame y (proceso i, frame y);
Azul: Procesos Pendientes o libre.

pág. 28
Imagen 4.2: Con el botón “buscar Proceso”, podemos obtener el estado
del proceso si es ocupado o libre, en caso de ser ocupado, nos mostrará la
dirección de memoria y en que frame se ubica.

pág. 29
Imagen 5: Dentro del panel de “Partición Fija” tenemos la opción “matrix” en
la cual mostraremos los procesos listados, además, una vez dado “Play” se da
por iniciado el TIEMPO de ejecución, en caso que el tiempo de llegada del
proceso coincida con la etiqueta TIEMPO , y su tamaño de página es menor a
ocho, entonces se muestra en la tabla “Procesos de 8 paginas” ocupando el
número de páginas, en caso que sea mayor , se lista en la tabla “Procesos
Rechazados”, si el proceso termina su duración en la tabla “Procesos de 8
paginas” entonces pasa a “Procesos Listos”.

Imagen 5.1: Utilizando el boton Play, a continuacion se mostrara la


secuencia de eventos generado por este boton, una vez dado play la
etiqueta tiempo “TIEMPO”empieza desde 0 , con un limite de tiempo
equivalente a la suma de todos los tiempo mas 50.

pág. 30
5.a)

5.b)

pág. 31
5.c)

5.d)

Imagen 5.2: Utilizando el boton “NUEVO PROCESO”, una vez ingresado los
valores que componen un proceso, al darle clic sobre este boton,
automaticamente captura el tiempo de ejecucion, y ello se guarda en el
boton “captura un tiempo”, de tal forma que el proceso se agrega en la
tabla de procesos creados.

pág. 32
Imagen 6: Se obtiene del botón “Mostrar Procesos Preparados” que se
encuentra en el panel inicial, esta listara todos los procesos listos, como se
obtuvo en la Imagen 5.

Imagen 7: Se obtiene del botón “Aplicar Algoritmo” que se encuentra en el


panel inicial, esta graficará todos los procesos listos, como se obtuvo en la
Imagen 6.
Algoritmo de Planificación: FIFO
pág. 33
Imagen 8: Se obtiene del botón “Resultados” que se encuentra en el panel
inicial, esta mostrará todos los procesos listos, tiempo Espera, tiempo de
Retorno, tiempo de Respuesta, estado y tamaño del proceso.

Imagen 9: Se obtiene del botón “Generar Interrupciones” que se encuentra en


el panel inicial, este nos permitirá crear interrupciones y ver el listado de las
interrupciones.
Las interrupciones son generadas aleatoriamente, basta ingresar el número de
interrupciones q se desea tener, y automáticamente, se genera su intervalo de
tiempo en la cual se ejecutara la interrupción, además podemos ver este listado
con el botón “verInterrupciones”.

pág. 34
En la sección de “Interrupciones Generadas”, podemos observar que se van
a generar 15 interrupciones, pudiendo ser de timer, pantalla o mouse
dependiendo del intervalo de tiempo.

Imagen 10: Se obtiene del botón “Ejecutar Interrupciones” que se encuentra en


el panel inicial, este nos permitirá visualizar por tiempo si se ejecuta una
interrupción o un proceso.

pág. 35
IV.5.- Pruebas y medidas aplicadas
En el desarrollo de la administración de memoria las pruebas realizadas son a través
de una simulación usando el lenguaje JAVA en el entorno Netbeans y la base de datos
MySQL.

pág. 36
pág. 37
IV.6.- Logros obtenidos

La simulación de la administración de procesos y memoria genera un mejor


entendimiento y/o aprendizaje ya que al estudiarlo o experimentarlo nos permite tener
más claro cómo es que asigna memoria o cuando requiere más memoria un proceso.

Por parte de los procesos, hemos logrado entender la lógica y procedimiento desde su
creación hasta su ejecución, y para ello de todas manera tuvimos que centrarnos en
gestión de memoria, estudiar tipos de planificación, como representarlo visualmente su
funcionamiento, entre otras actividades.

pág. 38
V. Conclusiones

 Nuestro simulador presenta gestión de Procesos, Memoria y E/S, en ella se


presenta áreas seccionadas de trabajo u pantallas específicas de trabajo, así de
este modo su presentación es más ordenado.
 Realizar la programación en varios hilos es complejo pero es la mejor forma de
realizar la gestión de Procesos y E/S, debido a que los resultados trabajando
con un solo hilo no es conveniente cuando tenemos demasiados procesos en
espera para asignación de memoria.
 Nuestra secuencia de ejecución para nuestro simulador cumple lo planificado,
mostrando detalladamente cada etapa simulada, siendo intuitivo y lógico a la
vez su manejo.
 El simulador procesa de una manera simple con un CPU, pero es mejor hacer
uso de la multiprogramación con varios CPU´s para mejorar la respuesta al
usuario sobre los procesos, además que al emplear la estrategia de asignación
“Best Fit” tenemos procesos cargado en zona inicial de memoria, ello sería de
mayor eficacia si fuera más de un CPU y memoria.
 En el sistema se muestra las tres estrategias de asignación de memoria, pero
se trabajó con el de “Best Fit”, pero en el transcurso y finalización del mismo,
nos dimos cuenta que para los procesos que siguen el algoritmo FIFO, es mejor
el uso del “First Fit” ya que los procesos que ingresan buscan el primer espacio
disponible en memoria para ser procesados y así se agiliza el tiempo de
respuesta.
 El direccionamiento de la memoria RAM nos ayudó en la programación a la hora
de la ubicación del proceso y entender cómo el sistema operativo lo realiza o
cómo podría hacerlo.
 La parte de grafica de asignación de proceso en memoria nos ayuda a analizar
el comportamiento al momento de buscar alguna partición en cada estrategia de
asignación, de tal manera que podamos observar la fragmentación interior y
exterior, ubicación en una frame y dirección.

VI. PRÓXIMAS MEJORAS E IMPLEMENTACIONES.

pág. 39
 En la sección de procesos, debemos implementar más algoritmo de
planificación para ver los diversos cambios o comportamientos de estos.
 Añadir la parte grafica dinámica de los procesos conforme transcurre el
tiempo y aparición de estos en el tiempo.
 Implementar en el simulador de S.O el trabajo de multiprocesamiento.
 Implementar las interrupciones desde un nivel inicial.
 Ampliar el rango de las direcciones y pasarlo a hexadecimal ya que en
nuestro proyecto se muestra en decimal.
 Implementar gráficamente la segmentación de memoria de proceso.
 Trabajo de memoria virtual.

VII. Anexos

pág. 40
I.1 Manual de usuario.

A. Instalación del NetBeans

1. Abrimos la página oficial de NetBeans IDE:

2. Damos click a Download:

3. Luego esperamos que se descargue el instalador:

pág. 41
4. Mientras esperamos la descarga, abrimos nuevamente la página principal y damos click a JDK
por separado.

5. Después aparece una nueva ventana y damos click en lo siguiente:

pág. 42
6. Luego aceptamos los Términos y Condiciones:

7. Después damos click a Ejecutar:

pág. 43
8. Ahora abrimos el instalador de NetBeans y le damos click a Ejecutar:

9. Después damos click a siguiente:

pág. 44
10. Luego seguimos dando click a Siguiente:

Finalmente termina la Instalación.

B. Instalación del MySQL

1. Para descargar MySQL, nos dirigimos al siguiente enlace:


https://www.mysql.com/downloads/ y elegimos la opción de MySQL Enterprise
Edition.

2. N
o
s

pág. 45
mostrará el área de tipo de descarga por sistema operativo empleado, en el cual
optaremos por (x86).

3. Una vez descargado el MySQL, debemos ejecutarlo para su instalación.

4. Luego de presionar el botón “Ejecutar”, nos saldrá una pantalla en la cual se mostrará
“cargando y configurándose” para su instalación, posteriormente aparecerá la siguiente
pantalla de instalación, en la cual solo tendremos que esperar su configuración
respectiva.

5. Terminado la configuración, nos pedirá tener previamente instalado Microsoft Visual C+


+ Redistributable (x86), para ello nos dirigimos al siguiente enlace
https://www.microsoft.com/es-es/download/details.aspx?id=5555, seleccionamos el
idioma español y realizamos la descarga respectiva.

pág. 46
Nosotros elegimos (x86) debido que satisface para las condiciones de nuestro Sistema
Operativo.
6. Descargado lo solicitado en el punto 5, lo ejecutamos e instalamos (cuestión de “Next”).
7. Retomando la instalación principal del MySQL, nos aparecerá el panel de seleccionar
productos, en el cual haremos la transferencia de “MySQL server”.

8. Del panel anterior, damos clic en “Next” para luego mostrarnos el área de “Instalacion”,
seleccionaremos nuestro producto y posteriormente clic en “Execute”.

pág. 47
9. Completado la ejecución, daremos Next hasta llegar al área de “Type and Networking”.

10. Una vez ubicados en la pantalla de “Type and Networking”, seleccionaremos la opción
de “Standalone MySQL server”, para posteriormente dar clic en “Next”.

11. Además debemos configurar el número de puerto y el tipo de configuración, por lo


general se especifica el puerto a “3306” y “Development Machine”. Realizado las
especificaciones, daremos clic en “Next”.

pág. 48
12. Llegado a las pantalla de “”Accounts and Roles”, debemos generar una contraseña de
acceso para MySQL, para nuestro caso es “root” dicho password.

13. De la pantalla anterior, haremos uso del botón “Add User” para agregar un nuevo
usuario, en la cual nos mostrará la pantalla de “MySQL User Detail”, aquí nos solicitará
nombre de usuario y el password, los demás campos quedan de manera
predeterminada. Terminado el detalle de Usuario (mediante “ok”) clic en “Next”.

pág. 49
14. La siguiente pantalla se refiere a “Windows Service”, seleccionamos los campos
necesarios como se muestra en la imagen de abajo, para luego dar clic en “Next”.

15. Para “Plugins and Extensions”, dejaremos con las opciones pre-seleccionadas y
daremos clic en “Next”.

pág. 50
16. En la pantalla de “Apply Configuration”, solo daremos “Execute”.

17. Esperamos que la pantalla anterior termine de ejecutarse por cada paso de su
configuración, luego daremos clic en “Finish”.

pág. 51
VII.3 Código fuente del sistema.

Script:
drop database operativos;
create database operativos;
use operativos;

create table proceso (cod_proceso int primary key auto_increment,


rafa_cpu int,
time_llegada int,
prioridad int,
tamanio int,
estado char(20));

create table interrupciones (cod_interr char(20) primary key,


interr_inicial int,
interr_fina int);

pág. 52
create table robin (cod_robin char(20),
timer int,
rafa_cpu int);

INSERT INTO proceso


VALUES (null,20,12,2,5,'creado'),
(null,25,15,1,7,'creado'),
(null,12,23,1,4,'creado'),
(null,37,24,2,10,'creado'),
(null,24,26,1,6,'creado'),
(null,22,27,1,3,'creado'),
(null,29,29,1,7,'creado'),
(null,21,30,1,13,'creado'),
(null,23,35,2,6,'creado'),
(null,27,42,2,9,'creado'),
(null,35,46,1,2,'creado'),
(null,24,48,1,1,'creado'),
(null,19,50,2,10,'creado'),
(null,22,56,1,4,'creado'),
(null,10,59,1,2,'creado'),
(null,5,60,2,5,'creado'),
(null,13,63,1,5,'creado'),
(null,19,68,2,6,'creado'),
(null,10,72,1,12,'creado'),
(null,13,75,1,3,'creado'),
(null,22,81,1,4,'creado'),
(null,24,89,1,8,'creado'),
(null,24,93,1,6,'creado'),
(null,24,98,1,3,'creado'),
(null,24,95,1,9,'creado');

pág. 53
INSERT INTO interrupciones
VALUES ('I0',6,8),
('I1',8,14),
('I2',15,21),
('I3',26,28),
('I4',49,51);

INSERT INTO robin


VALUES ('P1',3,23),
('P2',3,29),
('P3',3,21),
('P4',3,34),
('P5',3,24),
('P6',3,18),
('P7',3,45);

PRINCIPALES LINEAS CODIGO:

pág. 54
CARGAR DATOS DESDE LA BASE DE DATOS
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
conectar con=new conectar();
Connection reg= con.conexion();
String codProceso,rafaga,tiempollegada,prioridad;
String sql;

codProceso="null";
rafaga=T_RafaCpu.getText();
tiempollegada=T_TimeLlegada.getText();
prioridad=T_Prioridad.getText();
String est_ingr="creado";
String tamanio=jtxt_tamaño.getText();
sql="INSERT INTO proceso (rafa_cpu,time_llegada,prioridad,tamanio,estado)
VALUES (?,?,?,?,?)";
try {
PreparedStatement pst=reg.prepareStatement(sql);
// pst.setString(1, codProceso);
pst.setString(1, rafaga);
pst.setString(2, tiempollegada);
pst.setString(3, prioridad);
pst.setString(4, tamanio);
pst.setString(5, est_ingr);
int n=pst.executeUpdate();
if (n>0) {
JOptionPane.showMessageDialog(null,"Registro de proceso correcto");
} else {
}

} catch (SQLException ex) {


Logger.getLogger(Ingreso_datosproceso.class.getName()).log(Level.SEVERE,
null, ex);
}

}
GRAFICAR PARTICIONES:
tbl_ingreso_procesos.setRowSelectionInterval(Nprocesos(), Nprocesos());
tbl_Ingreso_Particion.setRowSelectionInterval(Nparticiones(), Nparticiones());
InsertarParticiones(35, 0, jpanel_primerAjuste);
PrimerAjuste();
InsertarParticiones(35, 0, jPanel_mejorAjuste);
MejorAjuste();
InsertarParticiones(35, 0, jPanel_peorAjuste);
PeorAjuste();
btn_graficar_memoria.setEnabled(false);
btn_limpiar_paneles.setEnabled(true);

UTILIZANDO HILOS PARA GRAFICAR:

public void run(){

listarPP();
//listarTablaF(); // TODO add your handling code here:
label.setText(String.valueOf(totalProcesos));
boton.setEnabled(false);

CODIGO FIFO:
public void FCSC(){
for(int i=1;i<listaDoble.size();i++){
for(int j=0;j<listaDoble.size()-1;j++){
if(listaDoble.get(i).dato.getTiempo()<listaDoble.get(j).dato.getTiempo()){
Proceso aux=listaDoble.get(j).getDato();
listaDoble.modificar(j, listaDoble.get(i).dato);
listaDoble.modificar(i, aux);
}
}
}

for (int i = 0; i < listaDoble.size(); i++) {


System.out.println("hola: "+listaDoble.get(i).dato.getNombre()+"
"+listaDoble.get(i).dato.getTiempo());
}
}

Anda mungkin juga menyukai