357
Universidad Tecnológica Nacional Facultad Regional Buenos Aires Proyecto Final “Sistema Operativo Routix” Profesor: Eduardo Ioli Ayudantes: Claudia Orlandi – Basilio Robino Curso: R6051 - Viernes Integrantes del Grupo: Candurra, Martín Legajo: 110397-0 Ortega, Mariano Gastón Legajo: 106511-7 Año: 2004

Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

  • Upload
    others

  • View
    1

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Universidad Tecnológica Nacional

Facultad Regional Buenos Aires

Proyecto Final

“Sistema Operativo Routix”

Profesor: Eduardo Ioli

Ayudantes: Claudia Orlandi – Basilio Robino

Curso: R6051 - Viernes

Integrantes del Grupo:

Candurra, Martín Legajo: 110397-0Ortega, Mariano Gastón Legajo: 106511-7

Año: 2004

Page 2: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Índice General

1. Descripción general__________________________________________________5Kernel Monolítico___________________________________________________________5

MicroKernel_______________________________________________________________5

2. Características y Especificaciones técnicas_______________________________9Características______________________________________________________________9

Especificación técnicas______________________________________________________10

3. Descripción detallada del proyecto_____________________________________11Protección, Segmentación y Paginación________________________________________12

Segmentación______________________________________________________________12

Paginación________________________________________________________________12

Memory Manager__________________________________________________________13

Multitarea________________________________________________________________14

Llamadas al sistema________________________________________________________18

Controlador de Floppy y DMA_______________________________________________20

Controlador de FAT12______________________________________________________21

Llamadas para el manejo de archivos__________________________________________22

Timers___________________________________________________________________23

Scheduler_________________________________________________________________24

Aplicaciones_______________________________________________________________25

4. Conexiones Eléctricas_______________________________________________27Generalidades_____________________________________________________________27

Circuitos__________________________________________________________________29

5. Circuitos impresos__________________________________________________45

6. Diagrama de Interconexión de Componentes____________________________46

7. Diagramas de Interconexionado_______________________________________48

8. Planos Mecánicos__________________________________________________55

9. Lista de Componentes_______________________________________________57

10. Cálculo de Confibilidad en los circuitos y programas de Computación______58Definición de Confiabilidad__________________________________________________58

Concepto de Falla__________________________________________________________58

Fallas paramétricas_________________________________________________________59

Fallas aleatorias____________________________________________________________59

Fallas por desgaste_________________________________________________________59

Confiabilidad del hardware__________________________________________________59

Page 3: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Confiabilidad del Software___________________________________________________60

Clasificación de los errores__________________________________________________60

Definición Matemática______________________________________________________61

Predicción de la confiabilidad________________________________________________63

Macromodelo de Musa______________________________________________________63

Estimación por momentos___________________________________________________66

Estimación por cuadrados mínimos___________________________________________67

11. Instrucciones de puesta en marcha, ensayo funcional, ajuste y calibración, registros.______________________________________________________________68

Software recomendado._____________________________________________________69

Obtención de los Fuentes____________________________________________________69

Bochs____________________________________________________________________69

GCC_____________________________________________________________________70

Winimage_________________________________________________________________70

Fuentes___________________________________________________________________70

12. Ensayos de aceptación y registro____________________________________71

13. Instrucciones de instalación y operación._____________________________72

14. Mantenimiento y diagnóstico de fallas________________________________78

15. Cálculo de costos y estudio del mercado para su comercialización._________79Análisis de Costos__________________________________________________________79

Costos fijos________________________________________________________________80

Costos Variables___________________________________________________________80

Mercado__________________________________________________________________82

Comparación______________________________________________________________83

16. Análisis de la planificación proyectada en la propuesta y la resultante real.__84

17. Bibliografía y normativa utilizada.___________________________________86Bibliografía_______________________________________________________________86

Normativas________________________________________________________________86

18. Hojas de datos de los componentes más relevantes.______________________87

19. Apéndice________________________________________________________88A. Código Fuente_________________________________________________________88

8254.c_________________________________________________________________________888254.h_________________________________________________________________________898259.h_________________________________________________________________________90alloc.c_________________________________________________________________________91alloc.h_________________________________________________________________________94atomic.c________________________________________________________________________95atomic.h________________________________________________________________________97blockcache.c____________________________________________________________________98blockcache.h___________________________________________________________________108debug.h_______________________________________________________________________110

Page 4: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

device.h_______________________________________________________________________111elf.h__________________________________________________________________________112error.c________________________________________________________________________114error.h________________________________________________________________________117event.c________________________________________________________________________120event.h________________________________________________________________________122fat.h__________________________________________________________________________123fat12.c________________________________________________________________________126file.c__________________________________________________________________________138file.h_________________________________________________________________________145floppy.c_______________________________________________________________________146floppy.h_______________________________________________________________________170init.c__________________________________________________________________________173int.c__________________________________________________________________________174io.c___________________________________________________________________________179kalloc.c_______________________________________________________________________180kalloc.h_______________________________________________________________________184kmain.c_______________________________________________________________________185kstdio.h_______________________________________________________________________188libk.c_________________________________________________________________________189list.h__________________________________________________________________________194misc.h________________________________________________________________________198mm.c_________________________________________________________________________199paging.c_______________________________________________________________________203paging.h_______________________________________________________________________207pic.c__________________________________________________________________________209sched.c________________________________________________________________________211segm.c________________________________________________________________________214segm.h________________________________________________________________________216shell.c________________________________________________________________________218signal.c_______________________________________________________________________222signal.h_______________________________________________________________________225stdlib.c________________________________________________________________________227string.c________________________________________________________________________228string.h________________________________________________________________________231sys_con.c______________________________________________________________________232sys_mem.c_____________________________________________________________________234sys_misc.c_____________________________________________________________________236sys_proc.c_____________________________________________________________________240sys_signal.c____________________________________________________________________261sys_time.c_____________________________________________________________________265syscalls.c______________________________________________________________________268syscalls.h______________________________________________________________________269system.h_______________________________________________________________________271task.c_________________________________________________________________________273task.h_________________________________________________________________________279teclado.c______________________________________________________________________285teclado.h______________________________________________________________________290time.c_________________________________________________________________________292time.h_________________________________________________________________________296timer.c________________________________________________________________________298timer.h________________________________________________________________________304types.h________________________________________________________________________305video.c________________________________________________________________________306video.h________________________________________________________________________309

Page 5: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

1. Descripción general

Antes de pasar a una descripción del proyecto mediante bloques, consideramos necesario definir dos tipos de arquitectura de Kernel de sistemas operativos, ellos son: Kernel Monolítico (el cuál hemos implementado en nuestro proyecto) y Micro Kernel.

Kernel Monolítico

Un Kernel monolítico define una interfaz virtual de alto nivel sobre el hardware, con un conjunto de primitivas o llamadas al sistema (system calls) que implementan servicios del sistema operativo como administración de procesos, concurrencia y administrador de memoria (memory manager) en distintos módulos que se ejecutan en modo protegido.

Incluso si cada módulo está separado del resto, la integración del código es muy fuerte, y es difícil hacerla bien. Además, como todos los módulos se ejecutan en el mismo modo, un error en uno de ellos puede colgar todo el sistema. Sin embargo, cuando se ha completado la implementación y ésta es fiable, la fuerte integración de los componentes permite un uso muy efectivo de las características de bajo nivel del sistema subyacente, lo que hace que un buen núcleo monolítico sea muy eficiente. Los partidarios del enfoque monolítico afirman que si el código no es correcto, no debería hallarse en un núcleo, y que si lo es, entonces hay pocas ventajas en la aproximación micro núcleo.

La mayoría de núcleos monolíticos, como Linux y el núcleo de FreeBSD, pueden cargar módulos ejecutables en cualquier momento, lo que permite una forma fácil de ampliar las capacidades del núcleo según se necesite, pero permitiendo que la cantidad de código que se ejecuta en espacio de núcleo se mantenga al mínimo.

Algunos ejemplos de núcleos monolíticos:

Núcleos Unix tradicionales, como los núcleos de los BSD. El núcleo Linux

MicroKernel

El enfoque de MicroKernel consiste en definir una abstracción muy simple sobre el hardware, con un conjunto de primitivas o llamadas al sistema que implementan servicios del sistema operativo mínimos, como la administración de hilos (threads ), el administrador de memoria y la comunicación entre procesos.

El objetivo principal es la separación de la implementación de los servicios básicos y de la política de funcionamiento del sistema. Por ejemplo, el proceso de bloqueo de E/S se puede implementar con un servidor en

Page 6: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

espacio de usuario ejecutándose encima del micro núcleo. Estos servidores de usuario, usados para gestionar las partes de alto nivel del sistema, son muy modulares y simplifican la estructura y diseño del núcleo. Si falla uno de estos servidores, no se colgará el sistema entero, y se podrá reiniciar este módulo independientemente del resto.

Algunos ejemplos de micro núcleos:

AIX La familia de micronúcleos L4 El micronúcleo Mach, usado en GNU Hurd y en MAC OS X Minix MorphOS QNX RadiOS VSTa

Modularización del Kernel Monolítico de Routix

Kernel (DPL 0)

Memory Manager

Scheduler

Drivers File System

SignalsSystem Calls

Aplicaciones de Usuario (DPL 3)

Tareas de Usuario Process Status (PS) Kill

Hardware

Page 7: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Alternativa 1: Modelo MultiCapas (Multi Layer)

Scheduler (capa 0)

Memory Manager (capa 1)

Message Interpreter (capa 2)

I/O Manager (capa 3)

Aplicaciones de Usuario (capa 4)

Page 8: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Alternativa 2: microKernel

Hardware

microKernel

Page 9: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

2. Características y Especificaciones técnicas

Características

Kernel monolítico

Interfaz POSIX compatible

Soporte cuasi preentivo

Manejo de señales

Cambio de tareas por software (software task switching)

Dos niveles de seguridad (modo usuario y modo kernel)

Temporizadores

Acceso a dispositivo de disco

Acceso directo a memoria (DMA)

Acceso a dispositivo de video

Acceso a dispositivos de consola

Manager de memoria

Cache de dispositivos de bloque (disco por ejemplo).

Creación dinámica de procesos.

Funcionamiento en modo protegido.

Page 10: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Especificación técnicas

Tipo de Kernel: Monolítico

Arquitecturas soportadas:

a) Intel 80386b) Intel 80486 DX, 80486 DX/2, 80486 DX/4, 80486 SXc) Intel Pentiumd) Intel Pentium Proe) Intel Pentium MMXf) Intel Pentium IIg) Intel Pentium IIIh) Intel Pentium IV

Memoria requerida:

o Código: 100 Kbo Datos: 256 Kbo Pila: 512Kb

Memoria soportada: hasta 4 Gigabytes.

Librerías: POSIX compatible

void printf ( char *string, ...);void puts(char *str);int putchar (char car);void gets (char *str);int strcmp(const char *s1, const char *s2);char *strcpy (char *dest, const char *src);char *strcat(char *dest, char *src);size_t strlen(const char *s);char *strncpy (char *dest, const char *src, size_t nbytes);char *str_to_upper (char *str);int memcmp ( const void *s1, const void *s2, dword n);void *memcpy ( void *dest, const void *src, dword n);struct tm *localtime(const time_t *clock);time_t mktime(struct tm *tm);char *asctime(const struct tm *tm);int sleep(int segundos);int usleep(int usegundos);

Lenguage de programación: Assembler Intel y AT&T, C.

Page 11: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Drivers:

o Video (manejo texto)o Tecladoo Manejador de Memoriao Disco Floppyo Filesystem FAT12o Timerso Puertos de entrada y salida

3. Descripción detallada del proyecto

Este proyecto comenzó como un desarrollo orientado a un Router de capa 3. A medida que fuimos desarrollando parte de él, asimilando realmente como programar un procesador Intel 80386 (con todas sus prestaciones) y comprendiendo como funcionan los sistemas operativos actuales, nos dimos cuenta que requeríamos una base sólida sobre la cuál en un futuro podríamos implementar cualquier tipo de sistema operativo, ya sea orientado a un Router como a un Firewall, servidor o workstation. Es decir dejamos un poco de lado el objeto final del proyecto y nos centramos en desarrollar un kernel sólido y abstracto, sobre el cuál podamos escalar en buenas proporciones (queríamos evitar por todos los medios, desarrollar un código que en poco tiempo se viera saturado de errores, que no pueda crecer, y que sea difícil de comprender por terceros).

A continuación pasamos a detallar cada modulo que compone al proyecto.

Page 12: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Protección, Segmentación y Paginación

Es sabido que no todo el código posee la misma prioridad o importancia dentro de un sistema. Existen partes vitales, las cuales en caso de fallar, colapsarían todo el conjunto. Por otro lado, muchas partes del código son prescindibles, es decir, que si llegaran a fallar o a faltar, el sistema completo o al menos parte de él podría seguir funcionando sin grandes inconvenientes. Podría citar como ejemplo un device driver de una placa Token Ring, el cuál en un router podría momentáneamente fallar, sin embargo la conmutación y enrutamiento de paquetes en las demás interfaces seguiría funcionando. Es por esto que decidimos utilizar dos niveles de protección (los cuales coinciden con el Anillo 0 y 3 de la unidad de segmentación y con los privilegios User y admin de la de paginación).

Segmentación

A medida que fuimos aprendiendo como utilizar objetos realizados en C en modo protegido fuimos descubriendo que esta técnica de protección era útil en algunos casos, pero nos imposibilitada desarrollar el código libremente. ¿Por qué pasa esto?. Los compiladores de C, utilizan un modelo de segmentación Flat, el cual equivale a decir que los segmentos de Código, Datos y Stack se encuentran superpuestos en sus comienzos. Esto a primera vista parece romper los esquemas y técnicas creadas por Intel para proteger los sistemas multitarea sin embargo, como es lógico, posee una explicación.

El lenguaje C fue concebido mucho antes que Intel creara su primer microprocesador, por eso la mayoría de las cualidades de este lenguaje son genéricas para casi todas las arquitecturas de microprocesadores que existen.

Teniendo todo esto en cuenta nos limitamos a utilizar sólo dos niveles de privilegio (Kernel y User), superponiendo los segmentos de código y datos con el fin de poder programar libremente.

Paginación

Esta técnica es la que nos permite realmente evitar que un proceso corriendo en modo User pueda inferir con código o datos vitales del sistema, los cuales se encuentran en modo Kernel.

Algo muy interesante que nos permitió la paginación y que realmente nos facilitó mucho la tarea de correr paralelamente aplicaciones fue la memoria virtual. Como es bien conocido por todos la unidad de paginación permite que una aplicación “crea” que está corriendo en una dirección dada (o

Page 13: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

lógica) cuando en realidad su posición física es diferente. Esta excelente capacidad nos permitió dos cosas:

Reacomodar el código de Kernel, sus Datos y Su Pila, a direcciones virtuales, las cuales nos permitirán en un futuro expandir con facilidad el tamaño del kernel.

Correr varias aplicaciones de usuario simultáneamente. Cuando uno linkea un archivo objeto, el linker puede traducir todas esas direcciones relativas al comienzo del código a direcciones específicas dictadas por el programador. Por ejemplo nuestras aplicaciones fueron linkeadas para correr en la dirección 0x80000000 (equivalente a 2GB). ¿ Porqué tuvimos que hacer esto ? Porque no teníamos forma de saber que posiciones están libres, asi que sencillamente buscamos cualquier espacio de memoria capaz de contener el proceso a correr y lo mapeamos virtualmente en la dirección deseada ( 0x80000000 en este caso).

Memory Manager

El Memory Manager tiene por función primordial la administración de memoria, es decir, deberá saber que bloques (páginas en nuestro caso) están libres y cuáles fueron entregados a algún proceso o aplicación. El Memory Manager comienza por su inicialización contando la memoria disponible, y calcula cuantas páginas podrá brindar a los procesos que las soliciten.

Para administrar la memoria utilizamos una estructura de tipo Pila, es decir, en ella se encuentran “apiladas” las direcciones de todas las páginas disponibles. Cada vez que un proceso pide una página, el MM simplemente la “popea” del stack, mientras que cuando un proceso la libera, la “pushea” nuevamente dentro de él.

Las funciones que se encargan de esto son:

int kmalloc_page_start (addr_t *inicio, addr_t *fin);addr_t kmalloc_page();int kfree_page(addr_t direccion);

El Memory Manager también implementa las clásicas funciones de alocación dinámica de bloques de tamaño variable: malloc y free.

Page 14: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Hay muchas tareas que debe implementar a nivel paginación. Una de las más importantes es kmapmem la cuál se encarga de mapear en el directorio y tabla de página correspondiente una dirección física en una lógica. Su prototipo es:

int kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo

Existen bastantes funciones auxiliares dentro del memory manager, para simplificar y estructurar el código que lo conforma.

Multitarea

Algo fundamental e infaltable en cualquier sistema operativo es la capacidad de simular la ejecución de varias tareas en forma simultanea, brindando una performance más alta y un mayor aprovechamiento de los recursos.

En un comienzo utilizamos todos los recursos que nos brindaba la arquitectura IA32, es decir, usábamos una estructura TSS por cada proceso que fuera a correr en el CPU. ¿ Que inconvenientes tuvo esto ? Existen algunos casos, donde necesito frenar la ejecución del proceso actual y realizar ciertas comprobaciones, pero sin llegar a realizar un cambio de contexto (el cuál significa transferir 104 bytes de la memoria al microprocesador y viceversa). Por ejemplo, cada vez que se cumple un TIC de reloj (impuesto por el Timer Tick) el scheduler debe verificar si la tarea actual excedió su tiempo de ejecución (por lo que deberá dar el control a otra tarea, luego de realizar todas las acciones administrativas correspondientes) en caso negativo, debe permitir que esta tarea siga ejecutándose. Si en vez de realizar una conmutación de contexto vía TSS (es decir, mover 208 bytes) sólo “pusheamos” y “popeamos” algunos registros de propósito general, estaremos ahorrando mucho tiempo, más si se tiene en cuenta que se produce un Tick cada 10 mili segundos (es decir, 100 ticks por segundo).

Todas las tareas, ya sean en modo Usuario o modo Kernel, utilizan el mismo TSS el cual es modificado por una rutina para ese fin. A este tipo de multitarea se la llama “Multitarea por software”.

Cada vez que llega una interrupción de Timer Tick, el Kernel produce un Stack Switching (en caso que se pase de nivel de privilegio 3 a nivel 0), para poder guardar en el Stack de modo Kernel de la tarea, los valores de los registros EFLAGS, EIP y CS. Esta acción es totalmente automática y es la

Page 15: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

que permite asegurar que una tarea nunca pueda corromper la información salvada en una pila al ocurrirse una interrupción o una excepción.

Como señalamos anteriormente, cada 10 milisegundos aparece un pulso de timertick, originado por el timer 0 del 8254, esto hace que el Controlador Programable de interrupciones genera una interrupción externa que es atendida por el Kernel.

Ocurre entonces la siguiente secuencia de eventos:

Con la llegada de la interrupción de timertick, se produce un cambio de nivel (de modo Usuario a modo Kernel), este cambio es realizado por el microprocesador quien realiza un stack switching permitiendo que el kernel trabaje sin riesgos de desborde del array de usuario. Con lo que en nuestro stack de modo kernel tenemos la dirección y segmento de retorno (registros EIP y CS), el estado de los flags (EFLAGS) y la dirección y segmento del stack de modo usuario.

En este momento guardamos en la pila (recordemos que ya estamos en modo kernel) los registros que cambian entre tareas (el código siguiente pertenece al archivo task.asm):

_switch_to_kernel_mode: ;(punto de entrada de la IRQ0)....push ebppush esipush edipush edxpush ecxpush ebxpush eaxpush dspush espush fspush gs.....

Resguardados estos registros, debemos comenzar a utilizar un stack de modo kernel pero de mayor tamaño e independiente de la tarea, para esto primero guardamos el puntero de pila y registro de paginación en las variables esp0 y cr3 de la estructura task_struct_t propia de la tareas:

; Guardamos el valor del esp de modo kernel de la tareamov ebx, dword [ _actual ]mov dword [ ebx ], esp

; Guardamos en la task_struct el valor del CR3

Page 16: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

mov ebx, dword [ _actual ]add ebx, 4 ;desplazar 4 bytes la direccion ya que

;CR3 es el 2do elemento de la estructuramov eax, cr3mov dword [ ebx ], eax

Y cargamos un stack de modo kernel de mayor tamaño:

; Recuperamos el stack del kernel, así trabajamos ; tranquilos y sín límitesmov eax, KERNEL_STACK_TOPmov esp, eax

Por fin, entonces pasamos el control al kernel

; Pasamos el control al kernelcall _timertick_handler

El handler de timertick es una función que actualiza los ticks transcurridos, actualiza el reloj del sistema, actualiza y cheque que no se hayan vencidos los timers, actualiza la estadísticas de uso del proceso en curso (ticks restantes y ticks totales utilizados), y en caso que haya terminado el tiempo de ejecución del proceso se llama al scheduler quien selecciona la próxima tarea a ejecutar. Todo esto lo veremos en mayor detalle en los punto “Timers” y “Scheduler”

El scheduler puede seleccionar otra tarea para ejecutar, con lo que cambiará la dirección apuntada por la variable actual a la estructura de la nueva tarea.

Una vez que retornamos de la función timertick_handler debemos recuperar el stack de modo kernel de la tarea:

_entrada_de_inicio:; Volvimos, ahora recuperamos el stack de modo kernel de la

tarea; que puede ser diferente a la anterior, todo depende de si se

venció; el tiempo de permanencia y/o el scheduler la switcheo (por

medio; del puntero _actual)

mov ebx, dword [ _actual ]mov eax, dword [ ebx ]mov esp, eax

Page 17: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Recuperamos su CR3

; También acá recuperamos el CR3mov ebx, dword [ _actual ]add ebx, 4mov eax, dword [ ebx ]mov cr3, eax

Si se a producido un cambio de tarea, el valor de puntero de pila de modo kernel (SS0) del TSS debe cambiarse, para poder acceder en la próxima interrupción, para ello:

; Pisamos el valor de esp0 en el TSS para que la próxima; interrupción pueda producirse; el cambio de modo ( usuario -> kernel ) de manera correcta; calculamos el top del esp0, recordando que estamos usando ; una página para el descriptor del proceso; y el stack, el cual encuentra su top al final del mismo, o sea:; top_esp0 = ( esp0 & 0xffffff00 ) + 4096

mov eax, espand eax, 0xfffff000add eax, 0x1000

mov dword [ _tss + OFFSET_ESP0 ], eax

Para entender un poco el código precedente debe tenerse en cuenta que cada tarea aloja en una misma página de 4Kb el contenido de su estructura (task_struct_t) al principio y su stack de modo kernel desde el final de dicha página.

Finalmente recuperamos todos los registros de este stack y retornamos:

; Recuperamos el contenido de todos los registrospop gspop fspop espop dspop eaxpop ebxpop ecxpop edxpop edipop esipop ebp

iret

Page 18: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Cuando el microprocesador ejecuta la instrucción iret pasa de modo Kernel a modo Usuario y recupera los registros de contexto de ejecución CS, EIP y EFLAGS, y la tarea vuelve a su ejecución habitual.

Llamadas al sistema

Tienen por objeto que los procesos que corren en espacio de Usuario puedan tener acceso a diferentes funciones del kernel, acceso a periféricos, comunicación con otros procesos, etc.

Las llamadas al sistema las implementamos vía interrupciones, específicamente en la int 0x50. Cuando alguna función de librería o el código usuario ejecuta la instrucción “int 0x50” inmediatamente se realiza un Stack Switching y la correspondiente toma de los parámetros. Estos últimos son recibidos mediante los registros de propósito general (eax, ebx, ecx, edx, esi y edi).

Ejemplo de llamada al sistema FORK:

int fork(void) {__asm__ __volatile__ ("movl %0, %%eax" : : "g" (SYS_PROCESS |

SYS_FORK) : "eax");

__asm__ __volatile__ ("int $0x50"); }

A diferencia de Linux que recibe las llamadas y las ejecuta apoyandose en un vector de punteros, nosotros implementamos varios vectores de punteros, separando las llamadas y clasificándolas en grupos). Si bien nuestro sistema es levemente mas lento que el utilizado por linux, permite mayor claridad al mirar el código fuente, con una consecuente mayor facilidad para interpretarlo.

Qué código es el que corre al ejecutarse “int 0x50”

_intSysCall:push eaxshr eax, 16 ;Verificar si el numero de grupo existecmp eax, MAX_SYSCALLS_GROUPSja error_syscall_nopop eaxPusheo los registros donde recibo los parámetros push ebppush esipush edipush edx

Page 19: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

push ecxpush ebxUsar como directorio de paginas el CR3 del Kernelmov ebx, [ _KERNEL_PDT ]mov cr3, ebxmov ebx, eaxshr ebx, 16 ;Pongo en ebx el numero de grupo de llamadas

jmp [_syscall_group_vector + ebx * 4] ; (El vector de grupos de llamadas a funciones se encuentra definido en syscalls.c )

Las llamadas implementadas al momento son:

Funciones de grupo PROCESS#define SYS_EXEC 0#define SYS_VOID 1#define SYS_FORK 2

Funciones de grupo CONSOLE#define SYS_PRINT 0#define SYS_GETS 1#define SYS_CLRSCR 2

Funciones de grupo TIMER#define SYS_SLEEP 0#define SYS_PROC_DUMP 1#define SYS_KILL 2#define SYS_USLEEP 3

Controlador de Floppy y DMA

Este driver lo implementamos para poder comprobar que tan estable era nuestro kernel ejecutando tareas dinámicas (es decir, cargadas desde algún medio, luego de haberse establecido las funcionalidades de sistema operativo).

Realmente nos tomó un poco más del tiempo del que esperábamos, ya que nos topamos con problemas “mecánicos” que nunca antes habíamos tenido. Como el controlador de floppy Intel 82077ª fue evolucionando a lo largo del tiempo para poder manejar discos de diferente tamaños físicos, densidades y estructuras lógicas, fue manteniendo compatibilidad hacia atrás, a medida que pasaba le tiempo. Esto que desde algún punto de vista es una característica muy positiva, se transforma en una carga a la hora de escribir un driver que pueda manejarlo. Existen múltiples comandos que realizan las mismas tareas, pero dejan algunos registros en estados diferentes, por lo que el programador debe tener mucho cuidado en como los utiliza.

El acceso a los sectores de disco es de tipo CHS (cilindro, cara, pista) por lo que el driver deberá encargarse de hacer las traducciones pertinentes dependiendo de la capacidad y del formateo del disco.

Page 20: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

El hecho que posea una gran cantidad de mecánica hace que deban tenerse en cuenta consideraciones necesarias, por ejemplo, para esperar a que el motor alcance la velocidad de régimen permanente. También deberá mantenerse una relación de compromiso en el apagado del motor, ya que si este permanece siempre encendido, su vida útil será muy baja; mientras que si lo apagamos inmediatamente después de un acceso, deberemos nuevamente esperar a que alcance la velocidad de régimen permanente antes de volver a realizar otra lectura (aumentando mucho el tiempo de lectura).

Además nos vimos en la obligación de aprender a configurar el controlador de DMA 8237ª, para lograr hacer transferencias por bloques y no por bytes.

Las funciones que componen al driver son:

1. void motor_on();(Enciende el motor)

2. void motor_off();(Apaga el motor)

3. int floppy_sendbyte(byte valor);(Envia un byte al registro de datos del controlador )

4. int floppy_get_result();(Lee un byte del registro de datos del controlador)

5. int init_floppy();(Inicializa al controlador)

6. int recalibrate();(Recalibra la posicion de la cabeza a la pista 0)

7. byte seek (byte cara, byte pista);(Posicionar el cabezal sobre la pista indicada)

8. int read_sector (byte cara, byte cilindro, byte sector);(Lee un sector físico (previamente el cabezal debe estar calibrado y posicionado)

9. int block(void);(block: bloquea la ejecución del proceso que la llama hasta recibir una interrupción de floppy)

10. void init_floppy_DMA ( byte comando );(Inicializa el controlador DMA, tanto para leer como para escribir (según comando))

11. int leer_escribir(byte operacion, dword sector_logico, byte *buffer);

Page 21: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

(Acepta como operación READ_SECTOR y WRITE_SECTOR. Es la encargada de convertir un sector lógico (o LBA) en el sector físico (CHS) correspondiente. Inicializa el controlador de floppy y enciende el motor. En caso de time outs, intenta hasta MAX_TRYS)

Controlador de FAT12

Implementamos este file system ya que es uno de los más sencillos, es leído por casi todos los sistemas operativos y es el sistema de archivos utilizado generalmente en los discos flexibles.

Las funciones comprendidas por este controlador tienen por objeto hacer transparente a las llamadas de archivos el acceso lógico a los archivos. El controlador está formado por:

1. int fat_12(void);(Lee el sector logico 0 (Boot sector), y levanta todos los parametros fisicos y logicos del disco para que sean usados por las demás funciones)

2. int levantar_fat(void);(Levanta todos los sectores correspondientes a la FAT y los coloca en la memoria Debera tenerse en cuenta que al cambiar el diskette, el flag "fat_levantada" debera volverse a FALSE)

3. fat12_entry_t *fat_file_find (char *nombre, fat12_entry_t *datos_archivo); (Recibe un nombre de archivo, y lo busca en el disco. En caso negativo retorna NULL)

4. int fat_next_sector ( dword sector_inicial );(Esta función recibe como parámetro un numero de sector y mediante la FAT obtiene cual es el siguiente)

5. void fat_adapta_name (byte *nombre_fat, byte *adaptado);(Recibe un nombre en formato FAT ( KERNEL BIN ) y lo transforma a un formato tipo string: KERNEL.BIN\0 )

6. void *floppy_cache (dword sector);Esta funcion mantiene una lista enlazada con sectores leidos del floppy. Cualquier funcion de fs que quiera leer o escribir un sector, deberá recurrir a esta. Devuelve un puntero a la dirección de memoria donde se encuentra el sector pedido)

Llamadas para el manejo de archivos

Dentro de este conjunto caen las funciones open, close, read y lseek (la función write no ha sido implementada, debido a que requiere para un

Page 22: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

correcto funcionamiento la implementación de spinlocks o candados dentro del kernel). Estas funciones poseen el mismo prototipo que sus pares del estándar Unix , con el fin de mantener cierta compatibilidad en lo que a desarrollo de aplicaciones se refiere.

Los prototipos son:

int open (char *nombre);int close (int fd);ssize_t read (int fd, void *buf, size_t len);int lseek (int fd, int offset, int donde);

Timers

Los timers son la base para el manejo de tiempos en el sistema, desde la simple actualización horaria pasando por funciones que permiten detenar la ejecución de una tarea durante cierto.

En nuestro sistema operativo implementamos el manejo y actualización de la fecha y hora, leyendo el Real Time Clock durante el inicio y actualizándolo con cada tick recibido, así como las funciones de librería necesarias para acceder a ellas:

1. struct tm *localtime(const time_t *clock)2. time_t mktime(struct tm *tm)3. char *asctime(const struct tm *tm)

siendo struct tm:

// Estructura tmstruct tm { int tm_sec; /* seconds after the minute - [0, 61] */ /* for leap seconds */ int tm_min; /* minutes after the hour - [0, 59] */ int tm_hour; /* hour since midnight - [0, 23] */ int tm_mday; /* day of the month - [1, 31] */ int tm_mon; /* months since January - [0, 11] */ int tm_year; /* years since 1900 */ int tm_wday; /* days since Sunday - [0, 6] */ int tm_yday; /* days since January 1 - [0, 365] */ int tm_isdst; /* flag for alternate daylight savings time */};

typedef int time_t;

Page 23: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

El kernel maneja también timers, que son activados ante ciertos eventos, por ejemplo, surgió como necesidad fundamental cuando se requería realizar demoras controladas en los programas, veamos el siguiente ejemplo:

for ( i=0; i<CUENTA_DEMORA; i++) { ....}

el código precedente permite realizar una demora, pero tiene dos falencias fundamentales:

No puede controlarse con exactitud el tiempo de demora, y de hecho varía según la velocidad de ejecución del microprocesador

Durante el tiempo de demora se sigue utilizando el procesador.

Estas dos condiciones resultan inaceptables. Para solucionar este inconveniente aparecen las funciones sleep y usleep que permiten dormir una tarea durante un cierto tiempo, o sea, la tarea queda en estado TASK_STOPPED mientras no se llego al tiempo especificado, con lo que no es ejecutada por el scheduler y entonces libera tiempo para que otros procesos utilicen el procesador.

1. int sleep(int segundos)2. int usleep(int usegundos)

Scheduler

Es el encargado de seleccionar la próxima tarea que se ejecutará en el microprocesador.

Cuando una tarea en ejecución vence el tiempo actividad (ver la secuencia explicada en la sección “Multitarea”) el scheduler toma control de la situación y decide cuál será la tarea a ejecutarse.

Para realizar esta selección el Scheduler cuenta con una lista enlazada de tareas (figura 1), cada tarea esta unívocamente caracterizada por la estructura task_struct_t:

typedef struct task_struct_t{

Page 24: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

dword esp0; dword cr3; dword cr3_backup; pid_t pid; struct task_struct_t *proxima; char descripcion[MAX_DESCRIPTION]; byte estado; word prioridad; word cuenta; dword tiempo_cpu; struct file *open_files [MAX_FILES_POR_TAREA]; //definido en file.h void *paginas[MAX_PAGINAS_POR_TAREA]; word num_code; //cantidad de paginas de codigo de la tarea word num_data; //cantidad de paginas de datos y bss int err_no; signal_struct_t senales;} task_struct_t ;

El scheduler utiliza los campos proxima y estado para encontrar la próxima tarea a ejecutar, lo cual es un método sencillo pero eficiente de selección, en una primer etapa, luego seguiremos avanzando con el fin de que el algoritmo de selección tenga en cuenta muchas mas variables (prioridad por ejemplo).

Aplicaciones

Como ya hemos comentado anteriormente, el kernel corre aplicaciones en un nivel de ejecucion 3 de la unidad de segmentacion y en modo usuario de la de paginacion. Al referirnos a aplicaciones podemos estar hablando tanto

Tarea 1

T ASK_ RUNN I NG

Proxim a

Tarea 2

T ASK_ STO PPED

Proxima

Tarea 3

T ASK_ RUNN I NG

P roxima

Tarea 4

T ASK_ RUNN I NG

Proxima

Tarea 5

T ASK_ ST O PPED

Proxima

I nicio

N ULL

Figura 1

Page 25: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

de programas de usuario normales, de drivers, o de la implementacion de algun tipo de servicio de red. Esto dependera de las funcionalidades del sistema, ya que como dijimos anteriormente nuestra intencion es general un kernel funcional, el cual sea facilmente adaptable para cumplir diferentes tareas. Alguien podria querer, por ejemplo, implementar un Firewall compuesto por varios modulos independientes al kernel, entonces para evitar o reducir los problemas que pueda causar alguno de ellos, simplemente se los ejecuta en modo User, es decir como una aplicacion.

Las aplicaciones deben estar realizadas en formato COFF32 (en un futuro proximo se implementara la ejecucion de tareas en formato ELF32).

Poseen como requisito fundamental ser linkeadas en la direccion virtual VMA (virtual memory address) 0x80000000 mediante el GNU LD.

Cada tarea poseera, al ejecutarse, su propio espacio de direcciones, es decir, que al ser ejecutada, se cambia el directorio de paginas de la tarea anterior por el de la tarea actual, el cual contiene los mapeos de los datos y codigo del kernel, sumados a los de esta tarea en particular.

Page 26: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

4. Conexiones Eléctricas

Generalidades

En esta sección del informe se presentarán las conexiones eléctricas que utiliza el hardware que se utiliza como base para la ejecución del sistema operativo.

Comenzaremos mostrando un esquema funcional del microprocesador utilizado para luego poder entendar las conexiones que se realizan a los dispositivos externos al mismo por medio de la placa base (motherboard).

Este primer diagrama nos muestra el bus del sistema y la interrelación del mismo con el bus de cache de nivel 1 y 2 fundamentales para proporcionar performance al sistema que se lo utilice como base.

Page 27: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Vemos a continuación el mismo diagrama con un mayor grado de detalle. Pueden ver los tres bloques que conforman el decodificador de instrucciones (Instruction Decoder) junto con los cinco bloques que pertenecen a la Unidad de Ejecución (Execution Unit).

A continuación se presentan los diagramas eléctricos de la interconexión del microprocesador con los dispositivos como la unidad controladora de floppy, memoria, controladora ide, isa, teclado, video, etc...

Page 28: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Circuitos

Diagrama general de conexión del microprocesador. para una mejor visualización se adjuntan los diagramas en formato pdf).

Page 29: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Diagrama de conexión del emulador.(para una mejor visualización se adjuntan los diagramas en formato pdf).

Page 30: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Diagrama general de conexión de la controladora de floppy (para una mejor visualización se adjuntan los diagramas en formato pdf).

Page 31: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Diagrama general de conexión del microprocesador. (para una mejor visualización se adjuntan los diagramas en formato pdf).

Page 32: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Diagrama general de conexión del bus IDE. (para una mejor visualización se adjuntan los diagramas en formato pdf).

Page 33: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Diagrama general de conexión del bus ISA. (para una mejor visualización se adjuntan los diagramas en formato pdf).

Page 34: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Diagrama general de conexión del teclado. (para una mejor visualización se adjuntan los diagramas en formato pdf).

Page 35: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Diagrama general de conexión del LA. (para una mejor visualización se adjuntan los diagramas en formato pdf).

Page 36: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Diagrama general de conexión del mouse y teclado. (para una mejor visualización se adjuntan los diagramas en formato pdf).

Page 37: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Diagrama general de conexión PCMCIA. (para una mejor visualización se adjuntan los diagramas en formato pdf).

Page 38: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Diagrama general de la fuente de alimentación. (para una mejor visualización se adjuntan los diagramas en formato pdf).

Page 39: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Diagrama general de conexión del generador de clock. (para una mejor visualización se adjuntan los diagramas en formato pdf).

Page 40: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Diagrama general de conexión de los puertos seriales. (para una mejor visualización se adjuntan los diagramas en formato pdf).

Page 41: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Diagrama general de conexión del terminador. (para una mejor visualización se adjuntan los diagramas en formato pdf).

Page 42: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Diagrama general de conexión VGA. (para una mejor visualización se adjuntan los diagramas en formato pdf).

Page 43: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Diagrama general de conexión de la memoria. (para una mejor visualización se adjuntan los diagramas en formato pdf).

Page 44: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

5. Circuitos impresos

Antes que nada, debemos recordar que hemos elegido desarrollar este proyecto basándonos en la familia de microprocesadores de 32 bits de Intel. La elección fue realizada partiendo de la base que son la familia de microprocesadores más vendida, y de más bajo costo; por lo que es muy fácil encontrar una arquitectura de este tipo en nuestro país, a fin de hacer sobre la misma el deploy de Routix.

Debido al tamaño de las imágenes referidas a los circuitos, hemos preferido referirnos directamente a las hojas de dato del fabricante.

Figura 1: (Figura 2-1, página 22 del manual Intel EXPLR1 Embedded PC Evaluation Platform Board Manual)

Figura 2: (Figura 5.1 , página 51 del manual Intel EXPLR1 Embedded PC Evaluation Platform Board Manual)

Figura 3: (Figura 5.2 , página 52 del manual Intel EXPLR1 Embedded PC Evaluation Platform Board Manual)

Vale aclarar que las figuras corresponden a un hardware Embebido conteniendo un microprocesador de la Familia Intel modelo 386SX. Podrían haberse seleccionado otras configuraciones, pero hemos decidido mostrar aquí sólo la más económica.

Page 45: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

6. Diagrama de Interconexión de Componentes

Adjuntamos a continuación algunas figuras que muestran posibles distribuciones de los componentes sobre una placa base o motherboard, recordar que esto es función de la marca y modelo, por lo que nos limitaremos a mostrar algunas de ellas.

Page 46: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,
Page 47: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

7. Diagramas de Interconexionado

NOTA: recordemos que el hardware del proyecto puede depender de la versión del microprocesador utilizado (siempre y cuando, obviamente, pertenezca a la familia Intel IA32). Por cuestiones de simplicidad hemos elegido mostrar los diagramas pertenecientes al interconexionado de un microprocesador 80386.

Estos diagramas esquemáticos han sido obtenidos del sitio oficial de Intel Co.

http://www.intel.com/design/intarch/intel386/docs_386.htm#Schematics

Page 48: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,
Page 49: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,
Page 50: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,
Page 51: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,
Page 52: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,
Page 53: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,
Page 54: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

8. Planos Mecánicos

Veamos algunos dibujos de frente, posterior y de la placa base de una PC convencional donde corre el sistema operativo Routix.

Page 55: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,
Page 56: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

9. Lista de Componentes

A continuación se detallan los componentes principales de hardware necesarios para llevar a cabo el proyecto.

1. Procesador Intel de la familia IA32

2. Placa base (Motherboard, Intel Compatible.)

3. 8259 Controlador programable de Interrupciones (PIC)

4. 8254 Timer Tic.

5. 82077AA Controlador de disquetera (Single-Chip Floppy Disk Controller)

6. Disquetera3 ½ (Floppy Drive)

7. 8452 Controlador de Teclado (Keyboard Controller)

8. 8237ª Controlador de DMA

Se adjuntan hojas de datos de una familia de fabricantes. Si bien existe una gran cantidad de fabricantes para los periféricos (8259, 8254, 8452, 84077AA) todos cumplen con un standar predefinido, por lo que la única diferencia es el costo y la calidad técnica de los manuales, a nivel funcional son exactamente iguales.

Si bien el desarrollo del sistema de archivos FAT a sido nuestro, nos hemos basado en un standar ya existente, por lo que también incluimos la especificación FAT de Microsoft Co. Denominada: “Microsoft Extensible Firmware Initiative FAT32 File System Specification”

Page 57: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

10. Cálculo de Confibilidad en los circuitos y programas de Computación

Definición de Confiabilidad

Es la probabilidad que tiene un elemento de funcionar correctamente durante un determinado período de tiempo bajo ciertas condiciones de funcionamiento.

Debemos tener en cuenta los siguientes aspectos al momento de tratar con la confibilidad:

Al representar una entidad probabilística su valor varía entre 0 (cero) y 1 (uno).

Se debe precisar el tiempo de funcionamiento esperado, sobre el que se estima la confiabilidad.

Debe haber una correcta especificación de los requerimientos del elemento, para poder determinar con exactitud si presenta o no una falla.

Las condiciones de funcionamiento deben ser especificadas en detalle, ya que de ellas depende fuertemente la confibilidad resultante.

Concepto de Falla

Se produce una falla cuando el elemento o sistema no es capaz de cumplir adecuadamente lo indicado por las especificaciones.

Podemos clasificarlas dentro de los siguientes grupos:

1. Fallas paramétricas2. Fallas aleatorias3. Fallas por desgaste

Page 58: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Fallas paramétricas

También se las denomina por degradación y se producen en los elementos o equipos electrónicos cuando una característica o parámetro empieza a degradarse, disminuyendo su prestación hasta quedar por debajo de lo especificado y convertirse en falla.Dependen parcialmente del tiempo y por lo tanto pueden prevenirse. Suelen producirse por corrosión o contaminación con influencia de condiciones ambientales.

Fallas aleatorias

Pueden lograr la destrucción total de un elemento. Aparecen súbitamente, sin aviso previo, y sin que sea posible predecir su ocurrencia individual. Pueden traer aparejado una disminución en las prestaciones hasta la destrucción total del equipo.

A diferencia de las fallas paramétricas, no presentan dependencia temporal, pero si puede hablarse de probabilidades en grandes números.

Fallas por desgaste

Se deben al desgaste de un elemento por su propio uso, generalmente son de caracter mecánico y de fuerte dependencia temporal, siempre y cuando se haga un uso adecuado del mismo dentro de las especificaciones dadas, o sea, si por ejemplo se trabaja un transistor la mayor parte del tiempo casi al 100% de la potencia máxima que puede disipar, su probabilidad de fallas por desgaste crece drásticamente. (De hecho la vida útil de un semiconductor aumenta al doble por cada 8°C que disminuimos de la temperatura máxima de juntura).

Confiabilidad del hardware

En nuestro proyecto particularmente el hardware utilizado sirvió como base para el desarrollo y funcionamiento del Sistema Operativo Routix. La línea de microprocesadores utilizados fue Intel y por tanto la confiabilidad del microprocesador varía de en cada línea de los mismos soportada, y es función de la marca de motherboard utilizada:

Intel 80386 Intel 80486 DX, 80486 DX/2, 80486 DX/4, 80486 SX Intel Pentium

Page 59: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Intel Pentium Pro Intel Pentium MMX Intel Pentium II Intel Pentium III Intel Pentium IV

Confiabilidad del Software

Se define confiabilidad del software como la probabilidad de que el mismo se ejecute correctamente, de acuerdo a especificaciones dada, y para un determinado período. Involucra el código y el entorno donde se esta ejecutando.

La confiabilidad de un software está integramente relacionada con errores de programación, los cuales clasificaremos en la sección siguiente.

Clasificación de los errores

Errores previos fijos:Son aquellos que subsisten luego que se ha trabajado en el debug del software o cambiando el código.

GeneradosAquellos que se producen como consecuencia de un error involuntario al modificar una parte determinada de código, ya sea al intentar erradicar un ‘bug’ o agregar una nueva funcionalidad.

Es fundamental que el programador realice un análisis detallado de su código al terminar un módulo del mismo, o sea, conviene dividir el análisis de errores por bloques de código asociados a una determinada funcionalidad. En nuestro caso, esta división se realizó de la siguiente manera:

Módulo de Arranque

Módulo de Scheduler

Módulo de Manejo de memoria Modo Kernel

Page 60: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Modo usuario

Módulo de drivers

Video

Teclado

Entrada-Salida (I/O)

Floppy

FAT12

Timers (8254)

Módulo de Timers

Módulo de Señales

Módulo de Llamadas al Sistema (syscalls)

Definición Matemática

Basemos en el siguiente gráfico para entender como interactúa un sistema respecto a sus entradas y como genera sus salidas:

Dado un conjunto de entradas posibles:

y un grupo de salidas:

SOFTWARESOFTWAREEntradaEi

SalidaF(Ei)

Page 61: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Y entonces fácilmente podemos decir que falla cuando:

Debido a que existen errores (bugs) producidos en la etapa de diseño y en la etapa de desarrollo del software.

El conjunto de entradas tiene asociado probabilidades que denominaremos Pi, y por tanto podemos generalizar la siguiente expresión:

Siendo Mi nulo cuando existe un error y de valor unitario en caso de haberlo.

y considerando las entradas independientes:

Y se puede determinar el valor de C(1) realizando varias corridas, y mediante la siguiente expresión:

siendo nf el número de fallas y n el número total de corridas.

Para el sistema operativo hemos realizado, mediante automatizaciones y chequeos de diversos tipos la cantidad de 5000 pruebas fallando 15 veces, las cuales luego de un análisis pudimos reducir a 0.

Por lo tanto podemos determinar el valor de la confiabilidad:

Page 62: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Predicción de la confiabilidad

Los modelos de confiabilidad no son simples y no hay uno que se utilice por sobre los demás.

La precisión puede variar bastante para un mismo programa en función de las entradas, pero no puede determinarse desde el momento inicial cual será el mejor grupo de ellas a aplicar.

Debido a esta problemática se han desarrollado técnicas que permiten evaluar el error en la estimación de confiabilidad de los distintos métodos.

Macromodelo de Musa

Se utiliza para estimar la confiabilidad, se dice que es un macromodelo por que no tiene en cuenta la estructura interna del software, se basa en conteo de errores.

La hipótesis que se asume es que todas las falla en el software son debidas a errores residuales o remanentes, en consecuencia la tasa de fallas es proporcional al número de errores remanentes en el programa.

Se parte de la tasa de fallas:

y entonces la probabilidad de operación correcta será:

Page 63: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

y el tiempo medio entre fallas (MTTF) será:

considerando una tasa de remoción de errores constante,

el MTTF queda:

con:

una vez definido esto resta comentar que para la estimación de los coeficientes del macromodelo pueden usarse los siguientes métodos:

a. Estimación por Máxima verosimilitudb. Estimación por momentosc. Estimación por cuadrados mínimos

Estas 3 técnicas se basan en los tiempos del proceso de Debbuging, el computo del tiempo total de horas de ejecución (H), el numero de corridas exitosas y fallidas para luego estimar ET y K.

Las técnicas de máxima verosimilitud y mínimos cuadrados requieren conocer en formas mas precisa en conjunto de datos T1,T2,T3,..,Tn-r y t1,t2,..tn-r. Obteniéndose mas precisión que la estimación por momentos.

En nuestro caso, según las pruebas realizadas tenemos:

Page 64: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Corridas exitosas = n-r

donde n:corridas del programa de las cuales falla r veces.

Tiempos de funcionamiento sin falla: T1,T2,T3,...,Tn-r

Tiempos de funcionamiento hasta la falla: t1,t2,t3,...,tr

Entonces las horas totales de funcionamiento serán:

y la tasa de fallas será:

y su inversa el MTTF

En nuestro caso, conociendo IT (cantidad de instrucciones en lenguaje máquina).

IT=300000

Con un tiempo de ejecución H=100 horas y realizando ET=5000 corridas.

Estimación por momentos

Consiste en realizar una prueba funcional en dos tiempos de depurado diferentes td1 y td2, con td1 < td2 y ec(td1) < ec(td2), es decir, se corrigieron errores entre estos dos tiempos.

Page 65: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Para cada intervalo debemos computar el tiempo total de ejecución, la cantidad de corridas exitosas y las fallidas; con esto podemos estimar el MTTF:

y de este sistema de ecuaciones se puede estimar K y Et,

y en nuestro caso será:

Et=49

K=172.45

Estimación por cuadrados mínimos

Utilizando la siguiente ecuación:

Page 66: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

o expresada mediante la ecuación de la recta:

Estimaremos los parámetros de la recta en base a las muestras, utilizando mínimos cuadrados (minimización del error cuadrático medio).

tdi ec(tdi) n r λ MTTFhoras errores ejecuciones fallas falla/hora hora/falla

1 11 50 16 16,00 0,06252 19 100 23 11,50 0,0869573 23 150 28 9,33 0,1071435 27 250 31 6,20 0,16129

10 29 500 33 3,30 0,3030315 33 750 34 2,27 0,44117620 35 1000 36 1,80 0,55555630 35 1500 36 1,20 0,83333350 36 2500 36 0,72 1,38888970 36 3500 37 0,53 1,891892

100 37 5000 37 0,37 2,702703

y graficando la tasa de fallas en función del tiempo de ejecución:

Tasa de fallas

0,002,004,006,008,00

10,0012,0014,0016,0018,00

1 2 3 5 10 15 20 30 50 70 100

horas

falla

s po

r hor

a

Page 67: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

11. Instrucciones de puesta en marcha, ensayo funcional, ajuste y calibración, registros.

Existen dos formas de poner en marcha el proyecto.

Directamente sobre una PC Corriéndolo sobre un emulador de PC (nosotros elegimos el Bochs

Emulator, pero podría haber sido el VmWare, VirtualPC, etc.).

Sea cuál sea la forma elegida como primer paso debe tenerse la distribución del mismo en el archivo denominado routix.zip que puede ser descargado desde la página Web routix.sf.net. También pueden obtenerse las fuentes, para que cualquiera pueda entender su funcionamiento, corregir errores o adaptarlo a tareas personales.

Deberá descomprimirse utilizando la herramienta WinZip o Winrar. Luego de realizada la descompresión, deberá ejecutar el programa “Install.exe”, el cuál lo guiará por pasos muy simples para poder instalar routix en un disquetera booteable.

Una vez instalado, simplemente se deberá reiniciar la máquina con el disquete colocado en la disquetera, con lo que iniciará el sistema, dejándolo en el shell de routix para que pueda introducir comandos.

A continuación se detalla el proceso para modificar el código de programa, cosa que no es recomendada excepto que se tengan los conocimientos suficientes del microprocesador y de arquitectura elegida para el proyecto.

Para el desarrollo se recomienda el siguiente software

Software recomendado.

Bochs Emulator DJGPP Nasm Winimage

Obtención de los Fuentes

La obtención de la última versión disponible vía CVS se encuentra en SourceForge. Allí mismo se detalla el método de acceso: Project: Routix OS: CVS

Page 68: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Bochs

¿ Qué es Bochs ?

No se trata de una mera maquina virtual sino más bien de un autentico emulador PC de tipo 386, 486, Pentium, Pentium Pro o AMD64, incluyendo opciones como MMX, SSE, SSE2 y hasta instrucciones 3DNow, capaz de emular la CPU, la BIOS y cargar la imagen de cualquier sistema operativo, sea éste último Windows XP o cualquiera de las distribuciones GNU/Linux disponibles en el mercado

Por lo que podremos ejecutar, por ejemplo, un sistema tipo Windows XP desde una ventana de nuestro GNU/Linux Mandrake, con el propósito de ir probando programas Windows XP sin renunciar a la comodidad de nuestro GNU/Linux. ¿Eres usuario Windows y quieres probar Linux sin cargarte al Windows? Pues, creas un PC virtual y montas una imagen GNU/Linux, sea cual sea la distribución. Brinda soporte 3DNow, SSE, SSE2, PNI(SSE3), imágenes de disco en el formato Vmware3 y la emulación VGA.

Basado en Wintel, se trata de un proyecto multiplataforma y totalmente open source, por lo que podremos probarlo de forma gratuita y hasta disfrutar de una pequeña imagen del Linux Mandrake. Es el programa ideal tanto para los programadores y desarrolladores de utilidades como usuarios Windows que quieran darse el primer chapuzón con GNu/Linux, pasando por un suave artificio: Bochs.

Una vez que tenemos a Bochs configurado podemos bajar el archivo Routix- Bochs.zip el cuál nos simplificará la configuración del emulador para correr Routix. Como verán, dentro de Routix-Bochs.zip se encuentra un directorio, el cuál deberá ser colocado dentro del dir donde se instaló a Bochs (el cual denominaremos Bochs_PATH). Solo basta ejecutar el bochsrc.bxrc para poder tener a Routix corriendo.

GCC

Sólo daremos una breve descripción sobre este compilador, podrá encontrar el resto de la información en gcc.gnu.org

GCC es un compilador integrado del proyecto GNU para C, C++, Objective C y Fortran; es capaz de recibir un programa fuente en cualquiera de estos lenguajes y generar un programa ejecutable binario en el lenguaje de la máquina donde ha de correr. La sigla GCC significa "GNU Compiler Collection". Originalmente significaba "GNU C Compiler"; todavía se usa GCC para designar una compilación en C. G++ refiere a una compilación en C++. Como curiosidad, mencionar que en realidad gcc no genera código binario alguno, sino código ensamblado. La fase de ensamblado a código binario la realiza el ensamblador de GNU (gas), y el enlazado de los objetos resultantes, el enlazador de GNU (ld). Este proceso es transparente para el usuario, ya que a no ser que se lo

Page 69: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

especifiquemos, gcc realiza el paso desde código en C a un binario ejecutable automáticamente.

Winimage

Este software es utilizado para colocar dentro de la imagen routix.img contenida en Bochs_PATH/routix los archivos que uno desee, sean o no ejecutables. Lo que nos permite hacer Wininage es crear discos crudos (o raw disks) los cuales pueden tener dentro de sí el binario conteniendo el kernel, listo para ejecutar. No queremos extendernos en todas las opciones y capacidades de este software, el cuál al poseer interfaz gráfica es muy intuitivo y fácil de utilizar.

Fuentes

El kernel de Routix se encuentra contenido en el archivo kernel.bin, el cuál es compilado al tipear “make” dentro del directorio base de Routix (suponiendo que djgpp y nasm están perfectamente configurados). En “src” se encuentran los fuentes del kernel mismo, mientras que en tareas pueden encontrar los fuentes de algunos programas que corren en modo usuario, incluido el Shell2 (utilizado actualmente por nosotros para realizar pruebas). En el directorio “Template” dentro de tareas, se encuentra un ejemplo de cómo debe realizarse un programa en routix. Allí se incluye el script de LD necesario para generar un COFF32 compatible con Routix.

Page 70: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

12. Ensayos de aceptación y registro

El sistema operativo ha sido probado en la totalidad de los aspectos respecto a las características propias (features como más se lo conoce en la jerga técnica).

Las primeras pruebas apuntaron al testeo de un inicio coherente y sin problemas, se buscaron “pérdidas de memoria” (memory leaks), segmentos de datos sin inicializar, excepciones mal trapeadas, errores en el sistema de páginación inicial.

Luego de esta exhaustiva prueba, y habiendo finalizado los drivers de teclado y video, se procedió a el ingreso de información a una velocidad mayor que el promedio de tipeo (entre 50 y 100 ms entre cada presión de tecla) para intentar lograr desbordar los buffers internos del sistema, tarea que arrojo los resultados esperados, y que permitió redimensionar el buffer de modo de evitar errores. Posteriormente se realizaron programas de testeo apuntando a detectar desbordes y errores en el driver de video, llevando las condiciones de testeo al límite tuvo un excelente respuesta y nos permitió realizar muchos ajustes (funciones de borrado de pantalla, de impresión de caracteres y strings como printf).

El siguiente ensayo fue sobre el gestionador de memoria, sobre quien se realizaron cientos de pruebas en búsqueda de un error que proporcionara o fuera indicador de una futura inestabilidad del sistema, encontramos sobre este muchos errores, y tuvimos que implementar un wrapper que permitiera disminuir los tiempos de debugging ya que el alocador de memoria era usado desde casi todo el ancho del sistema operativo.

#define MALLOC(alloc_type,size)mm_wrapper_malloc((alloc_type),(size))

#define FREE(alloc_type,address)mm_wrapper_free((alloc_type),(address))

El paso siguiente fue el testeo de los timers, para ello se pusieron a correr numerosa cantidad de procesos en paralelo generando cada uno de ellos llamadas a sistema que generaban instancias de timers, vimos aquí algunas posibilidades de optimización en las estructuras de ordenación de los mismos, y las aprovechamos mejorando la performance considerablemente.

Paso siguiente fue el testeo del driver de floppy, ya que luego de haber escrito su segunda versión con soporte asincrónico (el cual permite una utilización más eficiente de los recursos del sistema como Cpu) presentó muchos cambios y trajo aparejado ciertos errores que desaparecieron luego de esta etapa.

Page 71: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Luego fue el turno de las llamadas a sistema que permiten crear múltiples procesos como por ejemplo fork(), allí pudimos gracias a los testeos detectar algunos errores más que tenían que ver con la asignación de los directorios de páginas e índices del sistema de páginación.

Finalmente nos centramos en el testeo de la parte IPC del kernel, particularmente el intercambio de señales entre procesos, donde se arrojaron algunas excepciones y finalmente, luego de un intensivo análisis, pudieron corregirse exitosamente.

Como comentario final, podemos decir que la versión final de Routix testeada cumple con las expectativas esperadas tanto en estabilidad, confiabilidad y performance.

13. Instrucciones de instalación y operación.

Una vez que se ha obtenido el archivo denominado routix.zip, se está listo para hincar la instalación. Hemos agregado a la distribución un instalador el cuál simplifica las tareas de formateo del disquete sobre el cuál deseamos trabajar. También, este instalador es el encargado de copiar en el boot sector al loador y al archivo binario del kernel. La ejecución es realmente muy simple para cualquiera que ya haya instalado en una computadora algún software. Sólo deberá posicionarse sobre el icono de instalar.exe.

NOTA: El instalador sólo corre sobre plataforma Windows, ya sea 95-98/2000-XP. Hemos considerado que cualquier persona que posea conocimientos de Linux/Unix no encontrará inconveniente alguno en copiar la imagen en el boot sector de un disquete.

Existen unos requerimientos mínimos que deben suplirse para poder instalar Routix:

1. Procesador compatible familia Intel IA32.

2. 4MB Memoria RAM

3. Disquetera con capacidad de auto arranque 5 ¼ o 3 ½

4. Controlar VGA compatible o Superior

A continuación detallamos los pasos para dejar a Routix corriendo.

1. Colocar un disquete vacío (en caso de no estarlo se perderá el contenido del mismo).

2. Ejecutar el instalador (instalar.exe)

Page 72: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

3. Seleccionar el drive o disquetera de destino.

4. Una vez finalizada la instalación, ya se encuentra en condiciones de reinar su PC.

5. Deberá asegurarse que su BIOS le permita arrancar desde el disquete, en caso de no saberlo deberá seguir por el paso 6, en caso de estar seguro o saber como configurar a su PC para que arranque desde disquete salte al paso número 12.

6. Al reiniciar la máquina presione la tecla DELETE para ingresar en el BIOS.

7. Desplazarse con las flechas y ubicarse sobre las opciones avanzadas (Advanced options). Presionar ENTER.

8. Una vez allí, deberá posicionarse sobre la opción de “Primera opción de Arranque”.

9. Con las flechas derecha e izquierda deberá moverse hasta encontrar la palabra “Floppy Drive”.

10.Una vez hecho esto debe presionar ESCAPE.

11.El sistema le consultará sobre si desea grabar los cambios, a lo que usted contestará: “salir guardando los cambios”. En caso de que haya modificado erróneamente alguna opción no debida, elija “Salir sin guardar cambios”.

12.En este punto usted está listo para iniciar Routix desde su disquete. Al iniciar la PC la luz de la disquetera se encenderá indicando que se está realizando la búsqueda en el sector de arranque.

13.En caso de haber realizado hasta aquí todos los pasos correctamente verá la inicialización del sistema.

14.Una vez detectados y configurados los periféricos el sistema lo dejará parado en un SHELL, en el cuál está listo para ejecutar comandos.

Page 73: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Imagen que muestra como se ve la pantalla luego de arrancar exitosamente Routix.

Clear: borra la pantalla

Exec: ejecuta una tarea de usuario, la cuál deberá encontrarse en formato COFF32.

Echo: imprime un texto con echo.

Ps: Process Status. Muestra información referida a los procesos que se encuentran en ejecución.

Timers: Muestra información acerca de los timers que se encuentran en ejecución.

Read: lee un sector del disquete.

kill: envía una señal a un proceso.

Info: brinda información detallada del proceso seleccionado.

Renice: modifica la prioridad de un proceso.

free mem: Muestra en pantalla la cantidad de páginas de memoria disponibles

show morecores: muestra la cantidad de morecores realizados hasta el momento. Un Morecore es realizado cada vez que la fragmentación interna de una página de memoria no posibilita una asignación vía malloc.

Page 74: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

show cache: muestra en pantalla los sectores que se encuentran en el sistema de caché.

show zombies: muestra los procesos zombies que posee el sistema.

Setvar: asigna un valor a una variable.

Getvar: obtiene el valor d euna variable.

Información obtenida luego de ejecutar el comando “info”.

Se ha solicitado información sobre el proceso el cuál posee PID 2, en este caso el SHELL. Se ve en la imagen la dirección de el directorio de páginas del proceso, la ubicación del stack de kernel, del stack de usuario, y las direcciones de las páginas de ´codigo y datos de la tarea. Se muestran tanto las direcciones físicas como las lógicas (paginadas).

Page 75: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

En este caso se ha ejecutado un “show cache”, mostrando por pantalla que sectores de disco han sido “cacheados” y cuantas páginas de memoria ocupa.

A continuación mostramos como se ve por pantalla la ejecución de un comando erróneo, y cuál es la visualización tipo de la ejecución de un comando exitoso.

Page 76: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Finalmente mostramos la ejecución exitosa de los comandos getvar y setvar.

Page 77: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

14. Mantenimiento y diagnóstico de fallas

Para poder realizar de forma amena el mantenimiento y diagnóstico de fallas, realizaremos un cuadro de síntoma, falla y solución muy típico en productos de todo tipo.

Síntoma de la falla Causa posible Solución

Routix no arranca Disco flexible no insertado Coloque el disco en la ranura de la disquetera y reinicie el equipo

 La BIOS no tiene como dispositivo de booteo la unidad de disco removible

Reinicie la máquina accediendo al menú de la BIOS de su equipo y agregue la opción de "Booteo desde unidad Removible"

  Routix no está instalado en el disquete

Siga las instrucciones de la sección "Instalación" de este mismo manual

  Disco defectuosoCambielo por uno nuevo y siga las instrucciones de la sección "Instalación" de este mismo manual

Se interrumpe la cuenta de memoria

Uno de los bancos de memoria tiene problemas Reemplace el banco defectuoso.

Al intentar ejecutar un proceso, el sistema arroja el error "No such file or directory"

No existe el binario en el disquete

Compile e Instale el programa a ejecutar tal como se especifica en la sección de "Instalación"

Al ejecutar el comando "clear" no se borra la pantalla

Probablemente su placa de video tenga algún problema, ya que el driver utilizado por routix es genérico y corre en cualquier modelo de cualquier placa.

Verifique el correcto funcionamiento de su placa de video.

Luego de ejecutar un proceso deseo finalizarlo abruptamente El proceso no a concluído aún.

Ejecute el comando "kill" con el número de proceso a finalizar. Esto envía la señal SIGKILL que finaliza un proceso y dealoca los recursos del sistema por el tomados.

La primera vez que cargo un programa tarda más tiempo que las posteriores.

Esta actuando el cache de bloques del sistema.

La primera vez que se lee de disco se accede al dispositivo magnético leyendo de a bloques de 512bytes, devolviendo esta información al proceso y a su vez almacenándola en un cache interno, de modo que la próxima petición sobre los mismos sectores será servida desde el cache y no de disco, aumentando sustancialmente la performance del sistema.

Page 78: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Luego de la carga de un archivo la luz de la disquetera permanece encendida durante algún tiempo.

Funcionamiento normal del sistema.

Cada vez que se realiza una lectura desde disco, debe a nivel mecánico encenderse el motor que permite mover al mismo para realizar la lectura, luego de encencer el motor debe esperarse unos 500 mseg aproximadamente hasta que alcance la velocidad de régimen permamente. Es por esto que una vez concluida la lectura de un sector el sistema operativo crea un timer para que se apague el motor luego de 2 segundos de inactividad, de modo que si antes de dicho período se continúa leyendo información no habrá que esperar alcanzar el régimen permamente del motor.

El shell tarda en procesar las teclas Un proceso esta monopolizando el uso de cpu

Verifique mediante el comando "ps" que ningún proceso este tomando excesivo tiempo de cpu, si detecta esta condición y no es lo que esta esperando realice un kill del mismo.

15. Cálculo de costos y estudio del mercado para su comercialización.

Como todo desarrollo de software el principal componente es el valor agregado que le da cada programador, incluyendo además el conocimiento de arquitecturas necesarias para lograr un diseño flexible y sólido, altamente escalable y disponible.

Análisis de Costos

Antes de comenzar con el análisis puntual para nuestro proyecto sería bueno clarificar como se define el precio de un producto, para ello deberemos realizar algunas definiciones.

El costo de producción de una empresa puede subdividirse en los siguientes elementos: alquileres, salarios y jornales, la depreciación de los bienes de capital (maquinaría y equipo, etc.), el costo de la materia prima, los intereses sobre el capital de operaciones, seguros, contribuciones y otros gastos misceláneos. Los diferentes tipos de costos pueden agruparse en dos categorías: costos fijos y costos variables.

Page 79: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

 

Costos fijos

Los costos fijos son aquellos en que necesariamente tiene que incurrir la empresa al iniciar sus operaciones. Se definen como costos porque en el plazo corto e intermedio se mantienen constantes a los diferentes niveles de producción. Como ejemplo de estos costos fijos se identifican los salarios de ejecutivos, los alquileres, los intereses, las primas de seguro, la depreciación de la maquinaria y el equipo y las contribuciones sobre la propiedad.

El costo fijo total se mantendrá constante a los diferentes niveles de producción mientras la empresa se desenvuelva dentro de los límites de su capacidad productiva inicial. La empresa comienza las operaciones con una capacidad productiva que estará determinada por la planta, el equipo, la maquinaria inicial y el factor gerencial. Estos son los elementos esenciales de los costos fijos al comienzo de las operaciones.

Hay que dejar claro, que los costos fijos pueden llegar a aumentar, obviamente si la empresa decide aumentar su capacidad productiva, cosa que normalmente se logra a largo plazo, por esta razón, el concepto costo fijo debe entenderse en términos de aquellos costos que se mantienen constantes dentro de un período de tiempo relativamente corto.

Costos Variables

Los costos variables son aquellos que varían al variar el volumen de producción. El costo variable total se mueve en la misma dirección del nivel de producción. El costo de la materia prima y el costo de la mano de obra son los elementos más importantes del costo variable.

La decisión de aumentar el nivel de producción significa el uso de más materia prima y más obreros, por lo que el costo variable total tiende a aumentar la producción. Los costos variables son pues, aquellos que varían al variar la producción.

   GASTOSADMINISTRATIVOS  

 GASTOS DEFÁBRICA    

M.O. DIRECTA      MATERIAPRIMADIRECTA

COSTODIRECTO

COSTO DEFABRICACIÓN

COSTO DEPRODUCCIÓN

Page 80: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Nuestro proyecto, al igual que la gran mayoría de los proyectos de software se basan en tener gran parte de su costo apoyado en los costos fijos. Es decir, posee una gran cantidad de horas hombre de investigación y desarrollo de un núcleo central. Una vez desarrollado el mismo, podría reutilizarse infinidad de veces sin necesidad de ser modificado.

Existen casos excepcionales donde el cliente podría necesitar una modificación, también denominada “customización”, en la que se pide hacer leves variaciones para personalizar ciertos aspectos de software.

Por excepción de estas “customizaciones”, las cuales momentáneamente dejaremos de lado a fin de simplificar los cálculos, sólo nos quedan los costos variables referidos al embalaje, impresión de manuales y distribución.

Para lograr darle un precio de mercado a nuestro proyecto debemos hacer consideraciones sobre cuantas unidades se venderán.

Costos Fijos:

1. Bibliografía: si bien la mayoría de los textos ya los teníamos antes de realizar el proyecto, consideremos el costo necesario para adquirirlos a fin involucrar estos valores en el precio final del producto.

1. The design of the Unix Operating System: Maurice Bach U$S 552. Operating Systems: Andrew Tanenbaum U$S 703. The Design and Implementation of the 4.4 BSD Operating System: Marshall Kirk McKusik U$S604. Undestanding the Linux Kernel: Daniel Bovet, Marco CesatiU$S425. Los microprocesadores Intel: B. Brey U$S 556. Microprocesadores Avanzados 386 y 486. Pentium: Angulo U$S

30

Total: 312 U$S

2. Computadoras: Ocurre exactamente lo mismo que con la bibliografía, si bien poseíamos todo el equipamiento necesario para realizar el desarrollo, consideraremos el costo de adquirir el equipamiento nuevamente. Consideramos aproximadamente unos U$S 2000 de cuatro equipos hogareños utilizables para nuestro desarrollo.

3. Mano de obra/horas hombre dedicadas: Si bien el desarrollo se ha realizado en dos años, en los cuales es difícil contabilizar cuanto tiempo se le ha dedicado con gran precisión, consideraremos aprox. Unas 1000 Hs de trabajo. Si valuamos cada hora de investigación, diseño y desarrollo en $20, estaremos alcanzando la cifra de $20.000

El Total de los costos fijos asciende aproximadamente a los $27.000, o su equivalente en dolares a cambio acual (1 U$S= $2.92), la cifra asciende a U$S 9300.

Page 81: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

Como los productos de este tipo se venden por licencia, y por cada dispositivo embebido donde se colocará el sistema requiere una licencia, consideramos una venta la cuál podría ascender a las 100 licencias, por lo que el precio “final” podría aproximarse a los U$S93, sumados algunos gastos de embalaje, rondamos los U$S 100.

Es bastante evidente como disminuye el precio final a medida que aumentan las ventas, sobre todo en un producto de este tipo donde la mayor parte del costo se encuentra absorbido en los costos fijos.

Mercado

El mercado de los sistemas operativos crece día a día. En los años sesenta todos los sistemas eran operados por lotes o por tareas, es decir, debía terminar de ejecutarse una para comenzar a ejecutarse otra. Esto generaba retardos muy grandes debido a que la gran mayoría de las operaciones de ingreso/salida de datos desde/hacia el computador eran de tipo mecánicas. Es decir, mientras se realizaba una impresión vía matriz de puntos, el procesador quedaba en estado “idle”, es decir, esperando a que se termine de realizar la impresión, para ejecutar otra tarea. Este tiempo, era tiempo de procesamiento perdido, el cuál representaba una gran pérdida de dinero, sobre todo por lo costoso de los computadores de aquella época.

Con la aparición de Unix, los sistemas operativos multitarea fueron abriéndose paso, permitiendo ejecutar varios procesos “simultáneamente”, reduciendo en más de un 90% los tiempos muertos de los prehistóricos procesos por lotes.

Hoy en día, estos sistemas multitarea, son aplicados en una amplia variedad de campos, desde los electrodomesticos, hasta las plantas nucleares, pasando por telefonos celulares, satélites, computadoras hogareñas o automóviles.

Día a día son más los dispositivos que dejan de tener una lógica en hardware y pasan a tener un sistema operativo, el cuál es más simple de reemplazar, actualizar e incluso mucho más económico.

Nuestro sistema Routix es la base para un sistema operativo abocado al networking, pero con suficientes capacidades para poder ser escalable y extensible, pudiendo ser utilizada para aplicaciones embebidas. Nuestro sistema es fácilmente adaptable a las necesidades de muchos dispositivos de robótica, los cuales por cuestiones de tamaño no podrían utilizar un sistema operativo tan gran y voluminoso como Windows.

El mercado en el que entramos es en de los sistemas embebidos, donde los principales competidores son QNX y Windows CE. Estos sistemas tienen más

Page 82: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

horas hombre de desarrollo e investigación por lo que nuestro sistema no competirá con ellos en capacidades de tiempo real, sólo en el control planificado de tareas y dispositivos.

Comparación

Costo por procesador (dispositivo en caso de embebidos)QNX: U$S 700Windows CE: U$S 500Routix: U$S100

Es evidente la gran diferencia de costo que existe entre una licencia de QNX y una de nuestro sistema Routix. Desde ya que por el momento nuestra intención no es competir en el mismo mercado que un sistema como QNX que lleva ya 24 años de desarrollo ininterrumpido.

Nuestra gran ventaja se encuentra en que si una Pyme planea vender 100 dispositivos que requieran control embebido, deberán adquirir 100 licencias. La diferencia es de 600 U$S por licencia, lo cuál en una producción mayorista de 100 dispositivos, la diferencia asciende a U$S 60.000.

Page 83: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

16. Análisis de la planificación proyectada en la propuesta y la resultante real.

Nuestra proyección original fue la siguiente:

ACTIVIDAD DESCRIPCION ANTECESOR DURACIÓN1 Inicio - 02 Modulo Cache de Disco 1 03 Busqueda bibliografica 2 34 Analisis de funcionalidades 2 25 Estudio general y Diseño 3;4 66 Pseudocodificacion y Codificación 5 157 Pruebas de funcionamiento 6 48 Pruebas de performance 6 49 Documentacion del modulo 7;8 3

10 Modulo Driver Floppy 9 011 Busqueda bibliografica 10 312 Analisis de funcionalidades 10 213 Estudio general y Diseño 11;12 814 Pseudocodificacion y Codificación 13 1715 Pruebas de funcionamiento 14 416 Pruebas de performance 14 517 Documentacion del modulo 15;16 318 Modulo Llamada al sistema execve 1 019 Busqueda bibliografica 18 320 Analisis de funcionalidades 18 321 Estudio general y Diseño 19;20 322 Pseudocodificacion y Codificación 21 1523 Pruebas de funcionamiento 22 424 Pruebas de performance 22 425 Documentacion del modulo 23;24 326 Modulo Señales 25 027 Busqueda bibliografica 26 328 Analisis de funcionalidades 26 229 Estudio general y Diseño 27;28 730 Pseudocodificacion y Codificación 29 1831 Pruebas de funcionamiento 30 432 Pruebas de performance 30 433 Documentacion del modulo 31;32 334 Documentacion General del Proyecto 33;17 735 Fin 34 0

Particularmente tuvimos algunos desvíos en el transcurso del proyecto, el primero de ellos se dió en el módulo de Cache de Disco donde encontramos que las estructuras de datos involucradas en el mismo presentaban una complejidad importante y no permitían un interpretación rápida y amena del código, lo que nos llevó a analizar y desarrollar nuevas formas de manejo de

Page 84: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

estas estructuras mediante macros apropiadas bajo la concepción de encapsulación y generalización, esto provoco un desvío de una semana adicional.

El segundo desvío que experimentamos se dió durante las pruebas de funcionamiento del módulo de floppy, donde aparecieron algunos bugs cuya procedencia nos era totalmente desconocida e identificable, con lo cual la detección y corrección de los mismos nos incremento la duración de 4 días a un total de 12 días.

Durante la etapa de Pruebas de Performance del módulo de Señales, encontramos que ante ciertas circunstancias particulares el desempeño en el envío de señales daba un poco más bajo de lo que habíamos pensado, lo cual llevó a realizar un análisis exhaustivo de todo el código del módulo a fin de encontrar posibles puntos de optimización, este trajo aparejado un desvío de 9 días adicionales.

Y finalmente, el mayor desvío lo sufrimos en la etapa de documentación general del proyecto, donde por problemas laborales nos vimos imposibilitados de concluir algunos puntos que nos faltaban del mismo.

Page 85: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

17. Bibliografía y normativa utilizada.

Bibliografía

The design of the Unix Operating System: Maurice Bach Operating Systems: Andrew Tanenbaum The Design and Implementation of the 4.4 BSD Operating System:

Marshall Kirk McKusik Undestanding the Linux Kernel: Daniel Bovet, Marco Cesati Los microprocesadores Intel: B. Brey Microprocesadores Avanzados 386 y 486. Pentium: Angulo Intel Architecture Software Developer’s Manual, vol. 3: Intel Press GCC Manual: Richard Stallman Using ld - GNU linker: Steve Chamberlain Nasm Manual: Alexei A. Frounze How to write a COFF exec: DJ Delorie

Normativas

Single Unix Specification vol 2: http://www.opengroup.org POSIX (The Portable Operating System Interface): http://www.ieee.org FAT: http://www.microsoft.com/mscorp/ip/tech/fat.asp

Hemos además recurrido a los siguientes tutoriales/manuales online para adquirir los conocimientos necesarios para el desarrollo del proyecto:

Memory Managment 1: Tim Robinson http://www.osdever.net/tutorials/pdf/memory1.pdf

Memory Managment 2: Tim Robinson http://www.osdever.net/tutorials/pdf/memory2.pdf

Gcc Inline Assembly: http://www.osdever.net/tutorials/gccasmtut.php?the_id=68

Writing a Kernel in C: Tim Robinson Page Tables: Mike Rieker Protected Mode: Chris Giese

Page 86: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

18. Hojas de datos de los componentes más relevantes.

Se adjunta a continuación las hojas de datos de los controladores y componentes utilizados.

Page 87: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

19. ApéndiceA. Código Fuente

Adjuntamos a continuación el código fuente del Sistema Operativo, hemos preprocesado los fuentes de forma que resulte más clara y amena su lectura.

8254.c00001 00005 #include "routix/system.h"00006 #include "routix/8254.h"00007 #include <routix/kstdio.h>00008 #include "routix/debug.h"00009 00010 00011 00015 void init_8254()00016 {00017 00018 #if __8254_DEBUG00019 puts("init_8254:\n");00020 kprintf("\tCWR: 0x%x (COUNTER_0 | LSB_MSB | MODO2)\n",(COUNTER_0 | LSB_MSB | MODO2));00021 kprintf("\tFrecuencia oscilador interno: %d Hz\n",FOSC);00022 kprintf("\tFrecuencia de interrupcion : %d Hz\n",FINTERRUPCION);00023 kprintf("\tCuenta: 0x%x\n",CUENTA);00024 #endif00025 // Configuramos el contador 0 en modo 200026 outportb(CWR, COUNTER_0 | LSB_MSB | MODO2);00027 00028 // Configuramos la cuenta para una interrupción cada 10ms00029 outportb(COUNTER0, (unsigned char) CUENTA);00030 outportb(COUNTER0, CUENTA>>8);00031 00032 }00033

Page 88: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

8254.h00001 00005 void init_8254();00006 00007 #define FOSC 1193182 // Frec del oscilador interno00008 #define FINTERRUPCION 100 // Frec de interrupción (10 ms)00009 #define CUENTA FOSC / FINTERRUPCION00010 00011 #define BASE_8254 0x4000012 #define COUNTER0 BASE_825400013 #define COUNTER1 BASE_8254+100014 #define COUNTER2 BASE_8254+200015 #define CWR BASE_8254+300016 00017 // Control Word Register00018 #define COUNTER_0 0<<600019 #define COUNTER_1 1<<600020 #define COUNTER_2 2<<600021 #define READ_BACK 3<<600022 #define COUNT_LATH_CMDS 0<<400023 #define LSB 1<<400024 #define MSB 2<<400025 #define LSB_MSB 3<<400026 #define MODO0 0<<100027 #define MODO1 1<<100028 #define MODO2 2<<100029 #define MODO3 3<<100030 #define MODO4 4<<100031 #define MODO5 5<<100032 #define BCD 100033 00034 00035

Page 89: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

8259.h00001 /* 8259.h */00002 00003 #ifndef __SYSTEM00004 #include "routix/system.h"00005 #endif00006 00007 void enable_irq (byte irqn);00008 void disable_irq (byte irqn);00009 00010 void inicializarPics(unsigned char int1, unsigned char int2);00011 void mascarasPics(unsigned char mask1, unsigned char mask2);00012 void endOfInterrupt(void);00013

Page 90: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

alloc.c00001 00006 #ifndef __SYSTEM00007 #include "routix/system.h"00008 #endif00009 #include <routix/kstdio.h>00010 #include "routix/paging.h"00011 #include "routix/kalloc.h"00012 #include "routix/debug.h"00013 00015 volatile int num_mallocs = 0;00017 volatile int num_frees = 0;00018 00019 unsigned int umalloc_alloc = 0, umalloc_free = 0;00020 unsigned int file_alloc = 0, file_free = 0;00021 00022 void free (void *);00023 00025 addr_t *_inicio,*_fin,*_sp;00026 00027 /* Funciones relacionadas con malloc */00028 00029 typedef long Align;00030 00031 typedef union header {00032 struct {00033 union header *ptr;00034 unsigned size;00035 } s;00036 Align x;00037 } Header;00038 00039 //typedef union header Header;00040 00041 static Header base;00042 static Header *freep=NULL;00043 00044 Header *morecore(void);00045 00046 void *malloc (unsigned nbytes)00047 {00048 cli();00049 Header *p, *prevp;00050 unsigned nunits;00051 nunits = (nbytes + sizeof(Header)-1) / sizeof(Header) +1;00052 if ((prevp = freep)==NULL) {00053 base.s.ptr = freep = prevp = &base;00054 base.s.size = 0;00055 }00056 00057 for ( p=prevp->s.ptr ; ; prevp=p , p=p->s.ptr) {00058 if (p->s.size >= nunits) {00059 if (p->s.size == nunits)00060 prevp->s.ptr = p->s.ptr;00061 else {00062 p->s.size -= nunits;00063 p += p->s.size;00064 p->s.size = nunits;00065 }00066 freep = prevp;00067 /*TEMP*/ num_mallocs++;

Page 91: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00068 sti();00069 return (p+1);00070 }00071 else if (p==freep) {00072 if ( (p = morecore()) == NULL ) {00073 sti();00074 return NULL;00075 }00076 }00077 }00078 sti();00079 return NULL;00080 }00081 00082 00083 00084 volatile word morecores=0;00085 00086 Header *morecore(void)00087 {00088 Header *up;00089 00090 up = (Header *) kmalloc_page();00091 if (up == NULL) {00092 return NULL;00093 }00094 00095 morecores++;00096 00097 up->s.size= PAGINA_SIZE / sizeof(Header);00098 free ( (void *) (up+1));00099 return freep;00100 }00101 00102 00103 00104 void free (void *ap)00105 {00106 cli();00107 Header *bp, *p;00108 00109 bp = (Header *) ap - 1;00110 for (p=freep; ! (bp > p && bp < p->s.ptr) ; p=p->s.ptr)00111 if ( (p >= p->s.ptr) && (bp > p || bp < p->s.ptr))00112 break;00113 if ( (bp + bp->s.size) == p->s.ptr) {00114 bp->s.size += p->s.ptr->s.size;00115 bp->s.ptr = p->s.ptr->s.ptr;00116 }00117 else bp->s.ptr = p->s.ptr;00118 00119 if ( (p+p->s.size) == bp) {00120 p->s.size += bp->s.size;00121 p->s.ptr = bp->s.ptr;00122 }00123 else p->s.ptr = bp;00124 00125 freep = p; 00126 00127 num_frees++;00128 sti();

Page 92: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00129 }00130 00131 00132 00133

Page 94: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

atomic.c00001 /* spinlock.c */00002 00003 #include "routix/system.h"00004 #include "routix/atomic.h"00005 #include "routix/debug.h"00006 00007 // Funciones que aseguran la atomicidad de operaciones basicas00008 00009 inline int atomic_inc (int *p)00010 {00011 cli();00012 (*p)++;00013 sti();00014 return *p;00015 }00016 00017 inline int atomic_dec (int *p)00018 {00019 cli();00020 (*p)--;00021 sti();00022 return *p;00023 }00024 00025 inline int atomic_asign (int *p, int x)00026 {00027 cli();00028 *p = x;00029 sti();00030 return *p;00031 }00032 00033 inline int atomic_add (int *p, int x)00034 {00035 cli();00036 *p += x;00037 sti();00038 return *p;00039 }00040 00041 inline int atomic_sub (int *p, int x)00042 {00043 cli();00044 *p -= x;00045 sti();00046 return *p;00047 }00048 00049 // Retorna el valor que posee la variable candado, y luego la setea a 100050 inline int TestAndSet(spinlock_t *candado)00051 {00052 int retorno;00053 00054 __asm__ __volatile__ ("pushf\n\t"00055 "cli\n\t"00056 "movl %2, %0\n\t"00057 "movl $1, %1\n\t"

Page 95: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00058 "popf"00059 : "=m" (retorno), "=m" (*candado)00060 : "r" (*candado));00061 00062 /* cli();00063 00064 __asm__ __volatile__ ("movl %0, %%ebx ; movl $1, %%eax ; xchg %%eax, (%%ebx)" : : "m" (candado) : "ebx");00065 sti();00066 */ 00067 return retorno; 00068 }00069 00070 /* Momentaneamente solo usadas por funciones de kernel */00071 00072 // Candado, utilizado para verificar si algun proceso está evaluando el contenido de "valor"00073 spinlock_t kernel_lock = 0;00074 00075 00076 //Funcion de bloqueo del semaforo (equivalente a down o wait)00077 void spin_lock (spinlock_t *valor)00078 {00079 while(1) {00080 // Esperar mientras algún proceso este dentro de spin_lock/spin_unlock00081 while (TestAndSet(&kernel_lock));00082 00083 if (*valor > 0) {00084 (*valor)--;00085 break;00086 }00087 kernel_lock = 0; 00088 }00089 kernel_lock = 0;00090 }00091 00092 00093 //Funcion de desbloqueo del semaforo (equivalente a up o signal)00094 void spin_unlock (spinlock_t *valor)00095 {00096 // Esperar mientras algún proceso este dentro de spin_lock/spin_unlock00097 while (TestAndSet(&kernel_lock));00098 (*valor)++;00099 kernel_lock = 0; 00100 }

Page 96: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

atomic.h00001 /* atomic.h */00002 00003 #include <routix/system.h>00004 00005 typedef volatile int spinlock_t;00006 00007 int TestAndSet(spinlock_t *);00008 00009 void spin_lock (spinlock_t *);00010 void spin_unlock (spinlock_t *);00011 00012 // Operaciones basicas atomizadas00013 inline int atomic_inc (int *p); // Incremento 00014 inline int atomic_dec (int *p); // Decremento 00015 inline int atomic_asign (int *p, int x); // Asignacion00016 inline int atomic_add (int *p, int x); // Suma00017 inline int atomic_sub (int *p, int x); // Resta00018 00019 00020 // Macros00021 #define START_ATOMIC_OPERATION cli()00022 #define FINISH_ATOMIC_OPERATION sti()00023

Page 97: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

blockcache.c00001 /* blockcache.c */00002 00003 00004 /* 00005 * El cache de bloques se encarga de interactuar entre los pedidos de los diferentes00006 * filesystems y los drivers determinados, siendo su principal función la de mantener00007 * un cache con los bloques más accedidos.00008 * Presenta una lista de bloques libres y un hash accedido por device y sector lógico00009 * que conduce a listas de bloques (sus headers más precisamente).00010 * Existe otra lista de bloques libres (sin uso y utilizados pero de menor a mayor00011 * tiempo de acceso LRU) donde puede haber bloques de listas pertenecientes al hash.00012 *00013 */00014 00015 #include <routix/device.h>00016 #include <routix/kalloc.h>00017 #include <routix/kstdio.h>00018 #include <routix/task.h>00019 #include <routix/system.h>00020 #include <fs/blockcache.h>00021 #include <sys/list.h>00022 #include <routix/atomic.h>00023 00024 #define RUNSTATS 100025 00026 00027 #define PAGE_SIZE 409600028 00029 #define MAXHASHENTRIES 1000030 #define HASH(maxhash,dev,sector) ( (dev+sector)%maxhash )00031 #define HASH_DEVICE(dev) (dev)00032 00033 #define MAKE_MULTIPLE(original,multiple) ((original)+((multiple)-(original)%(multiple)))00034 00035 // Creamos los headers para manejar las listas de bloques libres y de hash.00036 static LIST_NEW(block_cache_t) free_list;00037 static LIST_NEW(block_cache_t) cached_list[MAXHASHENTRIES];00038 static LIST_NEW(block_cache_t) drv_req_list[MAXDEVICEENTRIES];00039 00040 00041 // Esta función se encarga de prealocar los bloques y sus respectivos headers00042 // de acuerdo a la cantidad de memoria total del sistema, utiliza la definición00043 // de MAX_BLOCKCACHEMEM_PCT en system.h (dado en un valor porcentual).00044 // NOTA: por ahora esta definición la dejo acá.00045 //00046 // Máximo uso de memoria por parte del cache de bloques: 5%00047 #define MAX_BLOCKCACHE_MEM 500048

Page 98: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00049 00050 // Funciones locales00051 static inline byte *alloc_block();00052 static inline block_cache_t *alloc_header();00053 static inline block_cache_t *getfreeblock(void);00054 00055 // Funciones locales de debug00056 static void show_cached_list(void);00057 00058 00059 void start_block_cache(int totalmemory)00060 {00061 int blocks;00062 int tmp;00063 //int pagesforblocks,pagesforheaders;00064 00065 00066 // Inicializamos los headers de las listas free_list, cached_list y drv_req (drivers request)00067 LIST_INIT(free_list);00068 00069 for (tmp=0; tmp<MAXHASHENTRIES; tmp++) {00070 LIST_INIT(cached_list[tmp]);00071 }00072 00073 for (tmp=0; tmp<MAXDEVICEENTRIES; tmp++) {00074 LIST_INIT(drv_req_list[tmp]);00075 }00076 00077 // Transformamos la cantidad de memoria de Mb a bytes00078 totalmemory *= 1024*1024;00079 00080 // Calcalumos la cantidad de bloques (redondeando hacia abajo),00081 // pero teniendo en cuenta que un bloque posee 512 bytes entrarán00082 // 8 bloques por página, por lo tanto redondemos la cantidad de00083 // blocks de modo que sea múltiplo de 800084 blocks=totalmemory*MAX_BLOCKCACHE_MEM/(100*BLOCK_SIZE);00085 blocks=MAKE_MULTIPLE(blocks,PAGE_SIZE/BLOCK_SIZE);00086 00087 // Un bloque es de 512bytes, por lo tanto en una página entran 8 bloques00088 //pagesforblocks=blocks/8;00089 00090 // Oks, ahora veamos, la cantidad de headers es igual a la cantidad de bloques,00091 // pero su tamaño es de sizeof(buffer_block_t), o sea que necesitaremos:00092 // memoria_headers=blocks*sizeof(buffer_block_t)00093 // y en páginas de 4KB:00094 // memoria_headers_pag=roundup(memoria_headers/4096)00095 // y redondeamos para arriba00096 //pagesforheaders=blocks*sizeof(buffer_block_t)/4096 + ( (blocks*sizeof(buffer_block_t))%4096 ) ? 1 : 0;00097 kprintf("Inicializando Cache de Bloques con %d bloques\n",blocks);00098 byte *datablock;00099 block_cache_t *headerblock;00100

Page 99: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00101 while ( blocks-- ) {00102 00103 // Alocamos un bloque de datos00104 datablock=alloc_block();00105 00106 // su correspondiente header00107 headerblock=alloc_header();00108 00109 // los vinculamos00110 BLOCK_CACHE_BUFFER(headerblock)=datablock;00111 BLOCK_CACHE_STATE(headerblock)=UNLOCKED;00112 BLOCK_CACHE_LOCKCOUNT(headerblock)=0;00113 LIST_CLEAN(BLOCK_CACHE_PENDING_PROCESS_LIST(headerblock));00114 00115 00116 // y lo agregamos a la lista de bloques libres00117 LIST_ADD(free_list,free,headerblock);00118 00119 }00120 00121 }00122 00123 00124 inline static byte *alloc_block()00125 {00126 static byte *actual_page=NULL;00127 static unsigned short int used_blocks=0;00128 00129 if ( (actual_page==NULL) || (used_blocks == (PAGE_SIZE/BLOCK_SIZE)) ) {00130 actual_page=(byte *) kmalloc_page();00131 used_blocks=0;00132 }00133 00134 return( (byte *) (actual_page+BLOCK_SIZE*(used_blocks++)) );00135 00136 }00137 00138 inline static block_cache_t *alloc_header()00139 {00140 static block_cache_t *actual_page=NULL;00141 static unsigned short int used_headers=0;00142 00143 if ( (actual_page==NULL) || (used_headers >= (PAGE_SIZE/sizeof(block_cache_t))) ) {00144 actual_page=(block_cache_t *) kmalloc_page();00145 used_headers=0;00146 }00147 00148 used_headers++;00149 00150 return(actual_page++);00151 }00152 00153 // Oks, le devolvemos el primer request00154 inline block_cache_t *getrequest(device_t device)00155 {00156 00157 // El primer request en la lista

Page 100: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00158 return( LIST_FIRST(drv_req_list[HASH_DEVICE(device)]) );00159 }00160 00161 // El floppy nos devolvió el control, ahora debemos analizar su respuesta00162 inline void endrequest(block_cache_t *block)00163 {00164 // Lo eliminamos de la lista de request00165 LIST_DEL(drv_req_list[HASH_DEVICE( BLOCK_CACHE_DEVICE(block) )],driver_request_list,block);00166 00167 // despertamos al proceso que generó la solicitud (es el primero en la lista)00168 despertar_task( LIST_FIRST(BLOCK_CACHE_PENDING_PROCESS_LIST(block)) );00169 00170 }00171 00176 inline void sendrequest(block_cache_t *block)00177 {00178 // Agregamos el bloque a la lista de solicitudes correspondiente00179 // al dispositivo00180 LIST_ADD_TAIL(drv_req_list[ HASH_DEVICE( BLOCK_CACHE_DEVICE(block) ) ],driver_request_list,block);00181 00182 // Activa el flag que indica tarea para un determinado driver, por ahora no hace nada00183 00184 }00185 00186 00287 int cache_read(device_t device, word sector, unsigned int start, char *dstbuffer, unsigned int len)00288 {00289 00290 block_cache_t *tmp;00291 task_struct_t *proc_iterator;00292 00293 #ifdef RUNSTATS00294 long long counter;00295 00296 if ( getvar("debugcache") == 1 ) 00297 kprintf("cache_read: starting, dev: %d, sector: %d, start: %d buffer: 0x%x len: %d\n",device,sector,start,dstbuffer,len);00298 00299 if ( getvar("debugcache") == 2 )00300 rdtscl(counter);00301 #endif00302 00303 restart:00304 00305 if ( getvar("debugcache") == 1 )00306 kprintf("cache_read: buscando bloque en la lista de cache\n");00307 00308 START_ATOMIC_OPERATION;00309 00310 #ifdef RUNSTATS00311 if ( getvar("debugcache")==1 )

Page 101: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00312 show_cached_list();00313 #endif00314 00315 // Primero buscamos si ya existe el bloque en la lista del cache00316 LIST_FOREACH(tmp,cached_list[ HASH(MAXHASHENTRIES,device,sector) ], cached)00317 if ( BLOCK_CACHE_DEVICE(tmp)==device && BLOCK_CACHE_SECTOR(tmp)==sector )00318 break;00319 00320 // Está cacheado ?00321 if ( tmp ) {00322 00323 #ifdef RUNSTATS00324 if ( getvar("debugcache") == 1 )00325 kprintf("cache_read: cache hit !\n");00326 #endif00327 00328 // Esta tomado por alguien más00329 if ( BLOCK_CACHE_STATE(tmp)==WRITE_LOCKED || BLOCK_CACHE_STATE(tmp)==SYNCRONIZING ) {00330 00331 // Colocamos el proceso actual al final de la lista de procesos con IO pendiente (el primer00332 // nodo es el proceso original que solicitó la IO)00333 LIST_ADD_TAIL(BLOCK_CACHE_PENDING_PROCESS_LIST(tmp),io_pending,actual);00334 00335 00336 // Ponemos a dormir la tarea00337 dormir_task(actual);00338 00339 FINISH_ATOMIC_OPERATION;00340 00341 // Rescheduleamos00342 _reschedule();00343 00344 // Oks, en este punto alguien nos despertó, volvemos a intentar tomar el bloque00345 // (odio los goto ! :P pero en este momento es una salida rápida y permite no00346 // oscurecer el código.00347 goto restart;00348 }00349 00350 // Se encuentra disponible00351 else {00352 00353 // Si esta deslockeado lo lockeamos, inicializamos la cuenta de locks a cero00354 // y lo quitamos de la lista de bloques free00355 if ( BLOCK_CACHE_STATE(tmp)==UNLOCKED ) {00356 BLOCK_CACHE_STATE(tmp)=READ_LOCKED;00357 LIST_DEL(free_list,free,tmp);00358 BLOCK_CACHE_LOCKCOUNT(tmp)=0;

Page 102: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00359 }00360 #ifdef RUNSTATS00361 else {00362 if ( getvar("debugcache")==3 )00363 kprintf("Sector: %d relockeando!\n",sector);00364 //show_cached_list();00365 }00366 #endif00367 00368 }00369 00370 }00371 00372 // No está cacheado00373 else {00374 00375 #ifdef RUNSTATS00376 if ( getvar("debugcache") == 1 )00377 kprintf("cache_read: cache miss(%d) ",sector);00378 #endif00379 00380 00381 // Obtenemos un bloque de la lista free00382 tmp=getfreeblock();00383 00384 #ifdef RUNSTATS00385 if ( getvar("debugcache") == 1 )00386 kprintf("cache_read: bloque obtenido de la free list 0x%x\n",tmp);00387 00388 if ( getvar("debugcache") == 1 )00389 kprintf("cache_read: eliminamos este nuevo bloque de la free list\n");00390 #endif00391 00392 // lo marcamos en Sincronización00393 BLOCK_CACHE_STATE(tmp)=SYNCRONIZING;00394 00395 // Seteamos el dispositivo, sector y operacion00396 BLOCK_CACHE_DEVICE(tmp)=device;00397 BLOCK_CACHE_SECTOR(tmp)=sector;00398 BLOCK_CACHE_OPERATION(tmp)=IOREAD;00399 00400 00401 #ifdef RUNSTATS00402 if ( getvar("debugcache") == 1 ) {00403 kprintf("cache_read: lo LOCKEAMOS\n");00404 kprintf("cache_read: entrada numero %d en la cached list\n",HASH(MAXHASHENTRIES,device,sector));00405 }00406 #endif00407 00408 // y lo insertamos en la lista de bloques cacheados00409 LIST_ADD_TAIL(cached_list[ HASH(MAXHASHENTRIES,device,sector) ],cached,tmp);00410 00411 00412 #ifdef RUNSTATS

Page 103: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00413 if ( getvar("debugcache") == 1 )00414 kprintf("cache_read: y lo insertamos al final de la lista de bloques cacheados\n");00415 #endif00416 00417 // colocamos el proceso actual al principio de la lista de procesos con IO pendiente00418 LIST_ADD(BLOCK_CACHE_PENDING_PROCESS_LIST(tmp),io_pending,actual);00419 00420 #ifdef RUNSTATS00421 if ( getvar("debugcache") == 1 ) {00422 kprintf("cache_read: insertamos el proceso actual en la lista de procesos con io pendiente\n");00423 kprintf("cache_read: enviamos el request\n");00424 }00425 #endif00426 00427 // Realizamos el request, en este punto, sendrequest pondrá a dormir el00428 // proceso actual hasta que se complete la petición.00429 sendrequest(tmp);00430 00431 // Ponemos a dormir la tarea00432 dormir_task(actual);00433 00434 #ifdef RUNSTATS00435 if ( getvar("debugcache") == 1 )00436 kprintf("cache_read: nos dormimos\n");00437 #endif00438 00439 FINISH_ATOMIC_OPERATION;00440 00441 // Rescheduleamos00442 _reschedule();00443 00444 START_ATOMIC_OPERATION;00445 00446 #ifdef RUNSTATS00447 if ( getvar("debugcache") == 1 )00448 kprintf("cache_read: nos despertamos !\n");00449 #endif00450 00451 // lo quitamos de la lista de procesos io pending00452 LIST_DEL(BLOCK_CACHE_PENDING_PROCESS_LIST(tmp),io_pending,actual);00453 00454 // despertar al resto de los procesos en espera de este bloque00455 LIST_FOREACH(proc_iterator,BLOCK_CACHE_PENDING_PROCESS_LIST(tmp),io_pending) {00456 despertar_task(proc_iterator);00457 }00458 00459 // vaciar la lista de procesos en estado IO

Page 104: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00460 LIST_CLEAN(BLOCK_CACHE_PENDING_PROCESS_LIST(tmp));00461 00462 00463 // El dispositivo concluyó su trabajo, por lo tanto recuperamos el control en este punto.00464 //00465 // si falló debemos:00466 // 1. quitarlo de la lista de bloques cacheados00467 // 2. colocarlo al ppio de la lista de bloques libres00468 // 3. retornar error (-1)00469 if ( BLOCK_CACHE_RETURN(tmp) == -1 ) {00470 00471 LIST_DEL(cached_list[ HASH(MAXHASHENTRIES,device,sector) ],cached,tmp);00472 00473 LIST_ADD(free_list,free,tmp);00474 00475 FINISH_ATOMIC_OPERATION;00476 00477 return -1;00478 00479 }00480 00481 }00482 00483 // Incrementamos la cantidad de locks en él00484 BLOCK_CACHE_LOCKCOUNT(tmp)++;00485 00486 // lo marcamos READ_LOCKED00487 BLOCK_CACHE_STATE(tmp)=READ_LOCKED;00488 00489 FINISH_ATOMIC_OPERATION;00490 00491 char *origin = BLOCK_CACHE_BUFFER(tmp) + start;00492 00493 // Copiamos los datos leidos al buffer del proceso00494 while ( len-- )00495 *dstbuffer++ = *origin++;00496 00497 START_ATOMIC_OPERATION;00498 00499 // Decrementamos la cantidad de locks en él00500 BLOCK_CACHE_LOCKCOUNT(tmp)--;00501 00502 if ( BLOCK_CACHE_LOCKCOUNT(tmp)==0 ) {00503 00504 // Deslockeamos el bloque00505 BLOCK_CACHE_STATE(tmp)=UNLOCKED;00506 00507 // Lo colocamos al final de la free list00508 LIST_ADD_TAIL(free_list,free,tmp);00509 00510 // Despertamos todos los procesos que están esperando por el bloque00511 // y vaciamos la lista00512 LIST_FOREACH(proc_iterator,BLOCK_CACHE_PENDING_PROCESS_LIST(tmp),io_pending)

Page 105: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00513 despertar_task(proc_iterator);00514 00515 LIST_CLEAN(BLOCK_CACHE_PENDING_PROCESS_LIST(tmp));00516 00517 }00518 00519 #ifdef RUNSTATS00520 if ( getvar("debugcache") == 2 ) {00521 long long int counterfinal;00522 rdtscl(counterfinal);00523 kprintf("0x%llx ",counterfinal-counter);00524 }00525 #endif00526 00527 FINISH_ATOMIC_OPERATION;00528 00529 return 1;00530 00531 }00532 00533 00562 static inline block_cache_t *getfreeblock(void)00563 {00564 00565 byte found=0;00566 block_cache_t *tmp;00567 00568 do {00569 00570 // Obtenemos el pri 00571 tmp=LIST_FIRST(free_list);00572 00573 // y lo quitamos de ella00574 LIST_DEL(free_list,free,tmp);00575 00576 // Bloque marcado como modificado00577 if ( BLOCK_CACHE_STATE(tmp)==DIRTY ) {00578 // proximo a agregar, manejo de escritura asincrónica00579 }00580 00581 // Bloque disponible00582 else00583 found=1;00584 00585 } while ( ! found );00586 00587 return tmp;00588 00589 }00590 00591 00592 static void show_cached_list(void)00593 {00594 int iter;00595 block_cache_t *tmp;00596 char state;00597 00598 int cached_blocks=0;00599

Page 106: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00600 for(iter=0; iter<MAXHASHENTRIES; iter++) {00601 00602 kprintf("Entry %d: ",iter);00603 00604 LIST_FOREACH(tmp,cached_list[iter],cached) {00605 cached_blocks++;00606 00607 switch ( BLOCK_CACHE_STATE(tmp) ) {00608 00609 case READ_LOCKED:00610 state='R';00611 break;00612 00613 case WRITE_LOCKED:00614 state='W';00615 break;00616 00617 case UNLOCKED:00618 state='U';00619 break;00620 00621 case SYNCRONIZING:00622 state='S';00623 break;00624 00625 default:00626 state='?';00627 break;00628 00629 00630 }00631 00632 if ( BLOCK_CACHE_STATE(tmp)==READ_LOCKED ) {00633 kprintf(" %d(%c%d)", BLOCK_CACHE_SECTOR(tmp),state,BLOCK_CACHE_LOCKCOUNT(tmp));00634 }00635 else {00636 kprintf(" %d(%c)", BLOCK_CACHE_SECTOR(tmp),state);00637 }00638 }00639 00640 kprintf("\n");00641 00642 }00643 00644 kprintf("%d bloques cacheados\n",cached_blocks);00645 00646 }

Page 107: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

blockcache.h00001 /* block.h */00002 00003 #ifndef __BLOCK_CACHE00004 #define __BLOCK_CACHE00005 00006 #include <routix/device.h>00007 #include <routix/task.h>00008 #include <routix/system.h>00009 #include <sys/list.h>00010 00011 // Cache00012 typedef enum block_state { READ_LOCKED, WRITE_LOCKED, SYNCRONIZING, UNLOCKED, DIRTY } block_state;00013 00014 typedef struct block_cache_t {00015 device_t device;00016 word sector;00017 byte *buffer;00018 00019 // Estado del bloque00020 block_state state;00021 unsigned int lock_count; 00022 00023 // Info para el driver00024 operation_t operation;00025 int ret;00026 00027 LIST_NEW(task_struct_t) pending_process_list; // lista de procesos en espera por este bloque00028 LIST_DATA(block_cache_t) free; // puede pertenecer a una lista de bloques libres00029 LIST_DATA(block_cache_t) cached; // puede pertenecer a una lista contenida en un hash00030 LIST_DATA(block_cache_t) driver_request_list; // puede pertenecer a una lista de requests a un driver00031 00032 } block_cache_t;00033 00034 #define BLOCK_CACHE_DEVICE(bf) ((bf)->device)00035 #define BLOCK_CACHE_SECTOR(bf) ((bf)->sector)00036 #define BLOCK_CACHE_BUFFER(bf) ((bf)->buffer)00037 #define BLOCK_CACHE_STATE(bf) ((bf)->state)00038 #define BLOCK_CACHE_LOCKCOUNT(bf) ((bf)->lock_count)00039 #define BLOCK_CACHE_OPERATION(bf) ((bf)->operation)00040 #define BLOCK_CACHE_RETURN(bf) ((bf)->ret)00041 #define BLOCK_CACHE_PENDING_PROCESS_LIST(bf) ((bf)->pending_process_list)00042 00043 #define DRIVER_REQUEST_DEVICE(bf) ((bf)->device)00044 #define DRIVER_REQUEST_SECTOR(bf) ((bf)->sector)00045 #define DRIVER_REQUEST_BUFFER(bf) ((bf)->buffer)00046 #define DRIVER_REQUEST_STATE(bf) ((bf)->state)00047 #define DRIVER_REQUEST_OPERATION(bf) ((bf)->operation)00048 #define DRIVER_REQUEST_RETURN(bf) ((bf)->ret)00049 00050 // Definiciones00051 #define BLOCK_SIZE 51200052

Page 108: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00053 00054 // Funciones00055 void start_block_cache(int totalmemory);00056 00057 block_cache_t *getrequest(device_t device);00058 inline void sendrequest(block_cache_t *block);00059 inline void endrequest(block_cache_t *block);00060 int cache_read(device_t device, word sector, unsigned int start, char *dstbuffer, unsigned int len);00061 00062 00063 #define CACHE_READ(device,sector,buffer) ( cache_read(device,sector,0,buffer,BLOCK_SIZE) )00064 00065 00066 #endif

Page 109: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

debug.h00001 /* debug.h */00002 00003 00004 #define __VMDEBUG 0 // Kernel Virtual Memory Debug00005 #define __KMM_DEBUG 0 // Kernel Memory Manager Debug00006 #define __8254_DEBUG 1 // 8254 Debug00007 00008 00009 00010 #define _debug(valor) \00011 __asm__ __volatile__ ( \00012 "sigue: \n\t" \00013 " movw %0, %%ax\n\t" \00014 " decw %%ax\n\t" \00015 " jnz sigue\n\t" \00016 : : "i" (valor) : "ax" );00017 00018 #define __debug() __asm__ __volatile__ ("push %eax; \00019 movl $1, %eax; \00020 debug1: cmp $1, %eax; \00021 nop; \00022 je debug1; \00023 pop %eax");00024 00025 // Estas macros se utilizan para registrar cuanto tiempo toma la ejecución de un bloque de código00026 #define START_TICKS_COUNT() ticks_t start_ticks_count, end_ticks_count; \00027 rdtscl(start_ticks_count);00028 #define END_TICKS_COUNT() rdtscl(end_ticks_count)00029 #define PRINT_TICKS_COUNT() kprintf("Cantidad de ticks: %d\n", end_ticks_count - start_ticks_count);

Page 111: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

elf.h 00001 /* elf.h */00002 00003 #ifndef __SYSTEM00004 #include "../include/system.h"00005 #endif00006 00007 typedef unsigned int Elf32_Addr; 00008 typedef unsigned short Elf32_Half;00009 typedef unsigned int Elf32_Off;00010 typedef int Elf32_Sword;00011 typedef unsigned int Elf32_Word;00012 00013 #define EI_NIDENT 1600014 00015 typedef struct Elf32_Ehdr {00016 unsigned char e_ident[EI_NIDENT];00017 Elf32_Half e_type;00018 Elf32_Half e_machine;00019 Elf32_Word e_version;00020 Elf32_Addr e_entry;00021 Elf32_Off e_phoff;00022 Elf32_Off e_shoff;00023 Elf32_Word e_flags;00024 Elf32_Half e_ehsize;00025 Elf32_Half e_phentsize;00026 Elf32_Half e_phnum;00027 Elf32_Half e_shentsize;00028 Elf32_Half e_shnum;00029 Elf32_Half s_shstrndx;00030 } Elf32_Ehdr;00031 00032 //e_type00033 #define ET_NONE 000034 #define ET_REL 100035 #define ET_EXEC 200036 #define ET_DYN 300037 #define ET_CORE 400038 #define ET_LOPROC 0xff0000039 #define ET_HIPROC 0xffff00040 00041 //e_version00042 #define EV_NONE 000043 #define EV_CURRENT 100044 00045 #define EM_386 300046 00047 00048 struct coff_header{00049 unsigned short f_magic; /* magic number */00050 unsigned short f_nscns; /* number of sections */00051 unsigned long f_timdat; /* time & date stamp */00052 unsigned long f_symptr; /* file pointer to symtab */00053 unsigned long f_nsyms; /* number of symtab entries */

Page 112: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00054 unsigned short f_opthdr; /* sizeof(optional hdr) */00055 unsigned short f_flags; /* flags */00056 };00057 00058 // Valor de f_magic para un COFF3200059 #define COFF32_TYPE 0x14c00060 00061 struct coff_sections{00062 char s_name[8]; /* section name */00063 unsigned long s_paddr; /* physical address, aliased s_nlib */00064 unsigned long s_vaddr; /* virtual address */00065 unsigned long s_size; /* section size */00066 unsigned long s_scnptr; /* file ptr to raw data for section */00067 unsigned long s_relptr; /* file ptr to relocation */00068 unsigned long s_lnnoptr; /* file ptr to line numbers */00069 unsigned short s_nreloc; /* number of relocation entries */00070 unsigned short s_nlnno; /* number of line number entries */00071 unsigned long s_flags; /* flags */00072 } ;00073 00074 #define COFF32_TEXT 0x2000075 #define COFF32_DATA 0x4000076 #define COFF32_BSS 0x8000077

Page 113: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

error.c 00001 00005 #include "routix/system.h"00006 #include "routix/task.h"00007 #include <routix/kstdio.h>00008 00009 00010 extern task_struct_t *actual;00011 00012 00013 char error_types[][55] = {00014 "OK",00015 "Operation not permitted",00016 "No such file or directory",00017 "No such process",00018 "Interrupted system call",00019 "I/O error", 00020 "No such device or address",00021 "Arg list too long",00022 "Exec format error",00023 "Bad file number",00024 "No child processes",00025 "Try again",00026 "Out of memory",00027 "Permission denied",00028 "Bad address",00029 "Block device required",00030 "Device or resource busy",00031 "File exists",00032 "Cross-device link",00033 "No such device",00034 "Not a directory",00035 "Is a directory",00036 "Invalid argument",00037 "File table overflow",00038 "Too many open files",00039 "Not a typewriter",00040 "Text file busy",00041 "File too large", 00042 "No space left on device",00043 "Illegal seek",00044 "Read-only file system",00045 "Too many links",00046 "Broken pipe",00047 "Math argument out of domain of func",00048 "Math result not representable",00049 "Resource deadlock would occur",00050 "File name too long",00051 "No record locks available",00052 "Function not implemented", 00053 "Directory not empty",00054 "Too many symbolic links encountered",00055 "Operation would block",00056 "No message of desired type",00057 "Identifier removed",00058 "Channel number out of range",00059 "Level 2 not synchronized",00060 "Level 3 halted",00061 "Level 3 reset",00062 "Link number out of range",

Page 114: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00063 "Protocol driver not attached",00064 "No CSI structure available",00065 "Level 2 halted",00066 "Invalid exchange",00067 "Invalid request descriptor",00068 "Exchange full",00069 "No anode",00070 "Invalid request code",00071 "Invalid slot",00072 "File locking deadlock error",00073 "Bad font file format",00074 "Device not a stream",00075 "No data available",00076 "Timer expired",00077 "Out of streams resources",00078 "Machine is not on the network",00079 "Package not installed",00080 "Object is remote",00081 "Link has been severed",00082 "Advertise error",00083 "Srmount error",00084 "Communication error on send",00085 "Protocol error",00086 "Multihop attempted",00087 "RFS specific error",00088 "Not a data message",00089 "Value too large for defined data type",00090 "Name not unique on network",00091 "File descriptor in bad state",00092 "Remote address changed",00093 "Can not access a needed shared library",00094 "Accessing a corrupted shared library",00095 ".lib section in a.out corrupted",00096 "Attempting to link in too many shared libraries",00097 "Cannot exec a shared library directly",00098 "Illegal byte sequence",00099 "Interrupted system call should be restarted",00100 "Streams pipe error",00101 "Too many users",00102 "Socket operation on non-socket",00103 "Destination address required",00104 "Message too long",00105 "Protocol wrong type for socket",00106 "Protocol not available",00107 "Protocol not supported",00108 "Socket type not supported",00109 "Operation not supported on transport endpoint",00110 "Protocol family not supported",00111 "Address family not supported by protocol",00112 "Address already in use",00113 "Cannot assign requested address",00114 "Network is down",00115 "Network is unreachable",00116 "Network dropped connection because of reset",00117 "Software caused connection abort",00118 "Connection reset by peer",00119 "No buffer space available",00120 "Transport endpoint is already connected",00121 "Transport endpoint is not connected",00122 "Cannot send after transport endpoint shutdown",00123 "Too many references: cannot splice",

Page 115: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00124 "Connection timed out",00125 "Connection refused",00126 "Host is down",00127 "No route to host",00128 "Operation already in progress",00129 "Operation now in progress",00130 "Stale NFS file handle",00131 "Structure needs cleaning",00132 "Not a XENIX named type file",00133 "No XENIX semaphores available",00134 "Is a named type file",00135 "Remote I/O error",00136 "Quota exceeded"00137 };00138 00139 00140 00141 void perror (char *str)00142 {00143 kprintf("%s: %s\n", str, error_types[actual->err_no]);00144 actual->err_no = 0; // Limpiar error de proceso00145 } 00146 00147 00148 void kpanic(char *str)00149 {00150 __asm__ __volatile__ ("cli");00151 00152 kprintf("\nKernel Panic: %s\n", str);00153 kprintf("Sistema detenido");00154 while(1);00155 }

Page 116: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

error.h

00001 /* errno.h */00002 00003 /* agrego las que no encontre :-( a partir del numero 10000*/00004 00005 void perror (char *str);00006 00007 #ifndef _I386_ERRNO_H00008 #define _I386_ERRNO_H00009 00010 #define EPERM 1 /* Operation not permitted */00011 #define ENOENT 2 /* No such file or directory */00012 #define ESRCH 3 /* No such process */00013 #define EINTR 4 /* Interrupted system call */00014 #define EIO 5 /* I/O error */ //no se puede leer el sector00015 #define ENXIO 6 /* No such device or address */00016 #define E2BIG 7 /* Arg list too long */00017 #define ENOEXEC 8 /* Exec format error */00018 #define EBADF 9 /* Bad file number */00019 #define ECHILD 10 /* No child processes */00020 #define EAGAIN 11 /* Try again */00021 #define ENOMEM 12 /* Out of memory */00022 #define EACCES 13 /* Permission denied */00023 #define EFAULT 14 /* Bad address */00024 #define ENOTBLK 15 /* Block device required */00025 #define EBUSY 16 /* Device or resource busy */00026 #define EEXIST 17 /* File exists */00027 #define EXDEV 18 /* Cross-device link */00028 #define ENODEV 19 /* No such device */00029 #define ENOTDIR 20 /* Not a directory */00030 #define EISDIR 21 /* Is a directory */00031 #define EINVAL 22 /* Invalid argument */00032 #define ENFILE 23 /* File table overflow */00033 #define EMFILE 24 /* Too many open files */00034 #define ENOTTY 25 /* Not a typewriter */00035 #define ETXTBSY 26 /* Text file busy */00036 #define EFBIG 27 /* File too large */ //tarea muy grande00037 #define ENOSPC 28 /* No space left on device */00038 #define ESPIPE 29 /* Illegal seek */00039 #define EROFS 30 /* Read-only file system */00040 #define EMLINK 31 /* Too many links */00041 #define EPIPE 32 /* Broken pipe */00042 #define EDOM 33 /* Math argument out of domain of func */00043 #define ERANGE 34 /* Math result not representable */00044 #define EDEADLK 35 /* Resource deadlock would occur */00045 #define ENAMETOOLONG 36 /* File name too long */00046 #define ENOLCK 37 /* No record locks available */00047 #define ENOSYS 38 /* Function not implemented */ //llamada al sistema no valida00048 #define ENOTEMPTY 39 /* Directory not empty */00049 #define ELOOP 40 /* Too many symbolic links encountered */00050 #define EWOULDBLOCK EAGAIN /* Operation would block */00051 #define ENOMSG 42 /* No message of desired type */00052 #define EIDRM 43 /* Identifier removed */

Page 117: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00053 #define ECHRNG 44 /* Channel number out of range */00054 #define EL2NSYNC 45 /* Level 2 not synchronized */00055 #define EL3HLT 46 /* Level 3 halted */00056 #define EL3RST 47 /* Level 3 reset */00057 #define ELNRNG 48 /* Link number out of range */00058 #define EUNATCH 49 /* Protocol driver not attached */00059 #define ENOCSI 50 /* No CSI structure available */00060 #define EL2HLT 51 /* Level 2 halted */00061 #define EBADE 52 /* Invalid exchange */00062 #define EBADR 53 /* Invalid request descriptor */00063 #define EXFULL 54 /* Exchange full */00064 #define ENOANO 55 /* No anode */00065 #define EBADRQC 56 /* Invalid request code */00066 #define EBADSLT 57 /* Invalid slot */00067 #define EDEADLOCK 58 /* File locking deadlock error */00068 #define EBFONT 59 /* Bad font file format */00069 #define ENOSTR 60 /* Device not a stream */00070 #define ENODATA 61 /* No data available */00071 #define ETIME 62 /* Timer expired */00072 #define ENOSR 63 /* Out of streams resources */00073 #define ENONET 64 /* Machine is not on the network */00074 #define ENOPKG 65 /* Package not installed */00075 #define EREMOTE 66 /* Object is remote */00076 #define ENOLINK 67 /* Link has been severed */00077 #define EADV 68 /* Advertise error */00078 #define ESRMNT 69 /* Srmount error */00079 #define ECOMM 70 /* Communication error on send */00080 #define EPROTO 71 /* Protocol error */00081 #define EMULTIHOP 72 /* Multihop attempted */00082 #define EDOTDOT 73 /* RFS specific error */00083 #define EBADMSG 74 /* Not a data message */00084 #define EOVERFLOW 75 /* Value too large for defined data type */00085 #define ENOTUNIQ 76 /* Name not unique on network */00086 #define EBADFD 77 /* File descriptor in bad state */00087 #define EREMCHG 78 /* Remote address changed */00088 #define ELIBACC 79 /* Can not access a needed shared library */00089 #define ELIBBAD 80 /* Accessing a corrupted shared library */00090 #define ELIBSCN 81 /* .lib section in a.out corrupted */00091 #define ELIBMAX 82 /* Attempting to link in too many shared libraries */00092 #define ELIBEXEC 83 /* Cannot exec a shared library directly */00093 #define EILSEQ 84 /* Illegal byte sequence */00094 #define ERESTART 85 /* Interrupted system call should be restarted */00095 #define ESTRPIPE 86 /* Streams pipe error */00096 #define EUSERS 87 /* Too many users */00097 #define ENOTSOCK 88 /* Socket operation on non-socket */00098 #define EDESTADDRREQ 89 /* Destination address required */

Page 118: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00099 #define EMSGSIZE 90 /* Message too long */00100 #define EPROTOTYPE 91 /* Protocol wrong type for socket */00101 #define ENOPROTOOPT 92 /* Protocol not available */00102 #define EPROTONOSUPPORT 93 /* Protocol not supported */00103 #define ESOCKTNOSUPPORT 94 /* Socket type not supported */00104 #define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */00105 #define EPFNOSUPPORT 96 /* Protocol family not supported */00106 #define EAFNOSUPPORT 97 /* Address family not supported by protocol */00107 #define EADDRINUSE 98 /* Address already in use */00108 #define EADDRNOTAVAIL 99 /* Cannot assign requested address */00109 #define ENETDOWN 100 /* Network is down */00110 #define ENETUNREACH 101 /* Network is unreachable */00111 #define ENETRESET 102 /* Network dropped connection because of reset */00112 #define ECONNABORTED 103 /* Software caused connection abort */00113 #define ECONNRESET 104 /* Connection reset by peer */00114 #define ENOBUFS 105 /* No buffer space available */00115 #define EISCONN 106 /* Transport endpoint is already connected */00116 #define ENOTCONN 107 /* Transport endpoint is not connected */00117 #define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */00118 #define ETOOMANYREFS 109 /* Too many references: cannot splice */00119 #define ETIMEDOUT 110 /* Connection timed out */00120 #define ECONNREFUSED 111 /* Connection refused */00121 #define EHOSTDOWN 112 /* Host is down */00122 #define EHOSTUNREACH 113 /* No route to host */00123 #define EALREADY 114 /* Operation already in progress */00124 #define EINPROGRESS 115 /* Operation now in progress */00125 #define ESTALE 116 /* Stale NFS file handle */00126 #define EUCLEAN 117 /* Structure needs cleaning */00127 #define ENOTNAM 118 /* Not a XENIX named type file */00128 #define ENAVAIL 119 /* No XENIX semaphores available */00129 #define EISNAM 120 /* Is a named type file */00130 #define EREMOTEIO 121 /* Remote I/O error */00131 #define EDQUOT 122 /* Quota exceeded */00132 00133 #endif

Page 119: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

event.c

00001 /* event.c */00002 00003 00004 #include "routix/event.h"00005 00006 // Puntero al inicio de la lista de eventos00007 event_t *event_inicio=NULL;00008 00009 int insertar_evento(event_t *nuevo)00010 {00011 event_t *tmp;00012 00013 if ( nuevo == NULL ) { return 0; }00014 00015 // Nos paramos al ppio de la lista00016 tmp = event_inicio;00017 00018 if ( event_inicio == NULL ) { event_inicio = nuevo; }00019 00020 else {00021 00022 // Buscamos la última tarea00023 for ( tmp = event_inicio; tmp->proximo != NULL ; tmp = tmp->proximo );00024 00025 // Nos colgamos de ella00026 tmp->proximo = nuevo;00027 }00028 00029 // La nueva tarea queda apuntando a NULL00030 nuevo->proximo = NULL;00031 00032 return 1;00033 }00034 00035 00036 // Función crítica, tengo que agregarle la deshabilitación de 00037 // interrupciones (bajo análisis)00038 int remover_evento(event_t *event)00039 {00040 event_t *tmp;00041 00042 // Es el primer event ?00043 if ( event == event_inicio ) {00044 event_inicio = event->proximo;00045 // Lo tengo que reemplazar por la constante correcta según la definición de errno.h00046 return 0;00047 }00048 00049 // Buscamos nuestro event entonces00050 for ( tmp=event_inicio; (tmp->proximo != event) && (tmp != NULL) ; tmp = tmp->proximo ) ;00051 00052 // Si no encontramos el event devolvemos error00053 if ( tmp == NULL ) {00054 // Lo tengo que reemplazar por la constante correcta según la definición de errno.h00055 return -1;

Page 120: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00056 }00057 else {00058 tmp->proximo = event->proximo;00059 }00060 00061 // Lo tengo que reemplazar por la constante correcta según la definición de errno.h00062 return 0;00063 }00064 00065 00066 void actualizar_eventos(device_t dispositivo)00067 {00068 event_t *tmp;00069 00070 // Chequeamos si hay events activos00071 if ( event_inicio == NULL ) {00072 return;00073 }00074 00075 for ( tmp=event_inicio; tmp != NULL; tmp = tmp->proximo ) {00076 00077 //kprintf("Evento: %x - Tipo: %d\n", tmp, tmp->dispositivo);00078 00079 if ( tmp->dispositivo == dispositivo ) {00080 00081 //kprintf("Despertando a la bella durmiente: 0x%x\n", tmp->proceso);00082 despertar_task(tmp->proceso);00083 }00084 00085 }00086 00087 }

Page 122: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

fat.h

00001 /* floppy.h */00002 00003 #ifndef __SYSTEM00004 #include "routix/system.h"00005 #endif00006 00007 #ifndef __FAT1200008 #define __FAT1200009 00010 //Macros para simplificar el uso de la funcion leer_escribir00011 #define leer_sector(sec,buf) leer_escribir(READ_SECTOR,sec,buf)00012 #define escribir_sector(sec,buf) leer_escribir(WRITE_SECTOR,sec,buf)00013 00014 #define BOOTSECTOR 000015 00016 // Estructura utilizada para caracterizar una particion FAT00017 typedef struct dev_fat_t00018 {00019 word fat_size; //Cantidad de sectores que ocupa cada FAT00020 word fat_start; //Sector de comienzo de la FAT00021 byte cantidad_de_fats; //Cantidad de FATs por disco (geenralmente 2)00022 word root_dir_start; //Sector de comienzo del Directorio raiz00023 word root_dir_size; //Cantidad de sectores asignados al root00024 dword sectores_ocultos; 00025 word sectores_totales; //cantidad total de sectores del disco00026 byte sectores_por_cluster;00027 word sector_size;00028 byte fat_levantada;00029 byte boot_leido; //Indica si el BPB ha sido leido y los parametros han sido cargados en las variables00030 }dev_fat_t;00031 00032 00033 // Estructura que contiene los campos principales de un BootSector tanto en FAT12 como FAT16 (son los primeros 62 bytes)00034 typedef struct boot_sector_t00035 {00036 unsigned BS_jmpBott: 24;00037 qword BS_OEMName;00038 unsigned BPB_BytsPerSec: 16;00039 unsigned BPB_SecPerClus: 8; 00040 unsigned BPB_RsvdSecCnt: 16;00041 unsigned BPB_NumFATs: 8;00042 unsigned BPB_RootEntCnt: 16;00043 unsigned BPB_TotSec16: 16;00044 unsigned BPB_Media: 8;00045 unsigned BPB_FATSz16: 16;00046 unsigned BPB_SecPerTrk: 16;00047 unsigned BPB_NumHeads: 16;00048 unsigned BPB_HiddSec: 32;00049 unsigned BPB_TotSec32: 32;00050 unsigned BS_DrvNum: 8;00051 unsigned BS_Reserved1: 8;

Page 123: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00052 unsigned BS_BootSig: 8;00053 unsigned BS_VolID: 32;00054 char BS_VolLab[11];00055 char BS_FilSysType[8];00056 }boot_sector_t;00057 00058 00059 //Estos son los datos que identifican a cada archivo dentro de un directorio00060 typedef struct fat12_entry_t00061 {00062 byte nombre[8];00063 byte extension[3];00064 byte atributo;00065 byte reservado[10];00066 word hora;00067 word fecha;00068 word sector; //Cluster de comienzo del archivo (relativo al final del ultimo sector de ROOT00069 dword size; //Tamaño en bytes00070 }fat12_entry_t;00071 00072 //Esta estructura es reciente. La idea es que con *fat12_data recoja la info del directorio, y que mediante la funcion00073 //fat_adapta_name la escriba en formato string dentro de nombre.00074 #define MAX_PATH_LEN 2900075 00076 typedef struct fat12_entry_ext_t00077 {00078 fat12_entry_t fat12_data;00079 char nombre[MAX_PATH_LEN];00080 }fat12_entry_ext_t;00081 00082 struct floppy_cache00083 {00084 dword sector;00085 byte bloque[512];00086 struct floppy_cache *next;00087 00088 };00089 00090 //Valores que puede tomar el 1er byte del campo nombre ( estructura dir_entry_t)00091 //Cualquier otro valor, significa el valor del primer caracter del nombre de archivo00092 #define FAT_EMPTY 0 // Campo aun no usado (luego del formateo)00093 #define FAT_SUBDIR 0x2E // El archivo es un directorio00094 #define FAT_DELETED 0xE5 // El archivo fue borrado00095 00096 #define SECTOR_SIZE 51200097 00098 00099 // structura utlizada para generar una lista enlazada que apunta a bloques en memoria que contienen la FAT00100 // del floppy que se encuentra en la diskettera.00101 typedef struct fat_t00102 {00103 byte *bloque;00104 struct fat_t *next;00105 }fat_t;

Page 124: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00106 00107 00108 //Tipo usado para mantener una lista enlazada con los sectores de un archivo contenidos en memoria00109 /*00110 typedef struct file_loaded_t00111 {00112 byte *bloque; //Apunta a un sector00113 struct file_loaded_t *next;00114 00115 } file_loaded_t;00116 */00117 00118 int init_floppy_fs(void);00119 00120 // Adapta un nombre de la forma fat (KERNEL BIN) a formato string: KERNEL.BIN\000121 // asi es mas facil su comparacion, impresion y usos varios00122 void fat_adapta_name (byte *nombre_fat, byte *adaptado);00123 00124 // Recibe un nombre de archivo, y lo busca en el disco. En caso negativo retorna NULL00125 fat12_entry_t *fat_file_find (char *nombre, fat12_entry_t *datos_archivo);00126 00127 // Esta funcion recibe como parametro un numero de sector y mediante la FAT obtiene cual es el siguiente00128 int fat_next_sector ( dword sector_inicial );00129 00130 void *floppy_cache (dword sector);00131 00132 // Abrir un archivo desde un dispositivo con formato FAT1200133 int open_FAT12 (char *nombre, int fd);00134 00135 00136 #define DIR_FAT_VIRTUAL 0xF800000000137 00138 00139 #endif00140

Page 125: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

fat12.c

00001 /* floppy.c */00002 #include "routix/system.h"00003 #include "string.h"00004 #include "drivers/fat.h"00005 #include "routix/paging.h"00006 #include "routix/kalloc.h"00007 #include <routix/kstdio.h>00008 #include <routix/file.h>00009 #include <drivers/floppy.h>00010 #include <fs/blockcache.h>00011 00012 //void printing (file_loaded_t *archivo);00013 00014 00015 // La mayoria de estas funciones estan hechas considerando un disco de 1.44MB (comportamiento impredecible en otro formatos)00016 00017 00018 //Algunas valores retornados00019 #define ERR_NOMEM -1 //No hay memoria suficiente (kmalloc_page==NULL)00020 #define ERR_NO_FAT -200021 #define ERR_NO_BOOT -300022 #define ERR_LAST_SECTOR -500023 #define LAST_SECTOR -100 //Ultimo sector00024 00025 00026 // Buffer donde se guardar cada bloque leido00027 byte buffer[512];00028 00029 00030 dev_fat_t dev_fat[1]; //Defino estructura para dos dispositivos FAT00031 00032 00034 // Lee el sector logico 0 (Boot sector), y levanta todos los parametros fisicos y logicos del disco00035 // para que sean usados por las demas funciones00037 int fat_12(void)00038 {00039 dev_fat[0].boot_leido = FALSE;00040 dev_fat[0].fat_levantada = FALSE;00041 00042 //Leer Boot Sector del floppy00043 //if ( leer_sector(0,buffer) != OK) {00044 if ( CACHE_READ(fd0,BOOTSECTOR,buffer) == -1) {00045 kprintf("No se pudo leer sector\n");00046 return -1;00047 }00048 00049 boot_sector_t *p= (boot_sector_t *) buffer;00050 00051 dev_fat[0].fat_size = p->BPB_FATSz16;00052 dev_fat[0].cantidad_de_fats = p->BPB_NumFATs;00053 dev_fat[0].sectores_ocultos = p->BPB_HiddSec;00054 dev_fat[0].sectores_totales = p->BPB_TotSec16;00055 dev_fat[0].root_dir_size = (p->BPB_RootEntCnt * sizeof(fat12_entry_t)) / SECTOR_SIZE;00056 dev_fat[0].sectores_por_cluster = p->BPB_SecPerClus;

Page 126: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00057 dev_fat[0].sector_size = p->BPB_BytsPerSec;00058 dev_fat[0].fat_start = 1; 00059 dev_fat[0].root_dir_start = 1 + dev_fat[0].sectores_ocultos + (dev_fat[0].cantidad_de_fats * dev_fat[0].fat_size);00060 00061 dev_fat[0].boot_leido=TRUE;00062 return OK;00063 }00064 00066 // Levanta todos los sectores correspondientes a la FAT y los coloca en la memoria00067 // Debera tenerse en cuenta que al cambiar el diskette, el flag "fat_levantada" debera volverse a FALSE00069 00070 fat_t fat_header; //Header de una lista enlazada que va apuntando a bloques en memoria de 512 (fragmentos de la FAT)00071 00072 int levantar_fat(void)00073 {00074 //CUIDADO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!00075 // malloc(100);00076 00077 //Cantidad de paginas que requiere la FAT (en gral para 9 sectores de FAT se requieren 2 paginas)00078 word fat_paginas = (dev_fat[0].fat_size * BLOQUE_SIZE) / PAGINA_SIZE;00079 00080 00081 //Contador para saber cuantos sectores de la fat se levantaron del diskette00082 word sec_fat_levantados=0;00083 word i, j;00084 00085 if ( dev_fat[0].boot_leido == FALSE ) {00086 kprintf("Debe levantarse el BOOT\n");00087 return ERR_NO_BOOT;00088 }00089 00090 if ( dev_fat[0].fat_levantada == TRUE ) {00091 return OK;00092 }00093 00094 00095 //Si la division (fat_size * BLOQUE_SIZE) / PAGINA_SIZE no da entera, redondear para arriba00096 if ( (dev_fat[0].fat_size * BLOQUE_SIZE) % PAGINA_SIZE)00097 fat_paginas++;00098 00099 00100 //Puntero a la lista enlazada de los bloques de FAT, inicializado a NULL en sus dos campos00101 fat_t *aux= &fat_header;00102 aux->bloque = NULL;00103 aux->next = NULL;00104 00105 for(i=0 ; i < fat_paginas ; i++) {00106 00107 //Obtener una pagina00108 if (!(aux->bloque = (byte *) kmalloc_page())) {00109 kprintf("No hay memoria disponible para levantar la FAT\n");

Page 127: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00110 return ERR_NOMEM;00111 }00112 00113 //Mapeo las paginas que contienen bloques en memoria virtual, para poder asi tenerlos en forma contigua00114 //(nadie me asegura que los bloques entregados por kmalloc_page sean contiguos)00115 kmapmem((addr_t) aux->bloque, DIR_FAT_VIRTUAL + (i * PAGINA_SIZE), KERNEL_PDT, PAGE_PRES | PAGE_SUPER | PAGE_RW); 00116 aux->bloque = (byte *) (DIR_FAT_VIRTUAL + (i * PAGINA_SIZE));00117 00118 //Hacer que cada nodo de la lista apunte a 512 bytes dentro de la pagina obtenida.00119 for(j=0;(j<((PAGINA_SIZE/BLOQUE_SIZE))) && (sec_fat_levantados<dev_fat[0].fat_size);j++, sec_fat_levantados++ ) {00120 //if (leer_sector(sec_fat_levantados + dev_fat[0].fat_start, aux->bloque)!=OK) {00121 if (CACHE_READ(fd0,sec_fat_levantados + dev_fat[0].fat_start, aux->bloque) == -1 ) {00122 kprintf("No se pudo levantar la FAT");00123 return -1;00124 }00125 00126 aux->next = (fat_t *) malloc( sizeof(fat_t) );00127 aux->next->bloque = aux->bloque + BLOQUE_SIZE;00128 aux = aux->next;00129 aux->next = NULL;00130 }00131 }00132 00133 //Levantar flag para que las funciones que requieran buscar algo en FAT, sepan que pueden hacerlo00134 dev_fat[0].fat_levantada = TRUE;00135 return OK;00136 }00137 00138 // **************************************************************************************************************00139 // Prepara el entorno (carga la FAT y el BPB) para que puedan ser utilizadas las demas funciones de acceso00140 // a disco00141 // **************************************************************************************************************00142 int init_floppy_fs(void)00143 {00144 dev_fat[0].fat_start = 1;00145 if ( (fat_12()!=OK) || (levantar_fat()!=OK) )00146 return -1;00147 00148 return OK;00149 } 00150 00151 00152 00153 // **************************************************************************************************************

Page 128: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00154 // Recibe un nombre en formato FAT ( KERNEL BIN ) y lo transforma a un formato tipo string: KERNEL.BIN\000155 // **************************************************************************************************************00156 void fat_adapta_name (byte *nombre_fat, byte *adaptado)00157 {00158 byte x=0,z;00159 strcpy(adaptado," ");00160 for( z=0 ; z<11 ; z++) {00161 if ( (z==8) && (nombre_fat[8]!=' ') ) {00162 adaptado[x]='.';00163 x++;00164 }00165 adaptado[x] = nombre_fat[z];00166 if (nombre_fat[z] != ' ')00167 x++;00168 }00169 adaptado[x]='\0';00170 00171 } 00172 00173 00174 00175 00177 //Esta funcion recibe un numero de sector (perteneciente a un archivo) y halla cual es el sector que le sigue.00178 //retorna el sector correspondiente, o LAST_SECTOR en caso de que el sector recibido ("sector") sea el ultimo.00180 int fat_next_sector ( dword sector )00181 {00182 //Si no se levanto la FAT del disco, no se puede hacer nada00183 if (dev_fat[0].fat_levantada==FALSE)00184 return ERR_NO_FAT;00185 00186 if (sector == 0xfff)00187 return ERR_LAST_SECTOR;00188 00189 sector -= 31; //Corrijo el sector, ya que la primera entrada disponible de la FAT apunta al sector 32, y no al 100190 00191 // Tener en cuenta que FAT12 utiliza codificacion inversa. Cualquier duda recurrir a Microsoft Hardware White PAPER00192 // FAT General Overview of On-Disk Format00193 byte lsb, msb;00194 00195 word indice; 00196 00197 indice = (sector * 3) >> 1;00198 lsb = fat_header.bloque[indice];00199 msb = fat_header.bloque[indice + 1];00200 00201 word proximo_sector;00202 00203 if (sector % 2) //Si es impar, tomo los tres nibbles mas altos00204 proximo_sector = (((msb << 8) | lsb) & 0xfff0) >> 4;00205 00206 else //Si es par, tomo los mas bajos00207 proximo_sector = ((msb << 8) | lsb) & 0x0fff;

Page 129: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00208 00209 if ( proximo_sector==0xFFF )00210 return LAST_SECTOR;00211 00212 return (proximo_sector + 31);00213 } 00214 00215 // **************************************************************************************************************00216 // Recibe un PATH que puede contener directorio y devuelve estilo mnt/files/prog.bin y devuelve el largo hasta00217 // la primera '/' o -1 en caso de que no sea una cadena de paths sino un solo nombre (estilo mnt).00218 // Esta funcion se usa multiples veces hasta llegar al archivo final.00219 // **************************************************************************************************************00220 int str_dir_len (char *nombre)00221 {00222 int len=0;00223 while( *nombre++ != '/') {00224 len++;00225 if ( (len > 12) || (*nombre=='\0') )00226 return -1;00227 }00228 00229 return len; 00230 } 00231 00232 00234 // fat12_entry_t *fat_file_find (char *nombre, fat12_entry_t *datos_archivo);00235 //00236 // Esta funcion recibe un nombre de archivo, y devuelve el sector de comienzo.00237 // Esta version soporta directorios, asi que, cualquier funcion o comando que la llame puede pasarle como parametro00238 // un archivo dentro de un directorio. (mnt/files/pepe.txt)00239 //00240 // NOTA: el directorio Root tiene un tamaño fijo, y sus sectores estan contiguos. Los demas 00241 // directorios, tienen por tamaño 0, sus sectores pueden no ser contiguos, y para saber que en que sector continua00242 // el directorio debera llamarse a fat_next_sector. El flag root_dir_flag es utilizado para indicar si el directorio00243 // en el que se busca es el Root o algun otro (ya que el programa debera comportarse de forma diferente).00245 00246 fat12_entry_t *fat_file_find (char *nombre, fat12_entry_t *datos_archivo)00247 {00248 00249 char nombre_aux[MAX_PATH_LEN]; //String auxiliar donde se va parseando el nombre por tramos (entre "/")00250 char nombre_archivos[MAX_PATH_LEN]; //String en el que se guarda cada nombre levantado del disco00251 00252 byte x; 00253

Page 130: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00254 byte root_dir_flag=TRUE; //Directorio en el que se busca es el Root.00255 00256 //Pasar el nombre a buscar a mayusculas (recordar que la FAT solo usa mayusculas)00257 str_to_upper(nombre);00258 00259 //Sector de comienzo y cantidad de sectores del directorio a leer00260 dword dir_sector, dir_size;00261 00262 //El primer directorio a leer sera el Root Dir, asi que cargo sus parametros 00263 dir_sector = dev_fat[0].root_dir_start;00264 dir_size = dev_fat[0].root_dir_size;00265 00266 int dir_len; //nombre actual es un archivo o directorio (ver funcion str_dir_len). Si es archivo dir_len=-100267 //si es directorio, dir_len=cantidad de caracteres del nombre00268 00269 fat12_entry_t *aux_fat; //Estructura para levantar los datos de cada archivo de disco00270 kprintf("1 Mallocs: %d\tFrees: %d\n", num_mallocs, num_frees);00271 00272 do {00273 fat_file_find_break:00274 if ((dir_len=str_dir_len(nombre)) > 0) { //Si es un directorio, buscarlo y apuntar00275 strncpy(nombre_aux, nombre, dir_len); //nombre al proximo directorio/archivo00276 nombre = nombre + dir_len + 1;00277 }00278 else strcpy(nombre_aux, nombre); //Si llego aca, *nombre es un archivo00279 00280 do {00281 kprintf("2 Mallocs: %d\tFrees: %d\n", num_mallocs, num_frees);00282 //if ( leer_sector(dir_sector, buffer) != OK) {00283 if ( CACHE_READ(fd0,dir_sector, buffer) == -1 ) {00284 kprintf("No se puede leer sector\n");00285 return NULL;00286 }00287 kprintf("3 Mallocs: %d\tFrees: %d\n", num_mallocs, num_frees);00288 00289 aux_fat = (fat12_entry_t *) buffer;00290 00291 00292 //Recorro desde 0-16 (que son las cantidad de entradas de archivos que hay por sector)00293 for( x=0 ; x < (SECTOR_SIZE / sizeof(fat12_entry_t)) ; x++) { 00294 fat_adapta_name( aux_fat->nombre , nombre_archivos);00295 00296 if ( strcmp( nombre_archivos, nombre_aux)==0 ) { 00297 if (dir_len < 0) {

Page 131: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00298 memcpy( datos_archivo, aux_fat, sizeof(fat12_entry_t));00299 return aux_fat;00300 }00301 dir_sector = aux_fat->sector + 31;00302 dir_size = 0xffff;00303 root_dir_flag=FALSE; //Ahora voy a buscar en otro directorio00304 goto fat_file_find_break;00305 }00306 aux_fat++;00307 }00308 if (root_dir_flag==TRUE) {00309 dir_sector++;00310 if (dir_sector > (dev_fat[0].root_dir_start + dev_fat[0].root_dir_size) )00311 return NULL;00312 }00313 else {00314 if ((dir_sector = fat_next_sector(dir_sector))==LAST_SECTOR)00315 return NULL;00316 } 00317 00318 } while (dir_sector != LAST_SECTOR);00319 00320 }while ( dir_len > 0 ); 00321 00322 //Si llegue aqui, archivo no encontrado.00323 return NULL;00324 }00325 00326 00327 00328 00329 00330 00331 00332 00333 00334 00335 00336 00337 struct floppy_cache *header_floppy_cache=NULL;00338 00339 dword sectores_cache=0;00340 00341 // Esta funcion mantiene una lista enlazada con sectores leidos del floppy. Cualquier funcion de fs que quiera leer00342 // o escribir un sector, deberia recurrir a esta. (Debe controlarse perfectamente que esta funcion mantenga 00343 // espejados a los sectores, es decir, en algun momento debera sincronizar los sectores con el disco00344 /*00345 struct flop_cache00346 {00347 dword sector;00348 byte *bloque;00349 };*/00350 /*

Page 132: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00351 #define MAX_CACHE_ENTRYS 10000352 struct flop_cache cache_index[MAX_CACHE_ENTRYS];00353 */00354 void floppy_cache_init (void)00355 {00356 00357 return; 00358 00359 /* 00360 word i;00361 for(i=0 ; i< MAX_CACHE_ENTRYS ; i++) {00362 cache_index[i].sector=0;00363 cache_index[i].bloque=NULL;00364 }00365 */00366 }00367 00368 /*00369 void *floppy_cache (dword sector)00370 {00371 word i;00372 byte flag=FALSE;00373 00374 //kprintf("Entrando a floppy_cache\n");00375 00376 for (i=0 ; i<MAX_CACHE_ENTRYS ; i++) {00377 if (cache_index[i].bloque==NULL)00378 break;00379 if (cache_index[i].sector == sector) {00380 //kprintf("***Sector se encontraba en el cache***");00381 return (cache_index[i].bloque);00382 }00383 } 00384 00385 if ( i >= MAX_CACHE_ENTRYS ) { // Debe implementarse algun algoritmo de sustitucion00386 //kprintf("***excedido de MAX_CACHE_ENTRYS en el cache***");00387 return NULL;00388 }00389 00390 // Como los sectores leidos los alloco en paginas, puedo meter en cada uno de ellos PAGINA_SIZE / SECTOR_SIZE (en casos00391 // normales 8 sectores por pagina). Los indices 0,8,16,24,etc deberan pedir una nueva pagina, mientras que los sectores00392 // "internos" (1,2,3,4,5,6,7) no.00393 00394 if ( (i % (PAGINA_SIZE / SECTOR_SIZE))==0 ) {00395 //kprintf("***Sector multiplo de: %d***", PAGINA_SIZE / SECTOR_SIZE);00396 if ( (cache_index[i].bloque = (byte *) kmalloc_page()) == NULL )00397 return NULL;00398 flag=TRUE;00399 }00400 // El sector es un sector "interno", no es necesario pedir memoria00401 else {00402 if ( cache_index[i-1].bloque==NULL ) { //Hay problemas de consistencia ?

Page 133: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00403 kprintf("Floppy cache PANIC");00404 return NULL;00405 } 00406 else { //Si todo esta bien00407 //kprintf("***Sector NO multiplo de: %d***", PAGINA_SIZE / SECTOR_SIZE);00408 cache_index[i].bloque = cache_index[i-1].bloque + SECTOR_SIZE;00409 }00410 }00411 00412 00413 if (leer_sector( sector, cache_index[i].bloque)!=OK) {00414 if (flag==TRUE)00415 kfree_page(cache_index[i].bloque);00416 return NULL;00417 }00418 00419 sectores_cache++; //Fines depurativos00420 cache_index[i].sector = sector;00421 return cache_index[i].bloque;00422 00423 }00424 */00426 // Funcion de cache que utiliza listas enlazadas (malloc y free) la cual tiraba excepciones al cachear el sector quinceavo00427 // no logre averiguar porque pero intuyo que tiene que ver con la implementacion de las primitivas de malloc y free00428 /* 00429 void *floppy_cache (dword sector)00430 {00431 struct floppy_cache *aux = header_floppy_cache;00432 00433 // Verificar si aun no se aloco ningun sector en el cache00434 if ( aux==NULL ) {00435 kprintf("ACA\n");00436 aux = (struct floppy_cache *) malloc ( sizeof(struct floppy_cache));00437 if ( aux == NULL) {00438 kprintf("Malloc no me dio memoria 1\n");00439 while(1);00440 } 00441 if ( leer_sector(sector, aux->bloque)!=OK ) {00442 free (aux);00443 aux->next = NULL;00444 return NULL;00445 }00446 aux->sector = sector;00447 aux->next = NULL;00448 header_floppy_cache = aux;00449 sectores_cache++;00450 return aux->bloque;00451 }00452 00453 // Verificar si en la lista enlazada del cache se encuentra el sector buscado 00454 for ( ; aux->next ; aux=aux->next ) {00455 if ( aux->sector == sector ) {00456 return aux->bloque;00457 }00458 }

Page 134: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00459 00460 // Este bloque es necesario para saber si el sector buscado es el ultimo nodo en la lista00461 if (aux->sector == sector) {00462 return aux->bloque;00463 }00464 // Si estoy aca, es que el sector no se encuentra en el cache00465 aux->next = (struct floppy_cache *) malloc ( sizeof(struct floppy_cache));00466 if ( aux->next == NULL) {00467 kprintf("Malloc no me dio memoria 2\n");00468 while(1);00469 } 00470 00471 if ( leer_sector(sector, aux->next->bloque)!=OK ) {00472 free (aux->next);00473 aux->next = NULL;00474 return NULL;00475 }00476 00477 aux = aux->next;00478 aux->sector = sector;00479 aux->next = NULL;00480 00481 sectores_cache++;00482 return aux->bloque;00483 00484 } 00485 */00486 00487 // **************************************************************************************************************00488 // Estas funciones solo son usadas a modo de prueba, no son parte del manejo de FAT1200489 // **************************************************************************************************************00490 00491 void print_fat_info (void)00492 {00493 putchar('\n');00494 boot_sector_t *p= (boot_sector_t *) buffer;00495 00496 if ( p->BPB_RsvdSecCnt != 1)00497 kprintf("Filesystem no reconocido\n");00498 else kprintf("Disco es FAT12\n");00499 00500 byte i;00501 kprintf("BS_FilSysType:");00502 for(i=0; i<8;i++)00503 putchar(p->BS_FilSysType[i]);00504 putchar('\n');00505 00506 kprintf("Sectores por FAT: %d\n", dev_fat[0].fat_size);00507 kprintf("Cantidad de FATs: %d\n", dev_fat[0].cantidad_de_fats);00508 kprintf("Fat start: %d\n", dev_fat[0].fat_start);00509 kprintf("Sectores ocultos: %d\n", dev_fat[0].sectores_ocultos);

Page 135: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00510 kprintf("Sectores totales: %d\n", dev_fat[0].sectores_totales);00511 kprintf("Sectores por Cluster: %d\n", dev_fat[0].sectores_por_cluster);00512 kprintf("Sectores asignados al directorio root: %d\n", dev_fat[0].root_dir_size);00513 kprintf("Comienzo del root dir: sector %d\n", dev_fat[0].root_dir_start);00514 } 00515 00516 00518 // Esta funcion imprime los nombres de todos los archivos que se hallen en el Root (no tiene utilidad real)00520 void fat_root_dir (void)00521 { 00522 if ((dev_fat[0].boot_leido==FALSE) || (dev_fat[0].fat_levantada==FALSE) )00523 if ( init_floppy_fs() != OK ) {00524 kprintf("No se puede leer disco\n");00525 }00526 00527 byte root_dir_sector;00528 byte x;00529 fat12_entry_t *datos;00530 00531 char nombre[MAX_PATH_LEN];00532 00533 for (root_dir_sector=dev_fat[0].root_dir_start;root_dir_sector<(dev_fat[0].root_dir_start+dev_fat[0].root_dir_size) \00534 ; root_dir_sector++) {00535 //if ( leer_sector(root_dir_sector, buffer) != OK) {00536 if ( CACHE_READ(fd0,root_dir_sector, buffer) == -1 ) {00537 kprintf("No se puede leer sector\n");00538 return;00539 }00540 datos = (fat12_entry_t *) buffer;00541 00542 for( x=0 ; x < (SECTOR_SIZE / sizeof(fat12_entry_t)) ; x++) { 00543 if ((datos->nombre[0]!=FAT_EMPTY) && (datos->nombre[0]!=FAT_SUBDIR) && \00544 (datos->nombre[0]!=FAT_DELETED)) {00545 fat_adapta_name( datos->nombre , nombre);00546 kprintf("Archivo: %s\n", nombre);00547 } 00548 datos++;00549 }00550 } 00551 }00552 00554 // Funcion llamada desde el shell al ejecutar "flop find"00556 void fat_test(void)00557 {00558 00559 if ((dev_fat[0].boot_leido==FALSE) || (dev_fat[0].fat_levantada==FALSE) )00560 if ( init_floppy_fs() != OK ) {00561 kprintf("No se puede leer disco\n");00562 }00563

Page 136: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00564 byte nombre[25];00565 fat12_entry_t datos_archivo;00566 kprintf("Archivo a buscar:");00567 gets(nombre);00568 if ( fat_file_find (nombre, &datos_archivo) ) {00569 kprintf("Tamaño: %d\n", datos_archivo.size);00570 00571 if (datos_archivo.atributo & 0x10)00572 kprintf("El archivo es un Directorio\n");00573 00574 kprintf("Comienza en Cluster: %d\n", \00575 (datos_archivo.sector * dev_fat[0].sectores_por_cluster) + dev_fat[0].root_dir_start + dev_fat[0].root_dir_size -2); 00576 }00577 else {00578 kprintf("Archivo no encontrado: %s\n", nombre);00579 return;00580 }00581 if (dev_fat[0].fat_levantada==FALSE) {00582 levantar_fat();00583 }00584 00585 00586 int sector=(datos_archivo.sector*dev_fat[0].sectores_por_cluster)+dev_fat[0].root_dir_start+dev_fat[0].root_dir_size-2;00587 00588 sector = fat_next_sector(sector);00589 00590 while ( (sector > 0) && (sector < 0xff0) ) {00591 kprintf("%d->", sector);00592 sector = fat_next_sector(sector);00593 }00594 kprintf("FIN\n"); 00595 } 00596

Page 137: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

file.c

00001 /* file.c */00002 #include "routix/system.h"00003 #include "string.h"00004 #include "drivers/fat.h"00005 #include "routix/paging.h"00006 #include "routix/kalloc.h"00007 #include <routix/kstdio.h>00008 #include "routix/file.h"00009 #include "routix/task.h"00010 #include <drivers/floppy.h>00011 #include <fs/blockcache.h>00012 #include <error.h>00013 00014 #define RUNSTATS 100015 00016 file_opened_t *header_archivos_abiertos;00017 00018 extern dev_fat_t dev_fat[0];00019 00021 // Funcion auxiliar usada para buscar en la lista enlazada, el file descriptor fd00022 // en caso de no encontrarse devuelve NULL, en caso contrario devuelve un puntero al nodo correspondiente00024 00025 00026 // Header a una lista enlazada con todos los archivos abiertos por el sistema00027 file_opened_t *header_archivos_abiertos=NULL;00028 00029 // Como abrir_archivo va a retornar un fd, creo una variable dword file_descriptor_actual, la cual va incrementando00030 // el fd por cada archivo abierto. Es decir, el primer fd que entregaria seria el 100031 00032 dword file_descriptor_actual=1; 00033 00034 // La idea es que haya una lista enlazada con todos los archivos abiertos en el sistema (independientemente a que00035 // cada proceso tengo en su estructura de datos info de los archivos que abrio.00036 // Cada nodo de la lista, contiene una estructura fat12_entry_ext_t datos, un puntero a un bloque de memoria (que sera00037 // levantado de disco por la funcion read, y un dword sector_actual que indica a que sector corresponde el bloque00038 // apuntado por byte *bloque.00039 // Si bien es ineficiente, para hacer bien claro el manejo, se levantara de disco de a 1 sector por vez.00040 00041 00042 extern task_struct_t *actual;00043 00044 int open (char *nombre)00045 {00046 word i;00047 int fd = -1;00048 00049 00050 // Verificar que el proceso tenga algun slot libre para abrir un archivo

Page 138: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00051 for (i=0 ; i < MAX_FILES_POR_TAREA ; i++)00052 if ( actual->open_files[i] == NULL ) {00053 fd = i;00054 break;00055 }00056 00057 if ( fd < 0 ) {00058 actual->err_no = EMFILE;00059 return -1; //el proceso posee la maxima cantidad de archivos abiertos, no se puede abrir otro00060 }00061 struct file aux;00062 00063 /* Esta funcion me devuelve en que dispositivo (aux.device) y en que file system (aux.fs) se encuentra el archivo00064 vfs_find(nombre, aux); 00065 como el file system virtual y el sistema de montajes no esta implementado, completo los valores a mano.00066 */ 00067 aux.device = DRIVE_0 ;00068 aux.fs = FAT12;00069 00070 actual->open_files[fd] = (struct file *) malloc (sizeof(struct file));00071 if ( ! actual->open_files[fd] )00072 return -1;00073 00074 file_alloc++;00075 00076 if ( aux.fs == FAT12 ) 00077 if ( open_FAT12(nombre, fd)!=OK ) {00078 kprintf("POR ACA....\n");00079 free(actual->open_files[fd]);00080 actual->open_files[fd] = NULL;00081 return -1;00082 }00083 00084 return fd;00085 } 00086 00087 // Abrir un archivo desde un dispositivo FAT1200088 int open_FAT12 (char *nombre, int fd)00089 {00090 if ((dev_fat[0].boot_leido==FALSE) || (dev_fat[0].fat_levantada==FALSE) ) 00091 if ( init_floppy_fs() != OK ) {00092 kprintf("No se puede leer disco\n");00093 return -1;00094 }00095 00096 fat12_entry_ext_t archivo;00097 00098 00099 if ( fat_file_find(nombre , &archivo.fat12_data) == NULL ) {//Archivo no se encuentra o no se puede abrir00100 kprintf("Cantidad de Mallocs: %d\tFrees: %d\n", num_mallocs, num_frees);00101 kprintf("No se encuentra el archivete\n");00102 return -1;00103 }00104

Page 139: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00105 actual->open_files[fd]->sectores = archivo.fat12_data.size / SECTOR_SIZE;00106 00107 if ( archivo.fat12_data.size % SECTOR_SIZE ) //Si no es un sector justo, aumentarlo en 100108 actual->open_files[fd]->sectores++;00109 00110 actual->open_files[fd]->offset = 0;00111 actual->open_files[fd]->offset_rel = 0;00112 actual->open_files[fd]->sector_origen = archivo.fat12_data.sector + dev_fat[0].root_dir_start + \00113 dev_fat[0].root_dir_size - 2;00114 actual->open_files[fd]->sector_actual = actual->open_files[fd]->sector_origen;00115 00116 actual->open_files[fd]->size = archivo.fat12_data.size;00117 00118 return OK;00119 } 00120 00121 00122 00123 int lseek (int fd, int offset, int donde)00124 {00125 00126 struct file *aux = actual->open_files[fd];00127 00128 dword sector_aux; // Numero de orden del sector (no es el numero del sector en el dispositivo. Toma los valores00129 // 0,1,2,3,4,5, etc dependiendo del sector sobre el cual este el offset00130 if (aux == NULL)00131 return -1;00132 00133 00134 if (donde == SEEK_SET) { //Posicionarse relativo al comienzo00135 00136 aux->sector_actual = aux->sector_origen; //Apuntar al primer sector (corrigiendolo)00137 if (offset < 0) {00138 aux->offset = 0;00139 return 0; //Posiciono al origen00140 }00141 00142 sector_aux = offset / SECTOR_SIZE;00143 00144 // Recorrer la FAT en busca del sector del proxumo sector00145 while ( sector_aux-- ) {00146 aux->sector_actual = fat_next_sector(aux->sector_actual);00147 if (aux->sector_actual <= 31) //provisorio00148 return 0; //El offset esta mas alla del tamaño del archivo00149 }00150 00151 aux->offset = offset;

Page 140: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00152 aux->offset_rel = offset % SECTOR_SIZE; //Offset relativo al comienzo del sector actual00153 return offset;00154 }00155 00156 else if (donde == SEEK_CUR) {00157 00158 offset = aux->offset + offset; //Aca obtuve el offset relativo al comienzo00159 return lseek(fd, offset , SEEK_SET); //AMO LA RECURSIVIDAD !!! no puedo creer que despues de escribir00160 } //tanto codigo repetido e ineficiente, me haya iluminado00161 00162 else if (donde == SEEK_END) {00163 if (offset > 0) 00164 return 0;00165 00166 offset = aux->size + offset; // Recordar que en este caso el offset seria negativo00167 return lseek(fd, offset , SEEK_SET);00168 }00169 00170 else return aux->offset;00171 00172 } 00173 00174 00175 00176 00177 int close (int fd)00178 {00179 struct file *aux;00180 if ( (aux = actual->open_files[fd])==NULL )00181 return -1;00182 00183 free(actual->open_files[fd]);00184 actual->open_files[fd] = NULL;00185 file_free++;00186 return fd;00187 }00188 00189 00190 //ssize_t read (int fd, void *buf, size_t nbytes)00191 //{00192 // size_t len=nbytes;00193 // ssize_t aux_len;00194 // 00195 // struct file *aux; //Apunta a la estructura de archivo abierto00196 // 00197 // if ( (aux=actual->open_files[fd] )==NULL) //Archivo no esta abierto00198 // return -1;00199 //00200 // //Corregir len en caso de que sea mayor que el tamaño del archivo00201 // if ( (aux->size) < (len + aux->offset) )00202 // len = (aux->size) - aux->offset;00203 //00204 // aux_len = len;

Page 141: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00205 // 00206 // char *bloque; //Puntero a bloque que contiene el sector ( mantenido por floppy_cache)00207 //00208 // //Esta variable me indica a cuantos bytes estoy del final del sector actual00209 // word remanente = SECTOR_SIZE - aux->offset_rel;00210 // word desplaz=0;00211 // 00212 //00213 // //Este ciclo va a ser el encargado de ir leyendo el sector que corresponde, y poniendolo en el buffer (buf)00214 // while (len > 0) {00215 // bloque = floppy_cache( aux->sector_actual );00216 // if (bloque == NULL) //Si no se pudo levantar al cache ese bloque...00217 // return -1;00218 //00219 // if (len <= remanente) //Si lo que voy a leer es menor que lo que falta para el final del sector00220 // aux_len = len; //no es necesario que cargue lea desde el disco (o desde el cache) es sector siguiente00221 //00222 // else aux_len = remanente; //Si en cambio, lo que tengo que leer es mayor a lo que queda de este sector00223 // //voy a tener que ir cargando del disco (o del cache) otros sectores hasta completar00224 // //el total00225 //00226 // //Poner en el buffer del llamante lo que lei del bloque actual00227 // memcpy( (buf + desplaz), (bloque + aux->offset_rel), aux_len);00228 // 00229 // //Corregir el offset00230 // lseek(fd, aux_len, SEEK_CUR );00231 // desplaz = desplaz + aux_len;00232 // len = len - aux_len;00233 // remanente = SECTOR_SIZE - aux->offset_rel;00234 // }00235 // 00236 // return desplaz;00237 //}00238 00239 ssize_t read (int fd, void *buf, size_t nbytes)00240 {00241 size_t len=nbytes;00242 ssize_t aux_len;00243 00244 struct file *aux; //Apunta a la estructura de archivo abierto00245 00246 #ifdef RUNSTATS00247 long long counter;00248 00249 if ( getvar("debugread") == 2 ) {00250 rdtscl(counter);00251 }00252 #endif00253 00254

Page 142: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00255 if ( (aux=actual->open_files[fd] )==NULL) //Archivo no esta abierto00256 return -1;00257 00258 //Corregir len en caso de que sea mayor que el tamaño del archivo00259 if ( (aux->size) < (len + aux->offset) )00260 len = (aux->size) - aux->offset;00261 00262 aux_len = len;00263 00264 //Esta variable me indica a cuantos bytes estoy del final del sector actual00265 word remanente = SECTOR_SIZE - aux->offset_rel;00266 word desplaz=0;00267 00268 00269 //Este ciclo va a ser el encargado de ir leyendo el sector que corresponde, y poniendolo en el buffer (buf)00270 while (len > 0) {00271 00272 /*00273 bloque = floppy_cache( aux->sector_actual );00274 if (bloque == NULL) //Si no se pudo levantar al cache ese bloque...00275 return -1;00276 */00277 00278 //setvar("debugcache",1);00279 //setvar("debugfloppy",1);00280 if ( cache_read(fd0,aux->sector_actual,aux->offset_rel,buf+desplaz,aux_len) == -1 )00281 return -1;00282 00283 00284 if (len <= remanente) //Si lo que voy a leer es menor que lo que falta para el final del sector00285 aux_len = len; //no es necesario que cargue lea desde el disco (o desde el cache) es sector siguiente00286 00287 else aux_len = remanente; //Si en cambio, lo que tengo que leer es mayor a lo que queda de este sector00288 //voy a tener que ir cargando del disco (o del cache) otros sectores hasta completar00289 //el total00290 00291 //Poner en el buffer del llamante lo que lei del bloque actual00292 //memcpy( (buf + desplaz), (bloque + aux->offset_rel), aux_len);00293 00294 //Corregir el offset00295 lseek(fd, aux_len, SEEK_CUR );00296 desplaz = desplaz + aux_len;00297 len = len - aux_len;00298 remanente = SECTOR_SIZE - aux->offset_rel;00299 }00300 00301 #ifdef RUNSTATS00302 if ( getvar("debugread") == 2 ) {00303 long long int counterfinal;

Page 143: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00304 rdtscl(counterfinal);00305 kprintf("R0x%llx ",counterfinal-counter);00306 } 00307 #endif00308 00309 00310 return desplaz;00311 }

Page 144: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

file.h

00001 /* file.h */00002 00003 #ifndef __SYSTEM00004 #include "routix/system.h"00005 #endif00006 00007 #ifndef __FAT1200008 #include "drivers/fat.h"00009 #endif00010 00011 #ifndef __FILE00012 #define __FILE00013 00014 00015 typedef struct file_opened_t00016 {00017 // byte *bloque;00018 dword sector_actual;00019 fat12_entry_ext_t datos;00020 dword fd; //File descriptor00021 dword offset; //Offset absoluto (al comienzo)00022 dword offset_rel; //Offset relativo al sector actual00023 dword sectores; //Cantidad de sectores que ocupa el archivo00024 struct file_opened_t *next;00025 }file_opened_t;00026 00027 ssize_t read (int fd, void *buf, size_t len);00028 int open (char *nombre);00029 int close (int fd);00030 int lseek (int fd, int offset, int donde);00031 00032 #define SEEK_CUR 100033 #define SEEK_SET 200034 #define SEEK_END 300035 00036 #define DRIVE_0 000037 #define FAT12 000038 00039 struct file 00040 {00041 byte device; // Tipo de dispositivo donde se encuentra el archivo00042 byte fs; // tipo de filesystem00043 dword sector_origen;// Sector donde comienza el archivo en el dispositivo device con filesystem fs00044 dword sector_actual;00045 dword offset; // offset desde el comienzo del archivo00046 dword offset_rel; // offset desde el sector sobre el que esta parado00047 dword sectores; // cantidad de sectores totales00048 dword size;00049 }; 00050 00051 #define MAX_FILES_POR_TAREA 500052 00053 #endif

Page 145: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

floppy.c

00001 /* floppy.c */00002 00003 /*00004 * Revision: 22 Marzo 200400005 * + Se migra la funcion (Floppy) llamada desde la rutina de atencion a interrupcion (intFloppy) a este archivo, 00006 * con lo que se hace la variable "continuar" (de ahora en mas llamada "floppy_continuar") como local al00007 * archivo (static).00008 *00009 * + Se ajustan los valores de inicializacion del floppy (comandos CONFIGURE y SPECIFY) de la siguiente forma:00010 * Se habilita la fifo (propia del 82077a) con un tama#o de 10 bytes.00011 * Step rate interval: 4mseg00012 * Head Unload time : 16mseg00013 * Head Load time : 16mseg00014 * 00015 * + Proxima revision:00016 * funciones de lectura y escritura00017 * conversion de sectores logicos a fisicos (LBA)00018 * ----------------------------------------------------------------00019 *00020 * Revision: 24 Marzo 200400021 *00022 * + Se crea la funcion dump_status_register() con fin de poder dumpear y debugear el estado de los registros00023 * de estado (ST0 a ST3)00024 *00025 * + En la funcion read_sector se reemplaza la verificacion de todos los bits del ST0 por una macro "COMMAND_OK"00026 * (definida en include/drivers/floppy.h) que solo chequea el valor del IC de este registro de estado.00027 * Esto es ya que cuando estamos en la condicion de sector=18 el valor de "H" devuelto por ST0 cambia (de 0 a 100028 * por ejemplo), pienso que se debera que nos indica la proxima posicion de la cabeza para leer el proximo00029 * sector (el sector numero 18 es el ultimo sector de un track en una cara).00030 * Con este cambio se observa que pueden ejecutarse sin problemas todos los archivos de disco.00031 */00032 00033 00034 00035 #include <drivers/floppy.h>00036 #include <fs/blockcache.h>00037 #include <routix/device.h>00038 #include <routix/atomic.h>00039 #include <routix/8259.h>00040 #include <routix/kstdio.h>00041 #include <routix/timer.h>00042 00043 #define OK 000044 00045 int block(void);00046 int floppy_get_result(void);

Page 146: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00047 int leer_sec(byte cara, byte cilindro, byte sector , byte *buffer);00048 void dump_states(void);00049 void dump_status_register(int numero, byte valor);00050 00051 void leer_escribir_new();00052 void init_floppy_block_new(void);00053 void recalibrate_block_new(void);00054 void motor_on_new_finish(timer_t *timer);00055 void seek_block_new();00056 void read_sector_block_new();00057 void error();00058 void error_por_timeout();00059 00060 00061 00062 00063 // Puntero a funcion para manejar las interrupciones00064 static void (*func)(void) = NULL;00065 00066 // Solicitud en proceso00067 static block_cache_t *actual_request = NULL;00068 #define ACTUAL_REQUEST (actual_request)00069 00070 //Contiene el estado del motor (0=apagado , 1=encendido)00071 static byte motor_status=MOTOR_OFF;00072 static byte floppy_calibrado=0;00073 static byte seek_status=0;00074 static byte rw_status=0;00075 00076 // Timer para encendido y apagado de motor00077 static timer_t *timer_motor = NULL;00078 // Timer de deteccion de TIMEOUTs00079 static timer_t *timer_timeout = NULL;00080 00081 // Array con los valores de estados y pcn en la fase de resultado.00082 // Valores validos: 0-255 ; ERR_TIMEOUT ; NO_VALIDO00083 static int status[12]; 00084 00085 #define ST0 status[0]00086 #define ST1 status[1]00087 #define ST2 status[2]00088 #define ST3 status[3]00089 00090 00091 // En esta direccion (640K - 1024) se ubica el bloque para transferencias DMA. La ubicacion de este bloque no puede00092 // quedar entre dos paginas (el tamaño de estas paginas es de 64K) es decir tiene que estar totalmente contenido dentro00093 // del mismo bloque.00094 addr_t dma_address=0xA0000 - 1024;00095 00096 00097 void motor_on()00098 {00099 outportb(DOR, DMA_INT | MOTA);00100 motor_status=1;00101 dword demora=0x3ffff; 00102 while (demora--); //Esperar por el regimen permanente del motor

Page 147: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00103 }00104 00105 00106 00107 // Version de motor on con timers00108 void motor_on_new()00109 {00110 timer_motor = create_timer(USECONDS_TO_TICKS(TIME_WAIT_FOR_MOTOR_ON), NULL, motor_on_new_finish, NULL);00111 00112 outportb(DOR, DMA_INT | MOTA);00113 }00114 00115 // Regimen permanente alcanzado00116 void motor_on_new_finish(timer_t *timer)00117 {00118 //kprintf("Pasaron 500mseg... regimen permanente alcanzado\n");00119 motor_status=MOTOR_ON;00120 00121 // El timer ya no existe00122 timer_motor = NULL;00123 00124 00125 // Si fue como resultado de un pedido de lectura o escritura00126 if ( ACTUAL_REQUEST != NULL )00127 leer_escribir_new();00128 00129 }00130 00131 00132 void motor_off()00133 {00134 outportb(DOR, DMA_INT);00135 motor_status=0;00136 floppy_calibrado=0;00137 }00138 00139 00140 void motor_off_new(timer_t *timer)00141 {00142 outportb(DOR, DMA_INT);00143 motor_status=MOTOR_OFF;00144 00145 // Todo a su posicion original00146 floppy_calibrado=0;00147 seek_status=0;00148 rw_status=0;00149 00150 //kprintf("motor_off_new: Apagando el motor\n");00151 00152 // Eliminamos el timer00153 //clean_timer(timer);00154 00155 // No existe00156 timer_motor = NULL;00157 }00158 00159 00160

Page 148: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00161 void set_dor(word valor)00162 {00163 outportb(DOR, valor);00164 }00165 00166 00167 00169 // Envia un byte al registro de datos del controlador //00171 int floppy_sendbyte(byte valor)00172 {00173 unsigned char msr;00174 int timeout;00175 00176 for (timeout=SENDBYTE_TIMEOUT; timeout; timeout--) {00177 00178 // Leemos primero el MSR (Main Status Register)00179 msr = inportb(MSR);00180 00181 // Si RQM=1 y DIO=0 ( Host puede escribir info)00182 if ( (msr & RQM) && ~(msr & DIO) ) {00183 outportb(DATA, valor);00184 break;00185 }00186 00187 }00188 00189 // Si timeout llego a 0 no se pudo completar la escritura00190 return timeout;00191 }00192 00193 00195 // Lee un byte del registro de datos del controlador //00197 int floppy_get_result()00198 {00199 unsigned char msr;00200 byte posicion=0;00201 int timeout;00202 00203 for (timeout=GETBYTE_TIMEOUT; timeout; timeout--) 00204 {00205 // Leemos primero el MSR (Main Status Register)00206 msr = inportb(MSR) & (RQM | CMDBUSY | DIO);00207 00208 // Si RQM=1, DIO=1 y CMD_BUSY=1 ( Host puede leer info)00209 if ( msr == (RQM | CMDBUSY | DIO) )00210 {00211 status[posicion++]=inportb(DATA);00212 continue;00213 }00214 //Si el controller dejo de estar ocupado (CMD_BUSY=0), no hay mas resultados que levantar, salida Ok00215 else if ( msr == RQM )00216 {00217 status[posicion]=NO_VALIDO;00218 return OK;00219 }00220 }00221 00222 // Si timeout llego a 0 no se pudo completar la escritura00223 return ERR_TIMEOUT;

Page 149: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00224 00225 }00226 00227 00228 // Inicializacion del floppy00229 int init_floppy()00230 {00231 int i;00232 00233 // Reset00234 outportb(DOR, 0);00235 00236 outportb(DOR, 0x0C);00237 00238 // Programamos la velocidad de datos (500 Kbps para 1.44MB)00239 outportb(CCR, DR_500KBPS);00240 00241 //Esperamos la interrupcion00242 block();00243 00244 // Recolectamos el estado de las interrupciones de los 4 drives00245 // que soporta el controlador00246 for (i=0; i<4; i++) {00247 00248 if ( ! floppy_sendbyte(SENSE_INTERRUPT_STATUS) ) {00249 return ERR_TIMEOUT;00250 }00251 00252 00253 if (floppy_get_result()==ERR_TIMEOUT) {00254 return ERR_TIMEOUT;00255 }00256 00257 }00258 00259 00260 // Ahora reconfiguramos el controlador00261 if ( ! floppy_sendbyte(CONFIGURE_0) ) {00262 return ERR_TIMEOUT;00263 }00264 if ( ! floppy_sendbyte(CONFIGURE_1) ) {00265 return ERR_TIMEOUT;00266 }00267 00268 // COMENTARIO: me quedan dudas respecto a estos valores ya que00269 // CONF_EIS: habilitamos los seeks automaticos (implicitos)00270 // CONF_EFIFO: deshabilitamos los fifos !! (modo 8272a)00271 // CONF_POLL: deshabilitamos el polling, esto esta oks00272 //if ( ! floppy_sendbyte(CONF_EIS|CONF_EFIFO|CONF_POLL) ) {}00273 if ( ! floppy_sendbyte( (CONF_EIS|CONF_POLL) | 0xa) ) { // 10 bytes de threshold00274 return ERR_TIMEOUT;00275 }00276 if ( ! floppy_sendbyte(0) ) {00277 return ERR_TIMEOUT;00278 }00279 00280 // Seguimos con SPECIFY00281 if ( ! floppy_sendbyte(SPECIFY) ) {00282 return ERR_TIMEOUT;

Page 150: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00283 } 00284 00285 if ( ! floppy_sendbyte(0xC1) ) { // Seteamos SRT=4mseg (0xC0) y HUT=16mseg (0x01)00286 return ERR_TIMEOUT;00287 }00288 00289 if ( ! floppy_sendbyte(0x8<<1) ) { // Seteamos HLT=16mseg (0x08 << 1) y ND (Ahora esta en NON-DMA !!)00290 return ERR_TIMEOUT;00291 }00292 00293 //kprintf("Inicializacion Oks !!\n");00294 00295 return OK; 00296 }00297 00298 00299 00300 00301 // Inicializacion del floppy00302 void init_floppy_new()00303 {00304 00305 // Reset00306 outportb(DOR, 0);00307 00308 outportb(DOR, 0x0C);00309 00310 // Programamos la velocidad de datos (500 Kbps para 1.44MB)00311 outportb(CCR, DR_500KBPS);00312 00313 //Esperamos la interrupcion, le indicamos la nueva rutina de atencion de interrupcion00314 //block();00315 func=init_floppy_block_new;00316 }00317 00318 00319 void init_floppy_block_new(void)00320 { 00321 int i;00322 00323 // Reseteamos a func a su valor default00324 func=NULL;00325 00326 // Recolectamos el estado de las interrupciones de los 4 drives00327 // que soporta el controlador00328 for (i=0; i<4; i++) {00329 00330 if ( ! floppy_sendbyte(SENSE_INTERRUPT_STATUS) ) {00331 //return ERR_TIMEOUT;00332 }00333 00334 00335 if (floppy_get_result()==ERR_TIMEOUT) {00336 //return ERR_TIMEOUT;00337 }00338 00339 }

Page 151: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00340 00341 00342 // Ahora reconfiguramos el controlador00343 if ( ! floppy_sendbyte(CONFIGURE_0) ) {00344 //return ERR_TIMEOUT;00345 }00346 if ( ! floppy_sendbyte(CONFIGURE_1) ) {00347 //return ERR_TIMEOUT;00348 }00349 00350 // COMENTARIO: me quedan dudas respecto a estos valores ya que00351 // CONF_EIS: habilitamos los seeks automaticos (implicitos)00352 // CONF_EFIFO: deshabilitamos los fifos !! (modo 8272a)00353 // CONF_POLL: deshabilitamos el polling, esto esta oks00354 //if ( ! floppy_sendbyte(CONF_EIS|CONF_EFIFO|CONF_POLL) ) {}00355 if ( ! floppy_sendbyte( (CONF_EIS|CONF_POLL) | 0xa) ) { // 10 bytes de threshold00356 //return ERR_TIMEOUT;00357 }00358 if ( ! floppy_sendbyte(0) ) {00359 //return ERR_TIMEOUT;00360 }00361 00362 // Seguimos con SPECIFY00363 if ( ! floppy_sendbyte(SPECIFY) ) {00364 //return ERR_TIMEOUT;00365 } 00366 00367 if ( ! floppy_sendbyte(0xC1) ) { // Seteamos SRT=4mseg (0xC0) y HUT=16mseg (0x01)00368 //return ERR_TIMEOUT;00369 }00370 00371 if ( ! floppy_sendbyte(0x8<<1) ) { // Seteamos HLT=16mseg (0x08 << 1) y ND (Ahora esta en NON-DMA !!)00372 //return ERR_TIMEOUT;00373 }00374 00375 // Si fue como resultado de un pedido de lectura o escritura00376 if ( ACTUAL_REQUEST != NULL )00377 leer_escribir_new();00378 00379 }00380 00381 00383 // Recalibra la posicion de la cabeza a la pista 000385 #define PCN status[1]00386 00387 int recalibrate()00388 {00389 00390 // Reseteamos el flag00391 floppy_calibrado=0;00392 00393 // Habilita el motor A y el Drive 000394 motor_on();00395 00396 // Ejecutamos un RECALIBRATE 00397 if ( ! floppy_sendbyte(RECALIBRATE) ) { 00398 return ERR_TIMEOUT;00399 }

Page 152: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00400 00401 if ( ! floppy_sendbyte(DRIVE_0) ) { // DS0=0 DS1=0 (Drive 0)00402 return ERR_TIMEOUT;00403 }00404 00405 if ( block()!=OK ) {00406 return ERR_NEED_RESET;00407 }00408 00409 // Sensamos el estado de interrupcion00410 if ( ! floppy_sendbyte(SENSE_INTERRUPT_STATUS) ) {00411 return ERR_TIMEOUT;00412 }00413 00414 // Obtener resultados de ejecucion 00415 if (floppy_get_result()==ERR_TIMEOUT) {00416 return ERR_TIMEOUT;00417 }00418 00419 // Analizamos el resultado del comando 00420 if ( ! COMMAND_OK ) {00421 //kprintf("RECALIBRATE\n");00422 dump_states();00423 return ERR_NEED_RESET;00424 }00425 00426 // Pudimos calibrarlo sin problemas00427 floppy_calibrado=1;00428 00429 return OK;00430 }00431 00432 00433 00434 int recalibrate_new()00435 {00436 00437 // Reseteamos el flag00438 floppy_calibrado=0;00439 00440 // Ejecutamos un RECALIBRATE 00441 if ( ! floppy_sendbyte(RECALIBRATE) ) { 00442 return ERR_TIMEOUT;00443 }00444 00445 if ( ! floppy_sendbyte(DRIVE_0) ) { // DS0=0 DS1=0 (Drive 0)00446 return ERR_TIMEOUT;00447 }00448 00449 //Esperamos la interrupcion, le indicamos la nueva rutina de atencion de interrupcion00450 func=recalibrate_block_new;00451 00452 // Aca debemos agregar el timer de timeout00453 timer_timeout = create_timer(USECONDS_TO_TICKS(TIEMPO_TIMEOUT_COMANDO), NULL, error_por_timeout, NULL);00454 00455 if ( getvar("debugfloppy")==1 )

Page 153: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00456 kprintf("Envio de recalibrate_new !!\n");00457 00458 return OK;00459 00460 }00461 00462 void recalibrate_block_new(void)00463 {00464 // Reseteamos a func a su valor default00465 func=NULL;00466 00467 // Eliminamos el timer de timeout00468 clean_timer(timer_timeout);00469 00470 // El timer ya no existe00471 timer_timeout = NULL;00472 00473 if ( getvar("debugfloppy")==1 )00474 kprintf("Recalibrado ok !!\n");00475 00476 // Sensamos el estado de interrupcion00477 if ( ! floppy_sendbyte(SENSE_INTERRUPT_STATUS) ) {00478 //return ERR_TIMEOUT;00479 error();00480 return;00481 }00482 00483 // Obtener resultados de ejecucion 00484 if (floppy_get_result()==ERR_TIMEOUT) {00485 //return ERR_TIMEOUT;00486 error();00487 return;00488 }00489 00490 // Analizamos el resultado del comando 00491 if ( ! COMMAND_OK ) {00492 dump_states();00493 //return ERR_NEED_RESET;00494 error();00495 return;00496 }00497 00498 // Pudimos calibrarlo sin problemas00499 floppy_calibrado=1;00500 00501 // Si fue como resultado de un pedido de lectura o escritura00502 if ( ACTUAL_REQUEST != NULL )00503 leer_escribir_new();00504 00505 //return OK;00506 }00507 00508 00509 byte read_sector_id (void)00510 {00511 // Habilita el motor A y el Drive 000512 motor_on();00513 00514 // Ejecutamos un Read sector id

Page 154: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00515 if ( ! floppy_sendbyte(READ_SECTOR_ID) ) { 00516 return ERR_TIMEOUT;00517 }00518 00519 if ( ! floppy_sendbyte(0) ) { // HD=0 (head number) , DS0=0 DS1=0 (Drive 0)00520 return ERR_TIMEOUT;00521 }00522 00523 block();00524 00525 // Sensamos el estado de interrupcion00526 /* if ( ! floppy_sendbyte(SENSE_INTERRUPT_STATUS) ) {00527 puts("Error, timeout enviando SENSE_INTERRUPT_STATUS\n");00528 return;00529 }00530 */00531 // Obtener resultados de ejecucion 00532 00533 if (floppy_get_result()==ERR_TIMEOUT)00534 {00535 return ERR_TIMEOUT;00536 }00537 00538 byte posicion=0;00539 while ( status[posicion] != NO_VALIDO && posicion < 12)00540 {00541 //kprintf("Resultado Read Id%d: %x\n", (posicion), status[posicion]);00542 posicion++;00543 }00544 00545 return 1;00546 00547 } 00548 00549 00551 // Posicionar el cabezal sobre la pista indicada00553 00554 byte seek (byte cara, byte pista)00555 {00556 00557 // Ejecutamos un Read sector00558 if ( ! floppy_sendbyte(SEEK) ) { 00559 return ERR_TIMEOUT;00560 }00561 00562 if ( ! floppy_sendbyte( (cara << 2) |DRIVE_0) ) { // HD=0 (head number) , DS0=0 DS1=0 (Drive 0)00563 return ERR_TIMEOUT;00564 }00565 00566 if ( ! floppy_sendbyte(pista) ) { // Cilindro00567 return ERR_TIMEOUT;00568 }00569 00570 block();00571 00572 // Sensamos el estado de interrupcion

Page 155: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00573 if ( ! floppy_sendbyte(SENSE_INTERRUPT_STATUS) ) {00574 return ERR_TIMEOUT;00575 }00576 00577 // Obtener resultados de ejecucion 00578 if (floppy_get_result()==ERR_TIMEOUT) {00579 return ERR_TIMEOUT;00580 }00581 00582 // Analizamos el resultado del comando 00583 if ( ! COMMAND_OK ) {00584 //kprintf("SEEK !!!\n");00585 dump_states();00586 return ERR_TIMEOUT;00587 }00588 00589 return OK;00590 } 00591 00592 00593 int seek_new (byte cara, byte pista)00594 {00595 00596 // Ejecutamos un Read sector00597 if ( ! floppy_sendbyte(SEEK) ) { 00598 return ERR_TIMEOUT;00599 }00600 00601 if ( ! floppy_sendbyte( (cara << 2) |DRIVE_0) ) { // HD=0 (head number) , DS0=0 DS1=0 (Drive 0)00602 return ERR_TIMEOUT;00603 }00604 00605 if ( ! floppy_sendbyte(pista) ) { // Cilindro00606 return ERR_TIMEOUT;00607 }00608 00609 //Esperamos la interrupcion, le indicamos la nueva rutina de atencion de interrupcion00610 func=seek_block_new;00611 00612 // Aca debemos agregar el timer de timeout00613 timer_timeout = create_timer(USECONDS_TO_TICKS(TIEMPO_TIMEOUT_COMANDO), NULL, error_por_timeout, NULL);00614 00615 if ( getvar("debugfloppy")==1 )00616 kprintf("Envio de seek_new !!\n");00617 00618 return OK;00619 }00620 00621 void seek_block_new()00622 {00623 // Reseteamos a func a su valor default00624 func=NULL;00625 00626 if ( getvar("debugfloppy")==1 )00627 kprintf("Retorno de seek_block !!\n");00628

Page 156: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00629 // Eliminamos el timer de timeout00630 clean_timer(timer_timeout);00631 00632 // El timer ya no existe00633 timer_timeout = NULL; 00634 00635 //kprintf("Int de seek Ok !!\n");00636 00637 // Sensamos el estado de interrupcion00638 if ( ! floppy_sendbyte(SENSE_INTERRUPT_STATUS) ) {00639 //return ERR_TIMEOUT;00640 error();00641 return;00642 }00643 00644 // Obtener resultados de ejecucion 00645 if (floppy_get_result()==ERR_TIMEOUT) {00646 //return ERR_TIMEOUT;00647 error();00648 return;00649 }00650 00651 // Analizamos el resultado del comando 00652 if ( ! COMMAND_OK ) {00653 dump_states();00654 //return ERR_TIMEOUT;00655 error();00656 return;00657 }00658 00659 //kprintf("seek_block_new: seek ok!!\n");00660 00661 // Pudimos calibrarlo sin problemas00662 seek_status=1;00663 00664 // Si fue como resultado de un pedido de lectura o escritura00665 if ( ACTUAL_REQUEST != NULL ) {00666 //kprintf("seek_block_new: Volvemos a leer_escribir_new\n");00667 leer_escribir_new();00668 }00669 00670 } 00671 00673 // Lee un sector fisico (previamente el cabezal debe estar calibrado y posicionado)00675 00676 int read_sector (byte cara, byte cilindro, byte sector)00677 {00678 00679 init_floppy_DMA (DMA_READ);00680 00681 // Ejecutamos un Read sector00682 if ( ! floppy_sendbyte(READ_SECTOR) ) { 00683 return ERR_TIMEOUT;00684 }00685 00686 if ( ! floppy_sendbyte(DRIVE_0 | (cara << 2)) ) { // HD=0 (head number) , DS0=0 DS1=0 (Drive 0)00687 return ERR_TIMEOUT;00688 }00689

Page 157: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00690 if ( ! floppy_sendbyte(cilindro) ) { // Cilindro00691 return ERR_TIMEOUT;00692 }00693 00694 if ( ! floppy_sendbyte(cara) ) { // Cabeza00695 return ERR_TIMEOUT;00696 }00697 00698 if ( ! floppy_sendbyte(sector) ) { // Sector00699 return ERR_TIMEOUT;00700 }00701 if ( ! floppy_sendbyte(2) ) { // Tamaño sector: 128 * 2^x (si x=2-->Sector=512 bytes)00702 return ERR_TIMEOUT;00703 }00704 if ( ! floppy_sendbyte( SECTORES_POR_PISTA ) ) { // Sectores por pista00705 return ERR_TIMEOUT;00706 }00707 if ( ! floppy_sendbyte(27) ) { // GAP: 27 para 3 1/2 ; 32 para 5 1/400708 return ERR_TIMEOUT;00709 }00710 if ( ! floppy_sendbyte(0xff) ) { // Data Lengh00711 return ERR_TIMEOUT;00712 }00713 00714 if ( block()!=OK ) {00715 //kprintf("Error read sector block\n");00716 return ERR_NEED_RESET;00717 }00718 00719 // Obtener resultados de ejecucion 00720 if (floppy_get_result()==ERR_TIMEOUT) {00721 return ERR_TIMEOUT;00722 }00723 00724 // Analizamos el resultado del comando 00725 if ( ! COMMAND_OK ) {00726 dump_states();00727 return ERR_NEED_RESET;00728 }00729 00730 return OK;00731 } 00732 00733 00734 00735 int read_sector_new (byte cara, byte cilindro, byte sector)00736 {00737 00738 //kprintf("read_sector_new: inicializando Dma\n");00739 00740 init_floppy_DMA (DMA_READ);00741 00742 // Ejecutamos un Read sector00743 if ( ! floppy_sendbyte(READ_SECTOR) ) {

Page 158: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00744 return ERR_TIMEOUT;00745 }00746 00747 if ( ! floppy_sendbyte(DRIVE_0 | (cara << 2)) ) { // HD=0 (head number) , DS0=0 DS1=0 (Drive 0)00748 return ERR_TIMEOUT;00749 }00750 00751 if ( ! floppy_sendbyte(cilindro) ) { // Cilindro00752 return ERR_TIMEOUT;00753 }00754 00755 if ( ! floppy_sendbyte(cara) ) { // Cabeza00756 return ERR_TIMEOUT;00757 }00758 00759 if ( ! floppy_sendbyte(sector) ) { // Sector00760 return ERR_TIMEOUT;00761 }00762 00763 if ( ! floppy_sendbyte(2) ) { // Tamaño sector: 128 * 2^x (si x=2-->Sector=512 bytes)00764 return ERR_TIMEOUT;00765 }00766 00767 if ( ! floppy_sendbyte( SECTORES_POR_PISTA ) ) { // Sectores por pista00768 return ERR_TIMEOUT;00769 }00770 00771 if ( ! floppy_sendbyte(27) ) { // GAP: 27 para 3 1/2 ; 32 para 5 1/400772 return ERR_TIMEOUT;00773 }00774 00775 if ( ! floppy_sendbyte(0xff) ) { // Data Lengh00776 return ERR_TIMEOUT;00777 }00778 00779 //Esperamos la interrupcion, le indicamos la nueva rutina de atencion de interrupcion00780 func=read_sector_block_new;00781 00782 // Aca debemos agregar el timer de timeout00783 timer_timeout = create_timer(USECONDS_TO_TICKS(TIEMPO_TIMEOUT_COMANDO), NULL, error_por_timeout, NULL);00784 00785 return OK;00786 }00787 00788 void read_sector_block_new()00789 {00790 00791 // Reseteamos a func a su valor default00792 func=NULL;00793

Page 159: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00794 // Eliminamos el timer de timeout00795 clean_timer(timer_timeout);00796 00797 // El timer ya no existe00798 timer_timeout = NULL; 00799 00800 // Obtener resultados de ejecucion 00801 if (floppy_get_result()==ERR_TIMEOUT) {00802 //return ERR_TIMEOUT;00803 error();00804 return;00805 }00806 00807 // Analizamos el resultado del comando 00808 if ( ! COMMAND_OK ) {00809 dump_states();00810 //return ERR_NEED_RESET;00811 error();00812 return;00813 }00814 00815 // Pudimos calibrarlo sin problemas00816 rw_status=1;00817 00818 // Si fue como resultado de un pedido de lectura o escritura00819 if ( ACTUAL_REQUEST != NULL )00820 leer_escribir_new();00821 00822 } 00823 00824 00825 char read_msr()00826 {00827 unsigned char msr;00828 00829 msr = inportb(MSR);00830 00831 return msr;00832 }00833 00835 // block: bloquea la ejecucion del proceso que la llama hasta recibir una interrupcion de floppy00837 00838 static byte floppy_continuar; // variable candado de block00839 00840 int block(void)00841 {00842 // Deshabilitamos las interrupciones 00843 disable_irq(6);00844 00845 floppy_continuar=0;00846 00847 // TEMPORAL00848 dword timeout=0xffffffff; //Este timeout es momentaneo (sera reemplazado por un timer). Puede que en maquinas con00849 //micro de mas de 600Mhz haya que aumentarlo... 00850 // Las habilitamos nuevamente00851 enable_irq(6); 00852 00853 // Esperamos que aparezca la interrupcion

Page 160: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00854 while (!floppy_continuar) {00855 timeout--;00856 if (!timeout) //En caso de no haber llegado la IRQ6, salir con ERR_TIMEOUT00857 return ERR_TIMEOUT;00858 }00859 00860 return OK;00861 }00862 00863 00864 00866 // Inicializa el controlador DMA, tanto para leer como para escribir (segun comando)00868 00869 void init_floppy_DMA ( byte comando )00870 {00871 outportb( DMA_MASK, 0x06 );00872 // Resetear el FlipFlop del DMA para que reconozca al primer byte enviado como un LSB00873 outportb ( 0xC, 0);00874 00875 // Enviar comando (DMA_READ, DMA_WRITE)00876 outportb( DMA_CMD, comando );00877 00878 // Seteo de la direccion. No debera estar por encima de los 16MB00879 outportb ( DMA_CH2_ADDR, (byte) dma_address);00880 outportb ( DMA_CH2_ADDR, (byte) (dma_address >> 8) );00881 outportb ( DMA_CH2_PAGE, (byte) (dma_address >> 16) );00882 00883 outportb ( DMA_CH2_COUNT, (byte) ( (BLOQUE_SIZE-1) & 0xff) );00884 outportb ( DMA_CH2_COUNT, (byte) ( (BLOQUE_SIZE-1) >> 8) );00885 outportb ( DMA_MASK, 2);00886 } 00887 00888 00889 00890 00892 // Acepta como operacion READ_SECTOR y WRITE_SECTOR (quiza pueda aceptar format).00893 // Es la encargada de convertir un sector logico (o LBA) en el sector fisico (CHS) correspondiente.00894 // Inicializa el controlador de floppy y enciende el motor. En caso de time outs, intenta hasta MAX_TRYS00896 00897 int leer_escribir(byte operacion, dword sector_logico, byte *buffer)00898 {00899 byte intentos=0;00900 byte cara, cilindro, sector;00901 00902 00903 intentar_nuevamente: 00904 intentos++;00905 if (intentos > MAX_FLOPPY_TRYS ) {00906 //kprintf("No se puede leer el sector %d(superados %d intentos)\n", sector_logico, MAX_FLOPPY_TRYS);00907 return ERR_MAX_TRYS;00908 }

Page 161: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00909 00910 00911 if (motor_status==0) {00912 init_floppy();00913 motor_on();00914 }00915 00916 00917 if (floppy_calibrado==0)00918 if ( recalibrate()!=OK )00919 goto intentar_nuevamente;00920 00921 00922 //Calcular el sector fisico (CHS) a traves del sector logico (LBA)00923 cara = (sector_logico / SECTORES_POR_PISTA) % CARAS_POR_PISTA;00924 cilindro = (sector_logico / SECTORES_POR_PISTA) /CARAS_POR_PISTA;00925 sector = (sector_logico % SECTORES_POR_PISTA) + 1;00926 00927 // Esto no deberia ser necesario ya que configuramos el controlador con EIS (Implied Seek) 00928 if ( seek(cara, cilindro) != OK) {00929 goto intentar_nuevamente;00930 }00931 00932 if (operacion == READ_SECTOR) {00933 if ( leer_sec(cara, cilindro, sector, buffer)!=OK )00934 goto intentar_nuevamente;00935 return OK;00936 }00937 00938 //No implementado00939 if (operacion == WRITE_SECTOR)00940 return OK;00941 else return -1;00942 } 00943 00944 00945 // Nueva funcion00946 //00947 // El proceso de lectura implica los siguientes pasos:00948 //00949 // 1. Encender el motor (si fuese necesario)00950 //00951 // a. Setear el bit del motor correspondiente en el registro DOR00952 // b. Esperar 500 mseg aproximadamente de modo que se estabilice00953 // la velocidad de giro del motor00954 //00955 // 2. Recalibracion (si fuese necesario)00956 //00957 // a. Enviar comando00958 // b. Esperar interrupcion00959 //00960 // 3. Seek en la cabeza, cilindro y sector correspondiente00961 //00962 // a. Enviar comando00963 // b. Esperar interrupcion

Page 162: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00964 //00965 // 4. Lectura del sector00966 //00967 // a. Enviar comando00968 // b. Esperar interrupcion00969 //00970 // Bien, el problema ppal es que si uso el modelo tipo:00971 //00972 // * envio comando00973 // * cambio el puntero de interrupcion de floppy00974 //00975 // se desestructura el codigo y pierdo las variables locales.00976 //00977 // Por ejemplo, en la funcion de lectura al llamar a la funcion de SEEK, 00978 // se pierde la memoria de la funcion previa (lectura).00979 //00981 //00982 // La primer solucion propuesta es la siguiente:00983 //00984 // Se guardará como un puntero la funcion base de ejecucion, en el ejemplo anterior sera00985 // la de lectura, en el proceso de lectura se realizara:00986 //00987 // 1. El motor esta encendido ?00988 // NO: ejecutar motor_on()00989 //00990 // Si no estaba encendido, motor_on se ejecutara y devolver el control al kernel mientras espera00991 // que se venza el timer de 500 mseg, la funcion de retorno de motor_on() establecera la variable00992 // global motor_status como encendida y llamara nuevamente a la funcion de lectura, quien ahora00993 // realizara los siguientes pasos:00994 //00995 // 1. El motor esta encendido ?00996 // SI: seguimos00997 // 00998 // 2. Esta Recalibrado ?00999 // NO: llamamos a recalibrate01000 //01001 // y el proceso continua de la misma forma01002 //01004 01005 //int leer_escribir_new(byte operacion, dword sector_logico, byte *buffer)01006 // Toma todos los argumentos necesarios de la variable global ACTUAL_REQUEST01007 void leer_escribir_new()01008 {01009 byte cara, cilindro, sector;01010 int cmdret;01011 01012 01013 if ( getvar("debugfloppy")==1 )01014 kprintf("leer_escribir_new: motor=%d calibracion=%d\n",motor_status,floppy_calibrado); 01015 01016 // Motor apagado ?01017 if (motor_status==MOTOR_OFF) {01018 if ( getvar("debugfloppy")==1 )

Page 163: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

01019 kprintf("leer_escribir_new: Motor apagado, encendiendo\n");01020 motor_on_new();01021 return;01022 }01023 01024 // Verificamos si existe un timer de apagado01025 else if (timer_motor!=NULL) {01026 01027 // Debemos eliminarlo01028 clean_timer(timer_motor);01029 01030 // No existe mas01031 timer_motor = NULL;01032 01033 }01034 01035 if ( ! floppy_calibrado ) {01036 //kprintf("leer_escribir_new: Calibrando\n");01037 01038 // Comando enviado oks?01039 if ( (cmdret=recalibrate_new()) == OK ) {01040 return;01041 }01042 01043 // Retornamos el error01044 else {01045 error();01046 return;01047 }01048 01049 }01050 01051 01052 //Calcular el sector fisico (CHS) a traves del sector logico (LBA)01053 cara = (DRIVER_REQUEST_SECTOR(ACTUAL_REQUEST) / SECTORES_POR_PISTA) % CARAS_POR_PISTA;01054 cilindro = (DRIVER_REQUEST_SECTOR(ACTUAL_REQUEST) / SECTORES_POR_PISTA) /CARAS_POR_PISTA;01055 sector = (DRIVER_REQUEST_SECTOR(ACTUAL_REQUEST) % SECTORES_POR_PISTA) + 1;01056 01057 if ( getvar("debugfloppy")==1 )01058 kprintf("leer_escribir: sector logico=%d ==> h=%d c=%d s=%d\n", DRIVER_REQUEST_SECTOR(ACTUAL_REQUEST), \01059 cara, cilindro, sector);01060 01061 // Esto no deberia ser necesario ya que configuramos el controlador con EIS (Implied Seek) 01062 if ( ! seek_status ) {01063 //kprintf("leer_escribir_new: Posicionando (Seeking)\n");01064 01065 // Comando enviado oks?01066 if ( (cmdret=seek_new(cara, cilindro)) == OK )01067 return;01068 01069 // Retornamos el error01070 else {01071 error();

Page 164: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

01072 return;01073 }01074 }01075 01076 if ( DRIVER_REQUEST_OPERATION(ACTUAL_REQUEST) == IOREAD ) {01077 01078 if ( getvar("debugfloppy")==1 )01079 kprintf("leer_escribir_new: Leyendo\n");01080 01081 // Todavia no fue hecha la lectura01082 if ( ! rw_status ) {01083 01084 // Comando enviado oks?01085 if ( (cmdret=read_sector_new(cara, cilindro, sector)) == OK )01086 return;01087 01088 // Retornamos el error01089 else {01090 error();01091 return;01092 }01093 01094 01095 }01096 01097 // Hicimos la lectura en un paso previo, veamos que resulto01098 else {01099 //kprintf("leer_escribir_new: Fase de lectura terminada, copiando al buffer\n");01100 01101 word i;01102 01103 byte *dma_block = (byte *) dma_address;01104 byte *buffer = DRIVER_REQUEST_BUFFER(ACTUAL_REQUEST);01105 01106 for(i=0 ; i < BLOQUE_SIZE ; i++) 01107 *buffer++ = *dma_block++;01108 01109 // Oks, ya hicimos todo, resta colocar ok en el retorno del buffer block, 01110 // marcarlo como hecho, despertar a la tarea que genero todo esto y01111 // colocar un timer de apagado de motor01112 floppy_calibrado=0;01113 seek_status=0;01114 rw_status=0;01115 01116 // Bloque leido correctamente01117 DRIVER_REQUEST_RETURN(ACTUAL_REQUEST) = 1;01118 01119 }01120 01121 }01122 01123 //No implementado01124 else if ( DRIVER_REQUEST_OPERATION(ACTUAL_REQUEST) == IOWRITE ) {

Page 165: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

01125 //kprintf("WRITE: operacion no permitida\n");01126 }01127 01128 // Indicamos al cache que terminamos nuestra operatoria01129 endrequest(ACTUAL_REQUEST);01130 01131 // Liberamos al floppy01132 ACTUAL_REQUEST=NULL;01133 01134 // En algunos segundos apagamos el motor01135 timer_motor = create_timer(USECONDS_TO_TICKS(TIEMPO_APAGADO_MOTOR_POR_INACTIVIDAD), NULL, motor_off_new, NULL);01136 01137 return;01138 01139 }01140 01141 // Esta funcion es llamada si se vencio el tiempo de espera de interrupcion01142 void error_por_timeout()01143 {01144 01145 // El timer ya no existe01146 timer_timeout = NULL; 01147 01148 // llamamos a la rutina de error01149 error();01150 01151 }01152 01153 // Algun error, debemos actualizar el bloque indicando dicho error01154 void error()01155 {01156 01157 // Oks, hubo un error, resta colocarlo en el retorno del buffer block,01158 // marcarlo como hecho, despertar a la tarea que genero todo esto y01159 // colocar un timer de apagado de motor01160 DRIVER_REQUEST_RETURN(ACTUAL_REQUEST) = -1;01161 01162 floppy_calibrado=0;01163 seek_status=0;01164 rw_status=0;01165 01166 // Liberamos al floppy01167 ACTUAL_REQUEST=NULL;01168 01169 // Indicamos al cache que terminamos nuestra operatoria01170 endrequest(ACTUAL_REQUEST);01171 01172 // En algunos segundos apagamos el motor01173 timer_motor = create_timer(USECONDS_TO_TICKS(TIEMPO_APAGADO_MOTOR_POR_INACTIVIDAD), NULL, motor_off_new, NULL);01174 01175 }01176

Page 166: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

01177 int leer_sec(byte cara, byte cilindro, byte sector , byte *buffer)01178 {01179 if ( read_sector(cara, cilindro , sector)!=OK )01180 return ERR_NEED_RESET;01181 01182 word i;01183 01184 byte *dma_block = (byte *) dma_address;01185 for( i=0 ; i < BLOQUE_SIZE ; i++) 01186 *buffer++ = *dma_block++;01187 01188 return OK;01189 }01190 01191 void dump_states()01192 {01193 int posicion;01194 01195 for (posicion=0; (posicion<sizeof(status)) && (status[posicion]!=NO_VALIDO); posicion++ )01196 dump_status_register(posicion, status[posicion]);01197 01198 01199 }01200 01201 01202 static char *ic_codes[] = { "Terminacion Normal", "Terminacion erronea",01203 "Comando invalido" , "Terminacion erronea causada por polling" };01204 01205 void dump_status_register(int numero, byte valor)01206 {01207 switch(numero) {01208 01209 // ST0 : 7-6:IC, 5:SE, 4:EC, 3:nada, 2:H, 1-0:DS01210 case 0:01211 //kprintf("ST0: 0x%x - ",valor);01212 //kprintf(" IC = 0x%x (%s)\n", (valor&0xc0) >> 6, ic_codes[ (valor&0xc0) >> 6 ]);01213 //kprintf(" SE = 0x%x (Seek end %s)\n", (valor&0x20)>>5, ( ( (valor&0x20) >> 5) == 0 ? "erroneo" : "ok") );01214 //kprintf(" EC = 0x%x (Equipment Check)\n", (valor&0x10)>>4);01215 //kprintf(" H = 0x%x (Head Address)\n", (valor&0x4)>>2);01216 //kprintf(" DS = 0x%x (Drive Select)\n", valor&0x3);01217 break;01218 01219 case 1:01220 puts("ST1:");01221 //kprintf(" EN = 0x%x (End of cylinder)\n", (valor&0x80)>>7);01222 //kprintf(" DE = 0x%x (Data error - CRC)\n", (valor&0x20)>>5);01223 //kprintf(" OR = 0x%x (Overrun / Underrun)\n", (valor&0x10)>>4);01224 //kprintf(" ND = 0x%x (No Data)\n", (valor&0x4)>>2);01225 //kprintf(" NW = 0x%x (Not Writable)\n", (valor&0x2)>>1);

Page 167: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

01226 //kprintf(" MA = 0x%x (Missing Address Mark)\n", valor&0x1);01227 break;01228 01229 case 2:01230 puts("ST2:");01231 //kprintf(" CM = 0x%x (Control Mark)\n", (valor&0x40)>>6);01232 //kprintf(" DD = 0x%x (Data Error in data field)\n", (valor&0x20)>>5);01233 //kprintf(" WC = 0x%x (Wrong Cylinder)\n", (valor&0x10)>>4);01234 //kprintf(" BC = 0x%x (Bad cylinder)\n", (valor&0x2)>>1);01235 //kprintf(" MD = 0x%x (Missing data address mark)\n", valor&0x1);01236 break;01237 01238 case 3:01239 puts("ST3:");01240 //kprintf(" WP = 0x%x (Write Protect)\n", (valor&0x40)>>6);01241 //kprintf(" T0 = 0x%x (Track 0)\n", (valor&0x10)>>4);01242 //kprintf(" HD = 0x%x (Head Address)\n", (valor&0x4)>>2);01243 //kprintf(" DS = 0x%x (Drive Select)\n", valor&0x3);01244 break;01245 01246 01247 01248 }01249 01250 01251 }01252 01253 01254 01255 // Rutinas de atencion de interrupcion01256 01257 // Bloqueo01258 void Floppy (void)01259 {01260 // Fin de interrupcion01261 endOfInterrupt();01262 01263 // Forma vieja01264 if ( func == NULL ) {01265 floppy_continuar=1;01266 }01267 01268 // Forma nueva01269 else {01270 (*func)();01271 }01272 01273 } 01274 01275 01276 // Procesa los pedidos en el buffer cache01277 void floppy_procesar_buffer(void)

Page 168: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

01278 {01279 01280 // Estamos procesando algun otro pedido ?01281 if ( ACTUAL_REQUEST != NULL )01282 return;01283 01284 01285 // Oks, veamos si hay algun pedido para nosotros01286 if ( (ACTUAL_REQUEST=getrequest(fd0)) == NULL )01287 return;01288 01289 //kprintf("\nHay un bloque nuevo para procesar: 0x%x !!!\n",ACTUAL_REQUEST);01290 01291 leer_escribir_new();01292 }

Page 169: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

floppy.h

00001 /* floppy.h */00002 00003 #ifndef __SYSTEM00004 #include "routix/system.h"00005 #endif00006 00007 00008 // defines generales00009 #define SENDBYTE_TIMEOUT 100000000010 #define GETBYTE_TIMEOUT 100000000011 00013 // Valores de errores00015 00016 //#define OK 000017 #define ERR_TIMEOUT -100018 #define ERR_NEED_RESET -200019 #define ERR_MAX_TRYS -300020 #define NO_VALIDO -10000021 00023 // Registros del controlador de floppy 8207700025 #define BASE 0x3f000026 #define SRA BASE00027 #define SRB BASE+100028 #define DOR BASE+200029 #define MSR BASE+400030 #define DSR BASE+400031 #define DATA BASE+500032 #define DIR BASE+700033 #define CCR BASE+700034 00035 00036 // Digital Output Register (DOR)00037 #define MOTD 1<<7 | 400038 #define MOTC 1<<6 | 400039 #define MOTB 1<<5 | 400040 #define MOTA 1<<4 | 400041 #define DMA 1<<3 | 400042 #define DMA_INT DMA00043 #define RESET 000044 #define DRIVE_0 000045 #define DRIVE_1 100046 #define DRIVE_2 200047 #define DRIVE_3 300048 00050 // Valores de los bits del Main Status Register (MSR)00052 #define RQM 1<<700053 #define DIO 1<<600054 #define NONDMA 1<<500055 #define CMDBUSY 1<<400056 #define DRV3BUSY 1<<300057 #define DRV2BUSY 1<<200058 #define DRV1BUSY 1<<100059 #define DRV0BUSY 1<<000060 00061 00062 // Configuration Control Register (CCR)00063 #define DR_1MBPS 300064 #define DR_500KBPS 000065 #define DR_300KBPS 1

Page 170: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00066 #define DR_250KBPS 200067 00068 // Datarate Select Register (DSR)00069 #define DSR_RESET 1<<700070 #define DSR_POWERDOWN 1<<600071 00072 00074 // Comandos00076 #define SENSE_INTERRUPT_STATUS 0x800077 00078 // CONFIGURE - son dos bytes que se deben enviar00079 #define CONFIGURE_0 0x1300080 #define CONFIGURE_1 000081 00082 // Opciones de CONFIGURE00083 #define CONF_EIS 1<<600084 #define CONF_EFIFO 1<<500085 #define CONF_POLL 1<<400086 00087 // SPECIFY00088 #define SPECIFY 0x300089 00090 // RECALIBRATE00091 #define RECALIBRATE 0x700092 00093 // READ SECTOR ID00094 #define READ_SECTOR_ID 0x4a00095 00096 // READ SECTOR00097 #define READ_SECTOR 0Xe6 // MT=1 MFM=1 SK=100098 00099 // WRITE SECTOR00100 #define WRITE_SECTOR 0x000101 00102 // SEEK00103 #define SEEK 0xf00104 00105 00107 //Definiciones relacionadas a la fase de resultados00109 #define ST0_IC_OK (0x0 << 6)00110 #define ST0_IC_ABNORMAL (0x1 << 6)00111 #define ST0_IC_NOT_EXIST (0x2 << 6)00112 #define ST0_IC_ABNORMAL_POLL (0x3 << 6)00113 #define ST0_SEEK (0x1 << 5)00114 #define ST0_NOT_READY (0x1 << 3)00115 #define ST0_HEAD00116 #define ST0_DRIVE_A 0x000117 #define ST0_DRIVE_B 0x100118 #define ST0_DRIVE_C 0x200119 #define ST0_DRIVE_D 0x300120 00121 // Verifica el contenido de los bits IC del ST000122 #define COMMAND_OK ( ! (ST0&0xc0 == ST0_IC_OK ) )00123 00124 00125 #define BLOQUE_SIZE 51200126 00127 void set_dor(word valor);00128 00129 00131 // Definiciones de DMA

Page 171: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00133 00134 #define DMA_MASK 0xA00135 #define DMA_CMD 0xB00136 #define DMA_CH2_PAGE 0x8100137 #define DMA_CH2_ADDR 0x400138 #define DMA_CH2_COUNT 0x500139 #define DMA_READ 0x46 // Floppy --> mem00140 #define DMA_WRITE 0x4A // mem --> floppy00141 00142 /* Inicializa el Canal 2 del DMA (usado para transferencias del floppy */00143 void init_floppy_DMA (byte);00144 00145 00147 // Definiciones del floppy00149 00150 #define SECTORES_POR_PISTA 1800151 #define CARAS_POR_PISTA 200152 #define MAX_FLOPPY_TRYS 1 // Cantidad maxima de intentos de lectura/escritura antes de tirar error00153 00154 int leer_escribir(byte operacion, dword sector_logico, byte *buffer);00155 00156 #define MOTOR_ON 100157 #define MOTOR_OFF 000158 00159 #define TIEMPO_APAGADO_MOTOR_POR_INACTIVIDAD 200000000160 #define TIEMPO_TIMEOUT_COMANDO 100000000161 #define TIME_WAIT_FOR_MOTOR_ON 50000000162

Page 172: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

init.c

00001 00006 #include "routix/system.h"00007 00008 00009 #define POSICION_LOADER 0xff800000 /* ubicacion del kernel.bin por parte del loader */00010 00011 00012 00013 extern void kmain (void); 00014 00015 00016 extern unsigned char _data_size;00017 extern unsigned char _code_size;00018 00019 00020 00021 void init(void)00022 {00023 char *origen, *destino; 00024 long i, largo;00025 00026 /* Copiar el kernel */00027 00028 destino = (char *) KERNEL_FCODE;00029 origen = (char *) POSICION_LOADER;00030 00031 00032 for(i=0 ; i < (long) &_code_size; i++)00033 *(destino+i) = *(origen+i);00034 00035 00036 __asm__ __volatile__ ("address_X: jmp (address_X - 0xff800000 + 5) ");00037 00038 00039 /* Copiar Datos */00040 00041 destino = (char *) KERNEL_FDATA;00042 origen = (char *) POSICION_LOADER + (long) &_code_size;00043 00044 largo= (long) &_data_size;00045 00046 for(i=0; i < largo ; i++)00047 *(destino+i) = *(origen+i);00048 00049 /* Una vez copiado todo en su lugar, saltamos a funcion ppal*/00050 kmain();00051 00052 }

Page 173: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

int.c

00001 /* int.c */00002 00003 #include "routix/paging.h"00004 #include "routix/segm.h"00005 #include "routix/8259.h"00006 #include "routix/debug.h"00007 #include "routix/kalloc.h"00008 #include <routix/kstdio.h>00009 00010 #include "drivers/fat.h"00011 00012 #ifndef __SYSTEM00013 #include "routix/system.h"00014 #endif00015 00016 #include "routix/event.h"00017 00018 00019 //extern byte floppy_continuar;00020 extern void intDefaultHandler(void);00021 extern void intTeclado(void);00022 extern void switch_to_kernel_mode(void);00023 extern void intProximaTarea(void);00024 extern void excepcion0(void);00025 extern void excepcion1(void);00026 extern void excepcion2(void);00027 extern void excepcion3(void);00028 extern void excepcion4(void);00029 extern void excepcion5(void);00030 extern void excepcion6(void);00031 extern void excepcion7(void);00032 extern void excepcion8(void);00033 extern void excepcion9(void);00034 extern void excepcion10(void);00035 extern void excepcion11(void);00036 extern void excepcion12(void);00037 extern void excepcion13(void);00038 extern void excepcion14(void);00039 extern void excepcion15(void);00040 extern void excepcion16(void);00041 extern void excepcion17(void);00042 extern void excepcion18(void);00043 extern void excepcion19(void);00044 00045 pd_t *directorio = (pd_t *) POSICION_DIR_PAGINAS;00046 00047 void DefaultHandler(void)00048 {00049 // putchar('I');00050 // putchar('\n');00051 //continuar=1;00052 endOfInterrupt();00053 }00054 00055 00056 void ExcepcionHandler(int numero,dword err1, dword err2, dword err3)00057 {00058 char *excepciones[] = { "Divide error",

Page 174: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00059 "Debug",00060 "NMI Interrupt",00061 "Breakpoing",00062 "Overflow",00063 "Bound range exceeded",00064 "Invalid opcode",00065 "Device not available",00066 "Double fault",00067 "Coprocessor segment overrun",00068 "Invalid TSS",00069 "Segment not present",00070 "Stack Fault",00071 "General Protection",00072 "Page Fault",00073 "",00074 "x87 FPU floating point error",00075 "Alignment check",00076 "Machine check",00077 "SIMD floating point" };00078 00079 /* if (numero==14) {00080 kprintf("\nSegmentation Fault\n");00081 sys_exit(-1);00082 }00083 */ 00084 00085 kprintf("\n EXCEPCION %d - %s\n",numero,excepciones[numero]);00086 kprintf(" Error 1: 0x%x\n",err1);00087 kprintf(" Error 2: 0x%x\n",err2);00088 kprintf(" Error 3: 0x%x\n",err3);00089 kprintf("Deteniendo el sistema.");00090 00091 while(1);00092 }00093 00094 /*00095 #define TECLADO_BUFFER_SIZE 1000096 #define TECLADO_PORT 0x6000097 00098 unsigned char bufferTeclado[TECLADO_BUFFER_SIZE];00099 unsigned char *ptrbufferTeclado=bufferTeclado;00100 00101 unsigned char Keyboard_Controller[] =00102 {00103 0, 0, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 225, 39, '\b',00104 0, 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', 129, '+', '\n',00105 0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 148, 132, '^', 0, '#',00106 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0,00107 '*', 0, ' ', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '-',00108 0, 0, 0, '+', 0, 0, 0, 0, 0, 0, 0, '<', 0, 000109 };00110 00111 00112 void Teclado(void) {00113 00114 char valor;00115

Page 175: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00116 endOfInterrupt();00117 00118 valor=inportb(TECLADO_PORT);00119 00120 if ( ptrbufferTeclado >= bufferTeclado+TECLADO_BUFFER_SIZE ) {00121 // Buffer lleno00122 }00123 00124 else if ( valor & 0x80 ) {00125 // Es un break code00126 // por ahora no hacemos nada00127 return;00128 }00129 00130 else {00131 *ptrbufferTeclado++ = Keyboard_Controller[valor];00132 }00133 00134 // Actualizamos los eventos de TECLADO00135 actualizar_eventos( TECLADO );00136 00137 }00138 */00139 /* Esto va ahora en el archivo drivers/floppy.c00140 void Floppy (void)00141 {00142 continuar=1;00143 endOfInterrupt();00144 } 00145 */00146 00147 00148 void inicializarInterrupciones( void )00149 {00150 pt_t *ptIDT;00151 descriptor_t *paginaIDT;00152 idtr_t *idtr_so;00153 page_index_t pi;00154 00155 00156 00157 paginaIDT = (descriptor_t *) kmalloc_page();00158 ptIDT = (pt_t *) kmalloc_page();00159 00160 //directorio->entry[513] = make_pde(1,1,0,0,0,0,0,0,(char *) ptIDT);00161 00162 pi = get_page_index( (addr_t) KERNEL_INTERRUPT );00163 00164 kprintf("Entrada de pagina de interrupciones: %x\n", ptIDT);00165 kprintf("Interrupciones: %x (real) - %x (virtual)\n", paginaIDT, KERNEL_INTERRUPT );00166 kprintf("Indice de directorio y tabla: %d - %d\n", pi.dir_index, pi.tabla_index);00167 00168 directorio->entry[ pi.dir_index ] = make_pde((addr_t) ptIDT, PAGE_RW | PAGE_PRES );00169 ptIDT->entry[ pi.tabla_index ] = make_pte((addr_t) paginaIDT, PAGE_PRES);00170 00171 int i;

Page 176: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00172 descriptor_t *temp;00173 00174 00175 for (i=0,temp = paginaIDT; i<256; i++,temp++)00176 *temp = make_int_gate( (word) DESC_CODE, (dword) intDefaultHandler, (byte) (PRESENTE | DPL_0) );00177 00178 // Manejo de excepciones00179 #define excepcion(numero,nombre) *(paginaIDT+numero) = make_int_gate( (word) DESC_CODE, (dword) nombre, (byte) (PRESENTE | DPL_0) );00180 00181 excepcion(0,excepcion0);00182 excepcion(1,excepcion1);00183 excepcion(2,excepcion2);00184 excepcion(3,excepcion3);00185 excepcion(4,excepcion4);00186 excepcion(5,excepcion5);00187 excepcion(6,excepcion6);00188 excepcion(7,excepcion7);00189 excepcion(8,excepcion8);00190 excepcion(9,excepcion9);00191 excepcion(10,excepcion10);00192 excepcion(11,excepcion11);00193 excepcion(12,excepcion12);00194 excepcion(13,excepcion13);00195 excepcion(14,excepcion14);00196 excepcion(15,excepcion15);00197 excepcion(16,excepcion16);00198 excepcion(17,excepcion17);00199 excepcion(18,excepcion18);00200 excepcion(19,excepcion19);00201 00202 //*(paginaIDT+0x20) = make_task_gate( (word) DESC_TSS0, (byte) (PRESENTE | DPL_0) );00203 *(paginaIDT+0x20) = make_int_gate( (word) DESC_CODE, (dword) switch_to_kernel_mode, (byte) (PRESENTE | DPL_0) );00204 *(paginaIDT+0x21) = make_int_gate( (word) DESC_CODE, (dword) intTeclado, (byte) (PRESENTE | DPL_0) );00205 00206 extern void intFloppy(void);00207 *(paginaIDT+0x26) = make_int_gate( (word) DESC_CODE, (dword) intFloppy, (byte) (PRESENTE | DPL_0) );00208 00209 // Entrada desde el modo usuario00210 extern void intSysCall(void);00211 *(paginaIDT+0x50) = make_trap_gate( (word) DESC_CODE, (dword) intSysCall, (byte) (PRESENTE | DPL_3) );00212 00213 // Switch de proceso, utilizado cuando un proceso pasa al estado TASK_STOPPED00214 *(paginaIDT+0x51) = make_int_gate( (word) DESC_CODE, (dword) intProximaTarea, (byte) (PRESENTE | DPL_0) );00215 00216 idtr_so = (idtr_t *) (paginaIDT+256);00217 00218 idtr_so->limite = 256*8 - 1;00219 idtr_so->base = (dword) paginaIDT;00220 00221 00222

Page 177: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00223 _lidt(idtr_so);00224 00225 }00226

Page 178: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

io.c

00001 /* io.c */00002 00003 #include "routix/system.h"00004 00005 00006 unsigned char inportb(word puerto )00007 {00008 unsigned char valor;00009 00010 __asm__ __volatile__("inb %w1,%b0" : "=a" (valor) : "d" (puerto) );00011 return valor;00012 }00013 00014 void outportb (word puerto, unsigned char dato)00015 {00016 __asm__ __volatile__("outb %b0,%w1" : : "a" (dato), "d" (puerto) );00017 }00018 00019 00020 00021 unsigned char inportb_p(word puerto )00022 {00023 unsigned char valor;00024 00025 __asm__ __volatile__("inb %w1,%b0\n\tnop" : "=a" (valor) : "d" (puerto) );00026 return valor;00027 }00028 00029 void outportb_p (word puerto, unsigned char dato)00030 {00031 __asm__ __volatile__("outb %b0,%w1\n\tnop" : : "a" (dato), "d" (puerto) );00032 }

Page 179: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

kalloc.c

00001 00007 #ifndef __SYSTEM00008 #include "routix/system.h"00009 #endif00010 #include <routix/kstdio.h>00011 #include "routix/kalloc.h"00012 #include "routix/task.h"00013 #include "error.h"00014 #include "routix/debug.h"00015 #include "routix/paging.h"00016 00017 #include "routix/misc.h"00018 00019 addr_t *_inicio,*_fin,*_sp;00020 00021 00022 /*00023 *00024 *00025 * _inicio -> |---------------|00026 * | |00027 * | |00028 * | |00029 * _sp -> |xxxxxxxxxxxxxxx|00030 * | |00031 * | |00032 * _fin -> |---------------|00033 *00034 * */00035 00036 00038 int kmalloc_page_start (addr_t *inicio, addr_t *fin)00039 {00040 _inicio = inicio;00041 _fin = fin;00042 _sp = fin;00043 return OK;00044 }00045 00047 int kfree_page(addr_t direccion)00048 {00049 if ( _sp < _inicio ) { return NULL; }00050 if (getvar("mmdebug")==1)00051 kprintf("KFREE: 0x%x\n", direccion);00052 *_sp-- = direccion;00053 00054 return 1;00055 }00056 00057 00058 addr_t kmalloc_page()00059 {00060 return get_free_page();00061 }00062 00066 addr_t get_free_page()00067 {00068 00069 addr_t direccion;

Page 180: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00070 00071 if ( _sp > _fin ) { return NULL; }00072 00073 _sp++;00074 direccion = *_sp;00075 00076 if (getvar("mmdebug")==1)00077 kprintf("KMALLOC: _inicio=0x%x _fin=0x%x _sp=0x%x - valor: %x\n",_inicio,_fin,_sp,direccion);00078 00079 return direccion;00080 }00081 00082 00087 void print_free_pages(word cant)00088 {00089 word i;00090 for(i=0 ; i<cant ; i++)00091 kprintf("Direccion: %x\n", *(_sp+i));00092 } 00093 00094 00095 00100 void inicializacion_kmalloc(int memoria_fisica, int memoria_kernel)00101 {00102 00103 int memoria_libre;00104 int mm_stack_size,paginas;00105 int pagina,pag;00106 00107 memoria_libre = memoria_fisica - memoria_kernel / 0x100000;00108 00109 kprintf("Memoria: \tInstalada %d Mb\tKernel %d Mb\tLibre %d Mb\n",memoria_fisica, memoria_kernel/0x100000,memoria_libre);00110 00111 paginas = 1024*1024*memoria_libre / 4096;00112 mm_stack_size = 4 * paginas;00113 00114 kprintf("El tamanio del stack de kmalloc_page para %d paginas es %d bytes - ",paginas,mm_stack_size);00115 kprintf("Inicio: 0x%x - Fin: 0x%x\n",memoria_kernel, memoria_kernel + mm_stack_size);00116 00117 00118 kmalloc_page_start( (dword *) memoria_kernel, (dword *) ( memoria_kernel + mm_stack_size ) );00119 00120 /* Determinamos la primer pagina de memoria libre */00121 pagina = memoria_kernel + mm_stack_size;00122 00123 if ( pagina & 0xfff ) {00124 pagina += 0x1000 - ( pagina & 0xfff );00125 }00126 else {00127 pagina = 0x1000 + pagina;00128 }00129 00130 00131 for( pag=((memoria_fisica*1024*1024)&0xfffff000)-4096 ; pag >= pagina ; pag -= 0x1000 ) {

Page 181: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00132 if ( kfree_page( (dword) pag ) == NULL ) { puts("error\n"); }00133 }00134 00135 00136 }00137 00139 inline dword kmem_free (void)00140 {00141 return (_fin - _sp);00142 } 00143 00144 00145 00146 00153 struct user_page *umalloc_page ( word flags, addr_t vdir, addr_t cr3)00154 {00155 addr_t aux = get_free_page();00156 if (!aux) {00157 actual->err_no = ENOMEM;00158 return NULL;00159 }00160 // Deberia mapear segun los flags que recibo00161 if (kmapmem( aux , vdir , cr3 , PAGE_PRES|PAGE_USER|PAGE_RW) !=OK) {00162 kprintf("umalloc_page: KMAPMEM error...\n");00163 return NULL;00164 }00165 00166 struct user_page *mem = (struct user_page *) malloc (sizeof(struct user_page));00167 // DEBUG00168 umalloc_alloc++;00169 // 00170 if (!mem) {00171 kfree_page (aux);00172 actual->err_no = ENOMEM;00173 return NULL;00174 }00175 mem->dir = aux;00176 mem->vdir = vdir;00177 mem->flags = flags;00178 mem->count = 1;00179 mem->next = NULL; 00180 return mem; 00181 }00182 00186 struct user_page *ufree_page (struct user_page *aux)00187 {00188 aux->count--; // Un proceso menos que refiere a esta pagina00189 if (aux->count > 0) // Si alguien sigue utilizandola, me voy00190 return aux;00191 00192 if (aux->dir) // Si no, la libero00193 kfree_page(aux->dir);00194 00195 // DEBUG00196 umalloc_free++;

Page 183: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

kalloc.h

00001 /* kalloc.h */00002 00003 #ifndef __SYSTEM00004 #include "routix/system.h"00005 #endif00006 00007 dword kmem_free (void);00008 addr_t get_free_page(void);00009 addr_t kmalloc_page(void);00010 int kfree_page(addr_t direccion);00011 00012 struct user_page *umalloc_page ( word flags, addr_t vdir, addr_t cr3);00013 struct user_page *ufree_page (struct user_page *aux);00014 00015 void *malloc (unsigned nbytes);00016 void free (void *);00017 00018 void inicializacion_kmalloc(int memoria_fisica, int memoria_kernel);

Page 184: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

kmain.c

00001 00006 #include "routix/system.h"00007 #include "routix/paging.h"00008 #include "routix/segm.h"00009 #include "routix/debug.h"00010 #include "routix/8259.h"00011 #include "routix/8254.h"00012 00013 #include "routix/task.h"00014 #include "drivers/fat.h"00015 #include "routix/kalloc.h"00016 #include "routix/syscalls.h"00017 #include <routix/kstdio.h>00018 #include "fs/blockcache.h"00019 00020 // Puntero a pagina de wrappers de usuario00021 addr_t *exit_addr;00022 void init_MM_base(void);00023 void init_MM (void);00024 void init_all_memory (dword memoria);00025 dword contar_memoria (void);00026 00027 void inicializarInterrupciones (void);00028 void start_scheduler (void);00029 void floppy_cache_init (void);00030 void entrada_de_inicio (void);00031 void init_time (void);00032 00033 void init_var (void);00034 00035 00036 void kmain (void)00037 {00038 /* Deshabilitamos todas las interrupciones */00039 mascarasPics(0xff,0xff);00040 00041 init_MM();00042 00043 /* Seguimos la ejecución en la dirección virtual */00044 __asm__("aca: jmp aca+5+0xc0000000");00045 00046 /* Acomodamos el stack pointer a su valor virtual00047 * 0x200000 es el TOP FISICO del STACK00048 * 0xd8000000 es el TOP VIRTUAL del STACK */00049 __asm__ __volatile__ ("movl $0x200000, %%eax\n\t" \00050 "subl %%esp, %%eax\n\t" \00051 "movl %%eax, %%esp\n\t" \00052 "movl $0xd8000000,%%eax\n\t" \00053 "subl %%esp, %%eax\n\t"00054 "movl %%eax, %%esp" : : : "eax" );00055 00056 00057 clrscr();00058 puts("Inicializando kernel....\n");00059 00060 puts("Inicializando Controladores Programables de Interrupciones...\n");00061 inicializarPics(0x20,0x28);00062

Page 185: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00063 puts("Kmalloc Inicializando...\n");00064 kprintf("Memoria fisica %d Megabytes\n",memoria);00065 00066 inicializacion_kmalloc(memoria, KERNEL_END );00067 puts("Kmalloc Inicializacion completa\n");00068 00069 /* Mapea linealmente el resto de la memoria fisica (a partir de los 4Mb en adelante) */00070 init_all_memory(memoria);00071 00072 00073 puts("Inicializando interrupciones\n");00074 inicializarInterrupciones();00075 00076 puts("Inicializando 8254\n");00077 init_8254();00078 00079 puts("Inicializando Rejoj\n");00080 init_time();00081 00082 // Inicialización del cache de bloques00083 start_block_cache(memoria);00084 00085 // Ubicar un directorio de páginas para las tareas en modo kernel00086 USER_PDT = kmalloc_page();00087 copy_page ((void *)USER_PDT, (void *)KERNEL_PDT);00088 unsigned long *puntero = (unsigned long *)USER_PDT;00089 int i;00090 // A los 2 primeros GB de memoria los pongo como Supervisor Only00091 for (i=0 ; i<PAGINA_SIZE ; i++)00092 puntero[i] = puntero[i] & 0xfffffffb;00093 00094 00095 // Inicialización del scheduler00096 puts("Inicializando el scheduler\n");00097 start_scheduler();00098 00099 /*00100 extern dev_fat_t dev_fat[1]; //Estructura para dispositivos con fs FAT00101 dev_fat[0].boot_leido = FALSE; 00102 dev_fat[0].fat_levantada = FALSE;00103 floppy_cache_init();00104 */00105 00106 kprintf("Task Struct Size: %d\n", sizeof(task_struct_t));00107 00108 // Habilitamos solo teclado, timertick y floppy00109 enable_irq(0);00110 enable_irq(1);00111 enable_irq(6);00112 00113 // Inicializar variables USER-KERNEL (moemntaneas) definidas en sysmisc.c00114 init_var();00115 00116 00117

Page 186: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00118 entrada_de_inicio();00119 00120 }00121

Page 187: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

kstdio.h

00001 00004 #include <sys/types.h>00005 00006 int putchar ( int );00007 int puts ( const char *);00008 byte *nextpos ( byte *);00009 void clrscr (void);00010 void scroll_up ( void );00011 unsigned char *gotoxy ( int , int );00012 char getascii_v ( char ); // Getascii para video00013 char *gets(char *s);00014 void printn( unsigned int num, int base);00015 int atoi(const char *str);00016 00017 unsigned char inportb (word puerto);00018 void outportb (word puerto, unsigned char dato);00019 unsigned char inportb_p (word puerto);00020 void outportb_p (word puerto, unsigned char dato);00021 00022 inline unsigned int get_vector_elements (char **p);

Page 188: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

libk.c

00001 /* libk.c */00002 00003 /* Aca van todas las funciones que inician la llamada al sistema. Usadas, por ejemplo, por INIT */00004 00005 #include "routix/system.h"00006 #include "routix/time.h"00007 #include "routix/paging.h"00008 #include "routix/task.h"00009 #include "sys/syscalls.h"00010 #include "routix/syscalls.h"00011 #include <routix/kstdio.h>00012 00013 #include <stdarg.h>00014 00015 // Constantes00016 #define HEXADECIMAL 1600017 00018 // Macros00019 #define PRINTn(num,base,padding) (printn_all(num,base,padding,0));00020 00021 00022 int exec (char *);00023 char getascii_video (char c);00024 void printn( unsigned int num, int base);00025 void printn_all( unsigned int num, int base, unsigned int padding,unsigned int anidamiento);00026 00027 00028 00029 int execve (char *tarea, char **argv, char **envp)00030 {00031 int retorno;00032 _syscall3(SYS_PROCESS | SYS_EXECVE, retorno, tarea, argv, envp);00033 00034 return retorno;00035 } 00036 00037 00038 void kprintf ( char *string, ...)00039 {00040 char *p=string;00041 char *d;00042 char car;00043 00044 unsigned int i;00045 long long int lli;00046 int padding;00047 00048 va_list argumentos;00049 00050 va_start(argumentos, string );00051 00052 for ( p=string; *p ; p++ ) {00053 if ( *p != '%' ) {00054 putchar(*p);00055 continue;

Page 189: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00056 }00057 00058 switch (*++p) {00059 00060 case 'c':00061 car=va_arg(argumentos, int); 00062 putchar( (char) car);00063 break;00064 00065 case 'x':00066 i = va_arg(argumentos, unsigned int );00067 printn(i,16);00068 break;00069 00070 00071 case 'd':00072 i = va_arg(argumentos, int);00073 if (i > (0xffffffff/2) ) {00074 putchar('-');00075 printn(~i+1,10);00076 break;00077 }00078 printn(i,10);00079 break;00080 00081 case 'u':00082 i = va_arg(argumentos, unsigned int);00083 printn(i,10);00084 break;00085 00086 case 'o':00087 i = va_arg(argumentos, unsigned int);00088 printn(i,8);00089 break; 00090 00091 case 's':00092 d = va_arg(argumentos, char *);00093 puts(d);00094 break;00095 00096 00097 // Tenemos el caso de querer imprimir un long long (8 bytes = 64bits)00098 // para ello tenemos que pensar que dado un número, por ej.:00099 // 2217 = 0x08A9 = 10001010100100100 // supongamos a modo de análisis que tenemos que imprimir estos 2 bytes y00101 // que nuestra capacidad de manejo (en registros) es de 1 byte.00102 // El MSB= 0x08 = 800103 // y LSB=0xA9 = 16900104 // mientras que deberíamos leer:00105 // MSB = 22 = 0x16 00106 // LSB = 17 = 0x1100107 //00108 // MSB = 0x08 --> 0x16 => dif = 0x16 - 0x08 = 0x0e00109 // LSB = 0xa9 --> 0x11 => dif = 0x11 - 0xa9 = neg 00110 //

Page 190: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00111 // Otro ejemplo:00112 // 3598 = 0x0E0E = 11100000111000113 //00114 // MSB = 0x0E --> 0x35 => dif = 0x35 - 0x0e = 0x2700115 // LSB = 0x0E --> 0x98 => dif = 0x98 - 0x0e = 0x8a00116 // 00117 // Por ahora no encuentro una forma sencilla de imprimir números long long00118 // en decimal, realizamos la implementación en hexa.00119 // 00120 case 'l':00121 00122 if ( *++p != 'l' )00123 break;00124 00125 switch ( *++p ) {00126 00127 case 'x':00128 lli = va_arg(argumentos, long long int);00129 00130 // Si los 4 bytes más significativos no son nulos el debemos agregar00131 // ceros en el menos significativo00132 if ( lli>>32 )00133 padding=8;00134 00135 // Si los 4 bytes más significativos son nulos no importa el padding, 00136 // pero lo colocamos en 1 para que cuando sea 0 imprima por lo menos00137 // ese caracter 00138 else00139 padding=1;00140 00141 PRINTn( (unsigned int) (lli>>32), HEXADECIMAL, 0);00142 PRINTn( (unsigned int) lli, HEXADECIMAL, padding);00143 break;00144 00145 }00146 00147 break;00148 00149 00150 00151 default:00152 putchar(*p);00153 break;00154 00155 }00156 00157 }00158 00159 va_end(argumentos);00160 }

Page 191: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00161 00162 void printn( unsigned int num, int base)00163 {00164 unsigned int div;00165 if ( (div=num/base) ) printn(div,base);00166 putchar( getascii_video(num%base) );00167 }00168 00169 00170 char getascii_video ( char c )00171 {00172 char valor = '0' + c;00173 00174 if ( valor > '9' ) valor += 7;00175 return valor;00176 }00177 00179 inline unsigned int get_vector_elements (char **p)00180 {00181 unsigned long i;00182 for ( ; *(p+i) ; i++);00183 return i;00184 }00185 00186 /* Permite imprimir un entero con padding00187 *00188 * function printn_all(numero, base, padding, anidamiento)00189 *00190 * division = numero/base;00191 * resto = numero%base;00192 *00193 * * Con resto levantamos el último dígito, ya que la división puede ser00194 * * nula, ej.: 7/16 = 0 pero 7%16 = 700195 * if ( division || resto ) {00196 * printn_all(division,base,padding,anidamiento+1)00197 * imprimir el caracter numero%base;00198 * }00199 *00200 * else {00201 * while( padding-- > anidamiento )00202 * imprimir el caracter '0'00203 * }00204 *00205 */ 00206 void printn_all( unsigned int num, int base, unsigned int padding,unsigned int anidamiento)00207 {00208 unsigned int div;00209 00210 if ( (div=num/base) || (num%base) ) {00211 printn_all(div,base, padding, anidamiento+1 );00212 putchar( getascii_video(num%base) );00213 }00214 00215 else {00216 00217 while ( padding-- >anidamiento)00218 putchar( getascii_video(0) );00219 }00220

Page 192: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00221 }00222

Page 193: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

list.h

00001 00006 #ifndef __LIST00007 #define __LIST00008 00021 00022 #define ALLOCATE(type) ( (type *) malloc(sizeof(type)) )00023 00025 #define DEF_ALLOC(type, name) \00026 type *name; \00027 ( name = (type *) malloc(sizeof(type)) );00028 00029 00052 #define LIST_DATA(type) struct { struct type *next,*previous; }00053 00054 // Macros de uso interno00055 #define LIST_NEXT(list,node) ((node->list).next)00056 #define LIST_PREVIOUS(list,node) ((node->list).previous)00057 00058 #define HEADER_NEXT(header) ((header).next)00059 #define HEADER_PREVIOUS(header) ((header).previous)00060 00061 00067 #define LIST_NEW(type) \00068 struct { \00069 type *next; \00070 type *previous; \00071 }00072 00073 #define LIST_INITIALIZER {NULL,NULL}00074 00075 #define LIST_INIT(header) \00076 HEADER_NEXT(header)=NULL; \00077 HEADER_PREVIOUS(header)=NULL;00078 00079 00083 #define LIST_FIRST(header) \00084 HEADER_NEXT(header)00085 00088 #define LIST_TAIL(header) \00089 HEADER_PREVIOUS(header)00090 00091 00092 00097 #define LIST_EMPTY(header) \00098 ((HEADER_NEXT(header) && HEADER_PREVIOUS(header)) ? 0 : 1)00099 00100 00108 #define LIST_ADD(header,list,node) \00109 LIST_NEXT(list,node)=HEADER_NEXT(header); \00110 if ( HEADER_NEXT(header) != NULL) \00111 LIST_PREVIOUS( list, LIST_NEXT(list,node) )= node; \00112 else \

Page 194: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00113 HEADER_PREVIOUS(header)=node; \00114 LIST_PREVIOUS(list,node)=NULL; \00115 HEADER_NEXT(header)=node;00116 00117 00118 00124 #define LIST_ADD_TAIL(header,list,node) \00125 if ( HEADER_PREVIOUS(header) != NULL ) \00126 LIST_NEXT( list, HEADER_PREVIOUS(header) ) = node; \00127 else \00128 HEADER_NEXT(header) = node; \00129 LIST_NEXT(list,node) = NULL; \00130 LIST_PREVIOUS(list,node) = HEADER_PREVIOUS(header); \00131 HEADER_PREVIOUS(header) = node;00132 00133 00138 #define LIST_DEL(header,list,node) \00139 if ( LIST_PREVIOUS(list,node) != NULL ) \00140 LIST_NEXT( list, LIST_PREVIOUS(list,node) ) = LIST_NEXT(list,node); \00141 else \00142 HEADER_NEXT(header) = LIST_NEXT(list,node); \00143 if ( LIST_NEXT(list,node) != NULL ) \00144 LIST_PREVIOUS( list, LIST_NEXT(list,node) ) = LIST_PREVIOUS(list,node); \00145 else \00146 HEADER_PREVIOUS(header) = LIST_PREVIOUS(list,node);00147 00148 00159 #define LIST_FOREACH(var,header,list) \00160 for(var=HEADER_NEXT(header); var!=NULL; var=LIST_NEXT(list,var))00161 00162 00163 00164 /* \brief Simil LIST_FOREACH, pero se pueden remover los nodos que se recorren00165 * su utilizacion es un poco compleja (deben agregarse dos líneas de código para su correcto uso)00166 *00167 * _LIST_FOREACH(child, actual->childs, brothers) {00168 * aux = LIST_NEXT(brothers, child); // Agregado 100169 * if (child->estado == TASK_ZOMBIE)

Page 195: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00170 * pid = sys_waitpid(child->pid,&value,WNOHANG);00171 * child = aux; // Agregado 200172 * }00173 * \todo Implementarlo más limpiamente00174 */00175 #define _LIST_FOREACH(var,header,list) \00176 for(var=HEADER_NEXT(header); var!=NULL; )00177 00178 /* \brief Permite insertar un nodo antes de otro nodo determinado00179 * es importante que nodebefore sea un nodo válido, esto implica que00180 * no se permite que nodebefore sea NULL por ejemplo.00181 */00182 #define LIST_INSERT_BEFORE(header,list,nodebefore,node) \00183 LIST_PREVIOUS(list,node)=LIST_PREVIOUS(list,nodebefore); \00184 LIST_NEXT(list,node)=nodebefore; \00185 if ( HEADER_NEXT(header)==nodebefore ) \00186 HEADER_NEXT(header)=node; \00187 else \00188 LIST_NEXT(list,LIST_PREVIOUS(list,nodebefore))=node; \00189 LIST_PREVIOUS(list,nodebefore)=node;00190 00191 00192 00193 00202 #define LIST_FOREACH_REVERSE(var,header,list) \00203 for(var=HEADER_PREVIOUS(header); var!=NULL; var=LIST_PREVIOUS(list,var))00204 00205 00206 /* Permite buscar un nodo de la lista por un valor de00207 * un atributo particular.00208 * Recibe como argumentos la lista, la variable donde00209 * devuelve un puntero al nodo encontrado o NULL en caso00210 * de busqueda sin resultados, el siguiente argumento es00211 * el nombre de la variable a buscar (definida en la 00212 * estructura y por ultimo el valor buscado.00213 * ej:00214 * task_struct_t *nodobuscado;00215 * LIST_FIND(runqueue,nodobuscado,priority,3)00216 */00217 #define LIST_FIND(header,list,var,name,value) \00218 for(var=HEADER_NEXT(header); var!=NULL && var->name!=value; var=LIST_NEXT(list,var))00219 00220 00227 #define LIST_ATTACH(dest, src, type) \

Page 196: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00228 { type *aux; \00229 _LIST_FOREACH(ptr, src) { \00230 aux = LIST_NEXT(src,ptr); \00231 LIST_ADD_TAIL(dest,dest, ptr); \00232 ptr = aux; \00233 } \00234 }00235 00239 #define LIST_CLEAN(header) \00240 LIST_INIT(header);00241 00242 #define LIST_REPLACE(list, original, replace) \00243 LIST_NEXT(list, replace) = LIST_NEXT(list, original); \00244 LIST_PREVIOUS(list, replace) = LIST_PREVIOUS(list, original); \00245 if (LIST_NEXT(list, replace)) \00246 LIST_PREVIOUS(list,LIST_NEXT(list, replace)) = replace; \00247 if (LIST_PREVIOUS(list, replace)) \00248 LIST_NEXT(list,LIST_PREVIOUS(list, replace)) = replace;00249 00250 #endif

Page 197: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

misc.h

00001 /* misc.h */00002 00003 #ifndef __SYSTEM00004 #include "routix/system.h"00005 #endif00006 00007 00008 // Setea el valor de una variable visible desde el modo Kernel y User00009 int setvar(char *nombre, int valor);00010 // Devuelve el valor de una variable visible desde el modo Kernel y User00011 int getvar(char *nombre);00012 00013 // Wrappers que transforman las direccion de nombre del User al Kernel space00014 inline int sys_setvar(char *nombre, int valor);00015 inline int sys_getvar(char *nombre);00016 00017 int find_var(char *nombre);00018 int find_empty_var(void);00019 00020 void sys_read_debug(int sector);00021 00022

Page 198: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

mm.c

00001 00007 #include "routix/system.h"00008 #include "routix/paging.h"00009 #include "routix/segm.h"00010 #include "routix/kalloc.h"00011 #include "routix/task.h"00012 #include "routix/debug.h"00013 00014 addr_t KERNEL_PDT = POSICION_DIR_PAGINAS;00015 addr_t USER_PDT;00016 00017 void init_MM_base(void);00018 dword contar_memoria (void);00019 dword memoria;00020 00021 00027 void init_MM_base()00028 {00029 page_index_t indice;00030 pd_t *dir;00031 pt_t *tabla;00032 word i;00033 gdtr_t *gdtr;00034 descriptor_t *gdt;00035 00036 dir= (pd_t *) POSICION_DIR_PAGINAS;00037 00038 /* Mapear linealmente en Tabla 1 de 0-4MB (posicion fisica del kernel */00039 indice=get_page_index( 0 );00040 dir->entry[ indice.dir_index ]=make_pde (POSICION_TABLA_1, PAGE_PRES | PAGE_SUPER | PAGE_RW);00041 tabla = (pt_t *) (dir->entry[ indice.dir_index ] & 0xfffff000);00042 for(i=0 ; i < PAGINAS_POR_TABLA ; i++)00043 tabla->entry[i]= make_pte( i * PAGINA_SIZE, PAGE_PRES | PAGE_SUPER | PAGE_RW ) ;00044 00045 00046 /* Mapear El codigo de kernel en 3GB (0xC0000000) */00047 indice=get_page_index(KERNEL_CODE);00048 dir->entry[ indice.dir_index ]=make_pde (POSICION_TABLA_KCODE, PAGE_PRES | PAGE_SUPER | PAGE_RW);00049 tabla = (pt_t *) (dir->entry[ indice.dir_index ] & 0xfffff000);00050 for(i=0 ; i < PAGINAS_POR_TABLA ; i++)00051 tabla->entry[i]= make_pte( KERNEL_FCODE + (i * PAGINA_SIZE), PAGE_PRES | PAGE_SUPER | PAGE_RW ) ;00052 00053 00054 /* Mapear Los datos de kernel en 3GB + 128MB (0xC8000000) */00055 indice=get_page_index(KERNEL_DATA);00056 dir->entry[ indice.dir_index ]=make_pde (POSICION_TABLA_KDATA, PAGE_PRES | PAGE_SUPER | PAGE_RW);00057 tabla = (pt_t *) (dir->entry[ indice.dir_index ] & 0xfffff000);00058 for(i=0 ; i < PAGINAS_POR_TABLA ; i++)

Page 199: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00059 tabla->entry[i]= make_pte( KERNEL_FDATA + (i * PAGINA_SIZE), PAGE_PRES | PAGE_SUPER | PAGE_RW ) ;00060 00061 /* Mapear el stack de kernel en 3GB + 128MB + 128Mb + 128MB - 128Kb00062 * mapeamos desde el TOP 128Kb hacia arriba (32 páginas) */00063 00064 00065 indice=get_page_index(KERNEL_STACK_TOP - KERNEL_STACK_SIZE);00066 dir->entry[ indice.dir_index ]=make_pde (POSICION_TABLA_KSTACK, PAGE_PRES | PAGE_SUPER | PAGE_RW);00067 tabla = (pt_t *) (dir->entry[ indice.dir_index ] & 0xfffff000);00068 for(i=0 ; i < KERNEL_STACK_SIZE / PAGINA_SIZE; i++)00069 tabla->entry[i+indice.tabla_index]= make_pte( KERNEL_FSTACK + (i * PAGINA_SIZE), PAGE_PRES | PAGE_SUPER | PAGE_RW );00070 00071 00072 /* Cargamos ahora la gdt */00073 gdtr = (gdtr_t *) POSICION_TABLA_GDT;00074 gdt = (descriptor_t *) POSICION_TABLA_GDT;00075 00076 *gdt++ = make_descriptor( 0, 0, 0, 0);00077 *gdt++ = make_descriptor( 0, 0xfffff, PRESENTE | DPL_0 | GENERAL | CODIGO, GRANULARIDAD | DB);00078 *gdt++ = make_descriptor( 0, 0xfffff, PRESENTE | DPL_0 | GENERAL | DATA | WRITE, GRANULARIDAD | DB);00079 *gdt++ = make_descriptor( 0, 0xfffff, PRESENTE | DPL_3 | GENERAL | CODIGO, GRANULARIDAD | DB);00080 *gdt++ = make_descriptor( 0, 0xfffff, PRESENTE | DPL_3 | GENERAL | DATA | WRITE, GRANULARIDAD | DB);00081 *gdt++ = make_descriptor( (dword) &tss, sizeof(tss_t), PRESENTE | DPL_0 | SISTEMA | TSS_AVAILABLE, DB);00082 00083 gdtr->limite =(dword) gdt - (dword) POSICION_TABLA_GDT - 1;00084 gdtr->base =(dword) POSICION_TABLA_GDT;00085 00086 lgdt( gdtr );00087 00088 _set_ds(DESC_DATA);00089 _set_es(DESC_DATA);00090 _set_fs(DESC_DATA);00091 _set_gs(DESC_DATA);00092 00093 ltr(DESC_TSS0);00094 } 00095 00096 00097 void init_MM (void)00098 {00099 dword memoria_total=0;00100 00101 page_off(); /* Deshabililitar paginacion */00102 00103 memoria_total=contar_memoria(); /* Contar memoria total del sistema */00104

Page 200: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00105 /* Habilitar 1 Tabla de 0-4MB, otra con Kernel Code (0xC0000000) y otra con Kernel Data (0xC8000000) */00106 init_MM_base();00107 00108 load_cr3( POSICION_DIR_PAGINAS );00109 page_on();00110 00111 memoria = memoria_total;00112 }00113 00114 00115 #define STEP 0x1000000116 00117 dword contar_memoria (void)00118 { 00119 dword *dir = (dword *) 0x200000;00120 dword data = 0x12345678;00121 dword prev;00122 00123 prev = *dir;00124 *dir = data;00125 00126 while ( *dir == data) {00127 *dir = prev;00128 dir += STEP;00129 prev = *dir;00130 *dir = data;00131 }00132 00133 return ( (dword) dir / 0x100000 );00134 }00135 00136 00138 void init_all_memory( dword memoria ) {00139 00140 int i,j;00141 page_index_t indice;00142 pt_t *pt;00143 00144 pd_t *dir= (pd_t *) POSICION_DIR_PAGINAS;00145 00146 /* Mapear linealmente en el resto de la memoria00147 * desde los 4Mb en adelante */00148 for ( i=1; i < memoria/4 ; i++) {00149 00150 #if __VMDEBUG00151 kprintf("PDE Numero %d (0x%x)\n",i,i*PAGINA_SIZE*1024);00152 #endif00153 indice = get_page_index(i*PAGINA_SIZE*1024);00154 pt = (pt_t *) kmalloc_page();00155 00156 dir->entry[ indice.dir_index ] = make_pde((addr_t)pt, PAGE_PRES | PAGE_SUPER | PAGE_RW);00157 00158 for ( j=0; j < PAGINAS_POR_TABLA; j++) {00159 pt->entry[j] = make_pte( i*PAGINA_SIZE*1024 + j*PAGINA_SIZE, PAGE_PRES | PAGE_SUPER | PAGE_RW);00160 }00161

Page 201: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00162 }00163 00164 }00165

Page 202: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

paging.c

00001 00007 #include "routix/system.h"00008 #include "routix/paging.h"00009 #include "routix/debug.h"00010 #include <routix/kstdio.h>00011 #include "routix/kalloc.h"00012 00013 00014 00016 page_index_t get_page_index (addr_t p)00017 { 00018 page_index_t indice;00019 00020 indice.dir_index = p / ( PAGINA_SIZE * TABLAS_POR_DIR);00021 indice.tabla_index = (p % ( PAGINA_SIZE * TABLAS_POR_DIR)) / PAGINA_SIZE;00022 return indice;00023 }00024 00025 00027 void *convertir_direccion ( void *dir_logica, addr_t cr3 )00028 {00029 void *dir_fisica;00030 00031 page_index_t indice;00032 00033 // Obtener los indices del directorio y de la tabla de paginas para la direccion logica00034 indice = get_page_index ( (addr_t) dir_logica );00035 00036 pd_t *dir= (pd_t *) cr3;00037 // Obtener la direccion de la tabla correspondiente y enmascarar los 12 bits de atributos00038 pt_t *tabla = (pt_t *) (dir->entry[indice.dir_index] & 0xfffff000);00039 // Obtener la direccion fisica y enmascarar los 12 bits de atributos00040 dir_fisica = (void *) (tabla->entry[indice.tabla_index] & 0xfffff000);00041 00042 // Sumarle a la pagina obtenida de la tabla el offset de la direccion logica00043 dir_fisica = dir_fisica + ((dword) dir_logica & 0xfff);00044 00045 return dir_fisica;00046 } 00047 00048 00050 pde_t make_pde (addr_t direccion, word atributos)00051 { 00052 pde_t entrada;00053 entrada= atributos & 0xfff;00054 entrada= entrada | direccion;00055 00056 return entrada;00057 }00058 00060 pte_t make_pte (addr_t direccion, word atributos)00061 {

Page 203: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00062 pte_t entrada;00063 entrada= atributos & 0xfff;00064 entrada= entrada | direccion;00065 00066 return entrada;00067 }00068 00069 00070 00072 /* ej.:00073 * mem = kmalloc_page();00074 * if ( ! kmapmem( fisica, mem, 0xe0000000, PAGE_PRES ) )00075 * kfree_page(mem);00076 */00077 #define ERR_DIR_BUSY -100078 #define ERR_NO_ALIGN -200079 00080 #define ERR_DIR_EMPTY -500081 00089 int kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo)00090 {00091 page_index_t indice;00092 indice = get_page_index ( logica );00093 pd_t *dir;00094 pt_t *tabla;00095 word i;00096 00097 atributo = atributo & 0xfff;00098 00099 if ( (fisica & 0xfff) || (logica & 0xfff) ) {00100 if ( getvar("pagedebug")==1 )00101 kprintf("Debug Mode - Fis2log: las direcciones deben estar alineadas a 4KB\n");00102 return ERR_NO_ALIGN;00103 }00104 00105 if ( getvar("pagedebug")==1 ) {00106 kprintf("Kmapmem: Mapeando 0x%x en 0x%x\n", fisica, logica);00107 kprintf("Kmapmem: Indice DIR: %d Indice Tabla: %d\n", indice.dir_index, indice.tabla_index);00108 }00109 00110 dir= (pd_t *) directorio;00111 00112 if (dir->entry[indice.dir_index] == 0 ) {00113 if ( getvar("pagedebug")==1 )00114 kprintf("Kmapmem: Debe alocarse una nueva tabla de paginas\n");00115 00116 dir->entry[indice.dir_index]= (pde_t) make_pde ( kmalloc_page(), PAGE_PRES | PAGE_SUPER | PAGE_RW);00117 tabla = (pt_t *) (dir->entry[indice.dir_index] & 0xfffff000);00118 /* Poner todas las pte en 0 */00119 for (i=0; i < PAGINAS_POR_TABLA ; i++)00120 tabla->entry[i]=(pte_t) make_pte (0, 0);00121 }00122

Page 204: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00123 else { // Si la entrada existe, esa pagina puede ya estar asignada00124 00125 tabla = (pt_t *) (dir->entry[indice.dir_index] & 0xfffff000);00126 if (tabla->entry[indice.tabla_index]) {00127 if ( getvar("pagedebug")==1 )00128 kprintf("Kmapmem: Pagina ya en uso\n");00129 return ERR_DIR_BUSY;00130 }00131 }00132 00133 tabla->entry[indice.tabla_index]= (pte_t) make_pte ( fisica , atributo);00134 00135 return OK;00136 }00137 00144 int kunmapmem (addr_t logica, addr_t directorio)00145 {00146 if ( logica & 0xfff) {00147 if ( getvar("pagedebug")==1 )00148 kprintf("KunmapMem: la direccion debe estar alineada a 4KB\n");00149 return ERR_NO_ALIGN;00150 }00151 00152 00153 page_index_t indice;00154 indice = get_page_index ( logica );00155 00156 pd_t *dir = (pd_t *) directorio;00157 00158 pt_t *tabla = (pt_t *) (dir->entry[indice.dir_index] & 0xfffff000);00159 00160 00161 if ( !tabla ) { //Si la entrada correspondiente a "logica" esta vacia00162 if ( getvar("pagedebug")==1 )00163 kprintf("Debug Mode - KunmapMem: la tabla esta vacia\n");00164 return ERR_DIR_EMPTY;00165 }00166 00167 //Liberar la entrada correspondiente00168 tabla->entry[indice.tabla_index] = 0;00169 00170 00171 //Ahora verifico si todas las entradas de la tabla estan vacias. Si es asi la libero. Con que haya una00172 //ocupada, no puedo hacerlo00173 word i;00174 for ( i=0 ; i < PAGINAS_POR_TABLA ; i++)00175 if ( tabla->entry[i] )00176 return OK;00177 00178 if (getvar("pagedebug")==1)00179 kprintf("Kunmapmem: liberando tabla en: 0x%x\n", dir->entry[indice.dir_index] & 0xfffff000);

Page 205: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00180 kfree_page( (addr_t) (dir->entry[indice.dir_index] & 0xfffff000) ); 00181 dir->entry[indice.dir_index] = 0;00182 return OK;00183 00184 } 00185 00187 void *make_pdt (void)00188 {00189 addr_t nuevo_directorio = kmalloc_page();00190 if ( nuevo_directorio == 0) {00191 return NULL;00192 }00193 00194 copy_page( (void *) nuevo_directorio, (void *) USER_PDT);00195 return (void *) nuevo_directorio;00196 } 00197 00200 void *copy_page( void *dest, const void *src)00201 {00202 __asm__("push %%ecx; push %%edi ; push %%esi ;cld ; rep ; movsl ; pop %%esi ; pop %%edi ; pop %%ecx" \00203 : : "c" ((word) (PAGINA_SIZE / (sizeof(dword)))), "S" (src), "D" (dest));00204 00205 return dest;00206 }00207

Page 206: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

paging.h

00001 /* paging.h */00002 00003 #ifndef __SYSTEM00004 #include "routix/system.h"00005 #endif00006 00007 #ifndef __ROUTIX_PAGING00008 #define __ROUTIX_PAGING00009 00010 #define DIR_SIZE 409600011 #define TABLA_SIZE DIR_SIZE00012 #define PAGINA_SIZE 409600013 #define TABLAS_POR_DIR 102400014 #define PAGINAS_POR_TABLA 102400015 00016 #define POSICION_DIR_PAGINAS ( KERNEL_FSTACK_TOP - KERNEL_STACK_SIZE - DIR_SIZE)00017 #define POSICION_TABLA_1 ( POSICION_DIR_PAGINAS - DIR_SIZE)00018 #define POSICION_TABLA_KCODE ( POSICION_TABLA_1 - TABLA_SIZE )00019 #define POSICION_TABLA_KDATA ( POSICION_TABLA_KCODE - TABLA_SIZE )00020 #define POSICION_TABLA_KSTACK ( POSICION_TABLA_KDATA - TABLA_SIZE )00021 00022 //Tomamos 4Kb para la GDT 00023 #define POSICION_TABLA_GDT ( POSICION_TABLA_KSTACK - PAGINA_SIZE )00024 00025 00027 #define PAGE_RW 0X0200028 #define PAGE_PRES 0x0100029 #define PAGE_SUPER 1<<200030 #define PAGE_USER 1<<200031 /*00032 #define PAGE_USER 1<<200033 #define PAGE_SUPER PAGE_USER00034 */00035 00037 typedef dword pte_t;00039 typedef dword pde_t;00040 00041 typedef struct pd_t {00042 pde_t entry[1024];00043 } pd_t;00044 00045 typedef struct pt_t {00046 pte_t entry[1024];00047 } pt_t;00048 00050 typedef struct page_index_t00051 {00052 word dir_index;00053 word tabla_index;00054 } page_index_t;00055 00056 00058 page_index_t get_page_index (addr_t );

Page 207: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00059 00060 00061 /* Carga CR3 */00062 #define load_cr3(x) __asm__ ("movl %0, %%cr3" : : "r" (x) )00063 00064 /* Desactiva/Activa la paginacion */00065 #define page_off() __asm__ ("mov %cr0, %eax; and $0x7fffffff, %eax; mov %eax, %cr0")00066 #define page_on() __asm__ ("mov %cr0, %eax; or $0x80000000, %eax; mov %eax, %cr0")00067 00069 void *make_pdt (void);00070 00071 pde_t make_pde (addr_t direccion, word atributos);00072 pte_t make_pte (addr_t direccion, word atributos);00073 00075 void *copy_page (void *dest, const void *src);00076 00078 void *convertir_direccion ( void *dir_logica, addr_t cr3 );00079 00080 int kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo);00081 int kunmapmem (addr_t logica, addr_t directorio);00082 00084 #define ALINEAR_4(dir) (((long) dir) & 0xfffffffc)00085 00086 #define GET_OFFSET(dir) (((long) dir) & 0xfff)00087 00088 #endif

Page 208: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

pic.c

00001 /* pic.c */00002 00003 #include "routix/system.h"00004 #include "routix/8259.h"00005 #include <routix/kstdio.h>00006 00007 #define PIC1_A0 0x2000008 #define PIC1_A1 0x2100009 #define PIC2_A0 0xa000010 #define PIC2_A1 0xa100011 00012 void inicializarPics(unsigned char int1, unsigned char int2)00013 {00014 00015 // Inicializamos con ICW100016 outportb(PIC1_A0,0x11);00017 outportb(PIC2_A0,0x11);00018 00019 // Movemos las interrupciones (ICW2)00020 outportb(PIC1_A1,int1);00021 outportb(PIC2_A1,int2);00022 00023 // Seteamos la posicion del PIC slave (ICW3)00024 outportb(PIC1_A1,0x4);00025 outportb(PIC2_A1,0x2);00026 00027 // Otros seteos: EOI, modo 8086 (ICW4)00028 outportb(PIC1_A1,0x1);00029 outportb(PIC2_A1,0x1);00030 00031 // Deshabilitamos todas las interrupciones00032 outportb(PIC1_A1,0xff);00033 outportb(PIC2_A1,0xff);00034 00035 }00036 00037 00038 00039 void mascarasPics(unsigned char mask1, unsigned char mask2)00040 {00041 outportb(PIC1_A1,mask1);00042 outportb(PIC2_A1,mask2);00043 }00044 00045 00046 00047 void endOfInterrupt(void)00048 {00049 outportb(PIC1_A0,0x20);00050 }00051 00052 void enable_irq (byte irqn)00053 {00054 word picn= PIC1_A1;00055 if ( irqn > 7)00056 {00057 picn = PIC2_A1;00058 }00059 outportb (picn, inportb(picn ) & ~ ( 1 << irqn) );

Page 210: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

sched.c

00001 00006 #include <routix/system.h>00007 #include <routix/segm.h>00008 #include <routix/paging.h>00009 #include <routix/kalloc.h>00010 #include <routix/task.h>00011 #include <routix/debug.h>00012 #include <routix/kstdio.h>00013 #include <error.h>00014 #include <routix/syscalls.h>00015 #include <sys/list.h>00016 #include <string.h>00017 #include <routix/signal.h>00018 00019 void idle_task(void);00020 void tarea_init(void); //Tarea INIT00021 00022 // Puntero a la lista enlazada de tareas00023 task_struct_t *tareas_inicio=NULL;00024 00025 // Puntero a la tarea actual00026 task_struct_t *actual=NULL;00027 00028 // Cantidad de tareas activas00029 extern volatile int tareas_activas;00030 00031 00032 task_struct_t *init_task, *pre_init_task;00033 00034 void start_scheduler(void)00035 {00036 /* Por ahora usamos la memoria fisica directamente, total esta mapeada00037 * hasta que reubiquemos el codigo y datos de las tareas a una dirección00038 * virtual particular */00039 00040 // Inicializo el tss con valores nulos00041 inicializarTss(&tss, 0, 0, 0, 0, 0 ); 00042 00043 // Tarea fundamental del sistema ! INIT_TASK corre cuando no hay nada para correr00044 addr_t INIT_stack = kmalloc_page();00045 00046 00047 init_task=init_new_task(DESC_CODE, DESC_DATA, (dword) &tarea_init, INIT_stack + 4096, 0x202, "init", 50);00048 pre_init_task = init_task;00049 00050 00051 init_task->pid = 1;00052 // Init es padre e hijo (santisima trinidad)... para evitar problemas al hacer init->padre00053 init_task->padre = init_task;00054 // LIST_INIT(init_task->zombie_header);00055 00056 // Aloco la estructura de señales de init y la incializo (cuidado !!! esto NO ANDA !!!!!!!)00057 // TASK_SIGNALS_ALLOC (init_task);

Page 211: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00058 // TASK_SIGNALS_INIT (init_task);00059 00060 // Despertamos la nueva tarea, ya que recordemos init_new_task crea la nueva tarea en estado STOPPED00061 despertar_task(init_task);00062 00063 // La tarea en ejecución será init_task00064 actual = tareas_inicio;00065 00066 }00067 00068 00069 int execve (char *, char **, char **);00070 void tarea_init()00071 {00072 00073 // Inicializamos la fat00074 extern dev_fat_t dev_fat[1]; //Estructura para dispositivos con fs FAT00075 00076 dev_fat[0].boot_leido = FALSE; 00077 dev_fat[0].fat_levantada = FALSE;00078 00079 00080 if (execve("init.bin", NULL, NULL)==-1)00081 kpanic("No se pudo cargar init.bin");00082 00083 init_task = encontrar_proceso_por_pid(2); // Init.bin00084 tareas_inicio = init_task;00085 sys_renice(2,1);00086 00087 _reschedule();00088 while (1) {00089 kprintf("Esto no debe imprimirse ya que esta tarea no se schedulea");00090 }00091 /* 00092 TASK_SIGNALS_ALLOC (init_task);00093 TASK_SIGNALS_INIT (init_task);00094 LIST_INIT (init_task->childs);00095 00096 pid_t pid;00097 int value;00098 kprintf("ejecutando INIT.....\n");00099 if ( exec("shell.bin")!=OK )00100 perror("exec shell");00101 00102 for (value = 0; value<0xffff;value++);00103 00104 while(1) {00105 do {00106 pid = sys_waitpid( -1 , &value, WNOHANG);00107 if (pid>0) 00108 kprintf("INIT: la condicion de salida de %d es: %d\n", pid, value);00109 }while(pid!=-1); 00110 _reschedule();00111 }00112 */00113 }

Page 212: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00114 00115 00116 /* Pasa los scan codes del buffer en crudo, a los ASCII con combinaciones de ALT, SHIFT y CTRL */00117 extern void leer_buff_teclado (void);00118 00119 00120 // Busca la próxima tarea activa00121 void scheduler()00122 {00123 task_struct_t *tmp;00124 00125 leer_buff_teclado();00126 00127 if ( tareas_activas ) {00128 00129 // Volvemos al principio00130 if ( (actual==NULL) || ((tmp = actual->proxima ) == NULL) ) { tmp = tareas_inicio; }00131 00132 // Buscamos una tarea para correr00133 while ( tmp->estado != TASK_RUNNING ) {00134 if ( (tmp = tmp->proxima) == NULL ) { tmp = tareas_inicio; }00135 }00136 actual = tmp;00137 // Buscar señales pendientes, y ejecutar handler00138 check_sigpending(actual, 1); 00139 }00140 00141 else {00142 actual=NULL;00143 _sti();00144 while ( ! tareas_activas ) ;00145 _cli();00146 scheduler();00147 }00148 00149 }00150

Page 213: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

segm.c

00001 00008 #include "routix/segm.h"00009 00010 #ifndef __SYSTEM00011 #include "routix/system.h"00012 #endif00013 00015 descriptor_t make_descriptor( dword base, dword limite, byte atr1, byte atr2 )00016 {00017 descriptor_t gdt_entry;00018 00019 gdt_entry.base1 = (word) (base & 0Xffff);00020 gdt_entry.base2 = (byte) ((base & 0xff0000) >> 16);00021 gdt_entry.base3 = (byte) ((base & 0xff000000) >> 24);00022 00023 gdt_entry.limite1 = (word) (limite & 0xffff);00024 gdt_entry.atr2 = (byte) (atr2 | ((limite & 0xf0000) >> 16));00025 gdt_entry.atr1 = atr1;00026 00027 return gdt_entry;00028 }00029 00031 descriptor_t make_int_gate( word segselector, dword offset, byte atr)00032 {00033 descriptor_t int_gate;00034 00035 int_gate.base1 = segselector;00036 int_gate.limite1 = (word) (offset & 0xffff);00037 int_gate.atr1 = (byte) (atr | INT_GATE);00038 int_gate.atr2 = (byte) ((offset & 0xff0000) >> 16);00039 int_gate.base3 = (byte) ((offset & 0xff000000) >> 24);00040 00041 return int_gate;00042 }00043 00045 descriptor_t make_trap_gate( word segselector, dword offset, byte atr)00046 {00047 descriptor_t int_gate;00048 00049 int_gate.base1 = segselector;00050 int_gate.limite1 = (word) (offset & 0xffff);00051 int_gate.atr1 = (byte) (atr | TRAP_GATE);00052 int_gate.atr2 = (byte) ((offset & 0xff0000) >> 16);00053 int_gate.base3 = (byte) ((offset & 0xff000000) >> 24);00054 00055 return int_gate;00056 }00057 00058 00059 descriptor_t make_task_gate( word segselector, byte atr)00060 {00061 descriptor_t task_gate;00062 00063 task_gate.base1 = segselector;00064 task_gate.atr1 = (byte) (atr | TASK_GATE);00065

Page 215: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

segm.h

00001 /* segm.h */00002 00003 #ifndef __SYSTEM00004 #include "routix/system.h"00005 #endif00006 00007 typedef struct gdtr_t {00008 word limite;00009 dword base;00010 } gdtr_t;00011 00012 typedef gdtr_t idtr_t;00013 00014 00015 typedef struct descriptor_t {00016 word limite1; // Limite 0:1500017 word base1; // Base 0:1500018 byte base2; // Base 16:2300019 byte atr1; // P, DPL(2bits),S, Tipo(4bits)00020 byte atr2; // G, D/B, 0, AVL, Limite 16:19 (4bits) 00021 byte base3; // Base 24:3100022 } descriptor_t;00023 00024 00025 #define PRESENTE 1 << 700026 #define DPL_0 0 << 600027 #define DPL_1 1 << 500028 #define DPL_2 2 << 500029 #define DPL_3 3 << 500030 #define GENERAL 1 << 400031 #define SISTEMA 000032 00033 //Descriptor de tipo GENERAL00034 //Tipos00035 #define DATA 0 << 300036 #define EXPAND_DOWN 1 << 200037 #define WRITE 1 << 100038 00039 00040 #define CODIGO 1 << 300041 #define CONFORMING 1 << 200042 #define READ 1 << 100043 00044 #define ACCESED 1 << 000045 00046 // Descriptor de tipo SISTEMA00047 // Tipos00048 #define LDT 200049 #define TASK_GATE 500050 #define TSS_AVAILABLE 900051 #define TSS_BUSY 0xb00052 #define CALL_GATE 0xc00053 #define INT_GATE 0xe00054 #define TRAP_GATE 0xf00055 00056 00057 // 2do byte

Page 216: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00058 #define GRANULARIDAD 1 << 700059 #define DB 1 << 600060 00061 00062 __inline__ void lgdt (gdtr_t *dir_gdtr_so);00063 descriptor_t make_descriptor( dword base, dword limite, byte atr1, byte atr2 );00064 descriptor_t make_int_gate( word segselector, dword offset, byte atr);00065 descriptor_t make_trap_gate( word segselector, dword offset, byte atr);00066 descriptor_t make_task_gate( word segselector, byte atr);00067 00068 00069 00070 #define _set_ds(valor) __asm__ __volatile__ ("movw %w0,%%ds\n\t" : : "r" (valor))00071 #define _set_es(valor) __asm__ __volatile__ ("movw %w0,%%es\n\t" : : "r" (valor))00072 #define _set_fs(valor) __asm__ __volatile__ ("movw %w0,%%fs\n\t" : : "r" (valor))00073 #define _set_gs(valor) __asm__ __volatile__ ("movw %w0,%%gs\n\t" : : "r" (valor))00074 #define _set_ss(valor) __asm__ __volatile__ ("movw %w0,%%ss\n\t" : : "r" (valor))00075 #define _set_esp(valor) __asm__ __volatile__ ("movl %0,%%esp\n\t" : : "r" (valor))00076 00077 #define _lidt(valor) __asm__ __volatile__ ("lidt (%0)" : : "q" (valor));00078 #define ldtr(valor) __asm__ __volatile__ ("lldt %w0" : : "a" (valor));00079

Page 217: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

shell.c

00001 /* tarea.c */00002 #include "stdarg.h"00003 #include <sys/types.h>00004 #include <lib/routix.h>00005 #include <routix.h>00006 #include <string.h>00007 #include <signal.h>00008 00009 char msg[50];00010 00011 char msg1[50];00012 char msg2[50];00013 00014 char str[]="Shell v 0.0.0.3";00015 00016 int j, k;00017 int pid;00018 int ntasks = 0; // Tareas hijas del shell (levantar condición de salida)00019 int aux;00020 00021 void _waiting_childs(int signo);00022 00023 void main(int argc, char **argv) 00024 {00025 printf("Shell3: Cantidad de argumentos recibidos de init: %d\n", argc);00026 int bucle;00027 for (bucle = 0; bucle < argc ; bucle++) 00028 printf("Argumento %d: %s\n", bucle, argv[bucle]);00029 00030 00031 puts(str);00032 00033 putchar('\n');00034 00035 signal(SIGCHLD, _waiting_childs);00036 00037 while(1) {00038 00039 printf("kernel# ");00040 gets(msg);00041 00042 if ( ! strcmp(msg, "clear") ) {00043 clrscr();00044 }00045 else if ( ! strcmp(msg, "exec") ) {00046 printf("Ingrese nombre de tarea:");00047 gets(msg1);00048 pid = fork();00049 if (pid==-1)00050 perror("fork");00051 else if (pid==0) { //Shell HIJO00052 if (execve(msg1, NULL, NULL)==-1)00053 perror("No pudo ejecutarse");00054 exit(-1);00055 }00056 ntasks++;

Page 218: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00057 }00058 else if ( ! strcmp(msg, "echo") ) {00059 printf("Ingrese texto:");00060 gets(msg1);00061 printf("%s\n", msg1);00062 }00063 else if ( ! strcmp(msg, "\n") ) {00064 }00065 else if ( ! strcmp(msg, "ps") ) { proc_dump(); }00066 00067 else if ( ! strcmp(msg, "ps count") ) { proc_dump(); }00068 00069 else if ( ! strcmp(msg, "timers") ) { timer_dump(); }00070 00071 else if ( ! strcmp(msg, "read") ) { 00072 00073 puts("Sector: ");00074 gets(msg1);00075 00076 read_debug(atoi(msg1));00077 00078 }00079 00080 else if ( ! strcmp(msg, "kill") ) {00081 00082 puts("Pid: ");00083 gets(msg1);00084 puts("Senal: ");00085 gets(msg2);00086 if (kill(atoi(msg1), atoi(msg2))==-1)00087 perror("kill");00088 00089 }00090 00091 else if ( ! strcmp(msg, "info") ) {00092 printf("Ingrese el PID: ");00093 gets(msg2);00094 if (proc_dump_v(atoi(msg2))==-1)00095 perror("proc dump verbose"); 00096 }00097 00098 else if ( ! strcmp(msg, "renice") ) {00099 printf("Ingrese el PID: ");00100 gets(msg1);00101 printf("Ingrese la nueva prioridad: ");00102 gets(msg2);00103 if (renice( atoi(msg1), atoi(msg2)) == -1)00104 perror("renice");00105 00106 proc_dump();00107 }00108 00109 else if ( ! strcmp(msg, "free mem") ) { printf("Paginas disponibles: %d\n",free_mem() ) ; }00110 00111 else if (! strcmp(msg, "show morecores")) {00112 show(1);00113 }00114 00115 else if (! strcmp(msg, "show cache")) {00116 show(2);

Page 219: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00117 }00118 00119 else if (! strcmp(msg, "show zombies")) {00120 show(3);00121 }00122 00123 else if (! strcmp(msg, "test malloc")) {00124 show(4);00125 }00126 00127 00128 else if (! strcmp(msg, "show ntasks")) {00129 printf("Cantidad de hijos del shell: %d\n", ntasks);00130 }00131 00132 else if (! strcmp(msg, "clear alloc")) {00133 show(5);00134 }00135 00136 else if (! strcmp(msg, "show alloc")) {00137 show(6);00138 }00139 00140 else if (! strcmp(msg, "clear signals alloc")) {00141 show(7);00142 }00143 else if (! strcmp(msg, "show signals alloc")) {00144 show(8);00145 }00146 00147 00148 else if (! strcmp(msg, "setvar")) {00149 printf("Ingrese el nombre: ");00150 gets(msg1);00151 printf("Ingrese el valor: ");00152 gets(msg2);00153 if (setvar(msg1, atoi(msg2))==-1)00154 printf("No pueden definirse más variables\n");00155 }00156 00157 else if (! strcmp(msg, "getvar")) {00158 printf("Ingrese el nombre: ");00159 gets(msg1);00160 j = getvar(msg1);00161 if (j==-1)00162 printf("%s no definida\n", msg1);00163 else printf ("Valor de %s: %d\n", msg1, j);00164 }00165 00166 else printf("comando o nombre de archivo erroneo\n");00167 // Debo hacerme cargo de los hijos que van terminando00168 /*00169 if (ntasks>0) {00170 pid = waitpid (0, &aux, WNOHANG);00171 if (pid>0) {00172 printf("SHELL 2 - Proceso: %d termino con: %d\n", pid, aux );00173 ntasks--;00174 }

Page 221: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

signal.c

00001 00006 #include <routix/system.h>00007 #include <routix/task.h>00008 #include <signal.h>00009 #include <routix/signal.h>00010 #include <sys/types.h>00011 #include <routix/kstdio.h>00012 #include <error.h>00013 #include <routix/debug.h>00014 #include <routix/syscalls.h> 00015 00016 void exec_sig_default (task_struct_t *task, int signo);00017 void sig_kill(task_struct_t *task);00018 00151 // Variables que contienen cuantos malloc y cuantos frees realizó el kernel para alocar estructuras de00152 // señales (sólo con propósitos de debug)00153 unsigned int task_signals_alloc = 0;00154 unsigned int task_signals_free = 0;00155 00156 00157 00163 int check_sigpending(task_struct_t *task, int save_context)00164 {00165 // No verificar ningún tipo de señales para init (al menos por ahora)00166 if (actual==pre_init_task)00167 return -1;00168 00169 if (getvar("pepe")==1)00170 return 0;00171 00172 // Si no hay señales pendientes... me voy00173 if (TASK_SIGPENDING(task)==0) {00174 return 0;00175 }00176 00177 int signo = 0;00178 unsigned long sig = TASK_SIGPENDING(task);00179 00180 while (signo < SIGMAX) {00181 // Si la señal está pendiente y no está inhibida (o enmascarada) ...00182 if ( (sig & 1) && !IS_MASKED(task,signo)) {00183 exec_sigpending(task, signo, save_context);00184 TASK_SIGNAL_COUNT(task, signo)--;00185 if (TASK_SIGNAL_COUNT(task, signo)<1)00186 // Borro el bit que indica que la señal está pendiente00187 TASK_SIGPENDING(task) = TASK_SIGPENDING(task) ^ (1<<signo);00188 // Me voy avisando que encontre al menos una señal pendiente00189 return 1;00190 }00191 // No importa la máscara para SIGKILL00192 else if ( (sig & 1) && ((signo==SIGKILL) || (signo==SIGSTOP)) )

Page 222: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00193 sig_kill(actual);00194 sig = sig >> 1;00195 signo++;00196 }00197 00198 return 0;00199 00200 /*00201 // Barrer todas las posibles señales00202 for (signo=0 ; (sig & 1)==0 ; signo++)00203 sig = sig >> 1;00204 00205 exec_sigpending(task, signo, save_context);00206 task->sigpending = task->sigpending ^ (1<<signo);00207 00208 // Si llegué al final y no hay más pendientes00209 if (signo > SIGMAX) {00210 kprintf("No hay más pendientes ???\n");00211 return 0;00212 }00213 00214 00215 // Retorno al scheduler, diciendo que había la menos una señal pendiente00216 return 1;00217 */00218 }00219 00220 00221 00229 void exec_sigpending(task_struct_t *task, int signo, int save_context)00230 {00231 if (TASK_SIGNAL_HANDLER(task, signo) == SIG_DFL) {00232 exec_sig_default(task, signo);00233 return;00234 }00235 00236 // Debo inhibir la posibilidad que me conmute la tarea, ya que si lo hace con el stack desbalanceado00237 // puede pasar cualquier cosa00238 cli();00239 00240 // Obtener el contexto de la tarea00241 struct int_regs_ext *context = GET_CONTEXT(task);00242 00243 unsigned long *user_ptr = (unsigned long *) context->esp;00244 // Obtener la dirección física del stack de la tarea00245 user_ptr = convertir_direccion( user_ptr, actual->cr3_backup);00246 00247 // Sólo debo "pushear" el EIP de la tarea y los registros para la primer señal pendiente00248 // verificando con first_signal00249 if (save_context == 1) {00250 // kprintf("EXEC: signo first: %d\n", signo);00251 *(--user_ptr) = context->eip;00252 // kprintf("Pusheando al stack el EIP: 0x%x\n", context->eip);00253 context->esp -= 4;

Page 223: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00254 *(--user_ptr) = context->eax;00255 *(--user_ptr) = context->ebx;00256 *(--user_ptr) = context->ecx;00257 *(--user_ptr) = context->edx;00258 *(--user_ptr) = context->edi;00259 *(--user_ptr) = context->esi;00260 context->esp -= (6 * sizeof(dword));00261 00262 *(--user_ptr) = TASK_SIGMASK(task);00263 context->esp -= 4;00264 // kprintf("Pusheando MASCARA: 0x%x\n", task->sigmask);00265 00266 00267 // Paso como argumento el número de señal00268 *(--user_ptr) = signo;00269 // Y como dirección de retorno el wrapper "sigcheck" que popea los registros (EAX - ESI)00270 *(--user_ptr) = TASK_SIGADDR(task);00271 context->esp -= 8;00272 context->eip = (dword) TASK_SIGNAL_HANDLER(task, signo);00273 }00274 else {00275 // Paso como argumento el número de señal (no muevo el stack porque quedo 4 bytes desplazado)00276 *(user_ptr) = TASK_SIGMASK(task);00277 // kprintf("Pusheando MASCARA: 0x%x\n", task->sigmask);00278 context->esp -= 4;00279 *(--user_ptr) = signo;00280 *(--user_ptr) = TASK_SIGADDR(task);00281 // Y pusheo en el stack la dirección del handler (cuando termine el otro handler, se ejecutará este)00282 context->eip = (dword) TASK_SIGNAL_HANDLER(task, signo);00283 context->esp -= 4;00284 //kprintf("EXEC: signo no first: %d\n", signo);00285 }00286 00287 // Coloco como máscara, la máscara del proceso (seteada con sigaction)00288 TASK_SIGMASK(task) = TASK_SIGNAL_MASK(task, signo);00289 sti();00290 00291 }00292 00297 void exec_sig_default (task_struct_t *task, int signo)00298 {00299 if (signo==9)00300 sig_kill(actual);00301 else kprintf("Proceso PID: %d\tSIG_DFL para la senal: %d no implementado \n", task->pid, signo);00302 }00303 00304 00305 void sig_kill(task_struct_t *task)00306 {00307 sys_exit(0);00308 }00309

Page 224: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

signal.h

00001 00005 #include "sys/types.h"00006 00007 00008 #ifndef __SIGNAL00009 #define __SIGNAL00010 00011 typedef unsigned long sigset_t;00012 typedef void (*__sighandler_t) (int);00013 00014 00015 //void (*signal(int sig, void (*func)(int)))(int);00016 void *signal (int sig, void (*func)() );00017 00018 struct sigaction {00019 __sighandler_t sa_handler;00020 sigset_t sa_mask;00021 int sa_flags;00022 void (*sa_restorer)(void);00023 };00024 00025 00026 #define SIGHUP 100027 #define SIGINT 200028 #define SIGQUIT 300029 #define SIGILL 400030 #define SIGTRAP 500031 #define SIGABRT 600032 #define SIGIOT 600033 #define SIGBUS 700034 #define SIGFPE 800035 #define SIGKILL 900036 #define SIGUSR1 1000037 #define SIGSEGV 1100038 #define SIGUSR2 1200039 #define SIGPIPE 1300040 #define SIGALRM 1400041 #define SIGTERM 1500042 #define SIGSTKFLT 1600043 #define SIGCHLD 1700044 #define SIGCONT 1800045 #define SIGSTOP 1900046 #define SIGTSTP 2000047 #define SIGTTIN 2100048 #define SIGTTOU 2200049 #define SIGMAX 23 // Numero de señales00050 00051 00052 #define SIG_ERR ((void (*)(int)) -1)00053 #define SIG_DFL ((void (*)(int)) 0)00054 #define SIG_IGN ((void (*)(int)) 1)00055 #define SIG_HOLD ((void (*)(int)) 2)00056 00057 int sigprocmask(int flag, const sigset_t *set, sigset_t *old_set);00058 00059 #define SIG_BLOCK 000060 #define SIG_UNBLOCK 100061 #define SIG_SETMASK 2

Page 225: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00062 00063 #define sigemptyset(set) (*set=0)00064 #define sigfillset(set) ( (*set=0xffffffff) ? 0 : -1)00065 #define sigaddset(set, signo) ( (signo<SIGMAX) ? ( *set |= (1<<signo))==0 : -1 )00066 #define sigdelset(set, signo) ( (signo<SIGMAX) ? ( *set&=(~(1<<signo)))&0 : (unsigned long) -1)00067 #define sigismember(set, signo) ( (signo<SIGMAX) ? ((*set>>signo)&1) : -1 )00068 00069 00070 int sigaction (int signo, struct sigaction *act, struct sigaction *oact);00071 00072 #endif

Page 226: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

stdlib.c

00001 /* stdlib.c */00002 00003 #include <sys/types.h>00004 #include <routix/system.h>00005 #include <string.h>00006 00007 /* Ascii to Integer00008 * "1943" => 1 * 10^3 + 9 * 10^2 + 4 * 10^1 + 3 * 10^000009 */00010 int atoi(const char *str)00011 {00012 int numero = 0;00013 int multiplicador = 1;00014 00015 size_t largo;00016 00017 for (largo = strlen(str) - 1 , multiplicador=1; largo > -1 ; largo--, multiplicador *= 10 )00018 numero += ( *(str+largo) - '0' ) * multiplicador;00019 00020 return numero;00021 }

Page 227: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

string.c

00001 /* string.c */00002 00003 #include "routix/system.h"00004 #include "string.h"00005 00006 int strcmp(const char *s1, const char *s2)00007 {00008 int i;00009 int retorno=-1;00010 00011 for ( i=0; (*s1 == *s2); i++, s1++, s2++) {00012 if ( ( *s1 == '\0' ) | ( *s1 == '\n' ) ) {00013 retorno=0;00014 break;00015 }00016 }00017 00018 return retorno;00019 }00020 00021 00022 size_t strlen(const char *s)00023 {00024 size_t cantidad = 0;00025 00026 for ( cantidad=0; *(s+cantidad) ; cantidad++) ;00027 00028 return cantidad;00029 }00030 00031 char *strcpy (char *dest, const char *src) 00032 {00033 while ( *src) {00034 *dest++=*src++;00035 }00036 *dest='\0';00037 return dest;00038 }00039 00040 char *strncpy (char *dest, const char *src, size_t nbytes) 00041 {00042 while ( *src && nbytes) {00043 *dest++=*src++;00044 nbytes--;00045 }00046 *dest='\0';00047 return dest;00048 }00049 00050 00051 char *str_to_upper (char *str)00052 {00053 char *str_ret = str;00054 00055 for ( ; *str ; str++)00056 *str = (char) toupper(*str);00057 return str_ret;00058 } 00059

Page 228: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00060 char *str_to_lower (char *str)00061 {00062 char *str_ret = str;00063 00064 for ( ; *str ; str++)00065 *str = (char) tolower(*str);00066 return str_ret;00067 } 00068 00069 00070 int tolower(int c)00071 {00072 if ( (c >= 'A') && (c <= 'Z') )00073 c+=32;00074 return c;00075 }00076 00077 int toupper(int c)00078 {00079 if ( (c >= 'a') && (c <= 'z') )00080 c-=32;00081 return c;00082 }00083 00084 00085 int memcmp( const void *s1, const void *s2, dword n)00086 {00087 byte *s22 = (byte *) s2;00088 byte *s11 = (byte *) s1;00089 00090 while (n--) {00091 if ( *s11 != *s22 )00092 return (int) (s11-s22);00093 s22++;s11++;00094 }00095 00096 return 0;00097 } 00098 00099 /*00100 void memcpy( void *dest, const void *src, dword n)00101 {00102 byte *dest1 = (char *)dest;00103 byte *src1 = (char *)src;00104 00105 while (n--)00106 *dest1++ = *src1++;00107 00108 return dest;00109 } 00110 */00111 00112 // Decidi escribir esta funcion de este modo al ver que el tiempo de ejecucion era entre 2 y 10 veces menor que00113 // el clasico codigo en C, sin sacrificar ningun tipo de comprobaciones. Influye tambien que esta funcion puede ser00114 // usada, entre otras cosas, para copiar paginas completas como ser el caso del directorio de paginas el cual sera00115 // duplicado por cada nueva tarea creada.00116 00117 void *memcpy( void *dest, const void *src, dword n)

Page 229: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00118 {00119 __asm__("push %%ecx; push %%edi ; push %%esi ;cld ; rep ; movsb ; pop %%esi ; pop %%edi ; pop %%ecx" \00120 : : "c" ((word) n), "S" (src), "D" (dest));00121 00122 return dest;00123 }00124 00125 void *memset(void *dest, int c, size_t n) 00126 {00127 size_t i;00128 char *dst = (char *) dest;00129 for (i=0 ; i<n ; i++)00130 dst[i] = c;00131 return dest;00132 }00133 00134 00135

Page 230: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

string.h

00001 /* string.h */00002 00003 #ifndef __ROUTIX_TYPES00004 #include <sys/types.h>00005 #endif00006 00007 00008 int strcmp(const char *s1, const char *s2);00009 char *strcpy (char *dest, const char *src); 00010 char *strcat(char *dest, char *src);00011 size_t strlen(const char *s);00012 char *strncpy (char *dest, const char *src, size_t nbytes); 00013 00014 char *str_to_upper (char *str);00015 char *str_to_lower (char *str);00016 int tolower(int c);00017 int toupper(int c);00018 00019 int memcmp ( const void *s1, const void *s2, dword n);00020 void *memcpy ( void *dest, const void *src, dword n);00021 void *memset(void *s, int c, size_t n);00022 00023 // Esto debería ir en stdlib.h00024 int atoi(const char *str);

Page 231: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

sys_con.c

00001 00007 #include "routix/system.h"00008 #include "routix/paging.h"00009 #include "routix/segm.h"00010 #include "routix/debug.h"00011 #include "sys/syscalls.h"00012 #include "routix/syscalls.h"00013 #include "error.h"00014 #include <routix/kstdio.h>00015 #include "string.h"00016 #include "routix/atomic.h"00017 #ifndef __TASK00018 #include "routix/task.h"00019 #endif00020 00021 00022 //Nuevas00023 extern int sys_process (void);00024 extern int sys_console (void);00025 extern int sys_timer (void);00026 extern int sys_mem (void);00027 00028 extern task_struct_t *actual;00029 00030 00031 00032 00033 // Vector de funciones de llamadas al sistema (grupo Console)00034 int (*syscall_console[MAX_SYSCALLS]) (void) = {00035 (int (*) (void)) sys_print, 00036 (int (*) (void)) sys_gets, 00037 (int (*) (void)) sys_clrscr 00038 };00039 00040 00041 00042 // Similar a llamada nix Write pero escribiendo siempre hacia stdout00043 int sys_print (void *buff, size_t largo)00044 {00045 buff = convertir_direccion (buff , actual->cr3_backup);00046 00047 size_t aux;00048 00049 static spinlock_t candado = 1;00050 00051 // spin_lock(&candado);00052 00053 for (aux=0 ; aux<largo; aux++) {00054 //Demora utilizada para verificar el funcionamiento de spinlocks00055 // for(i=0 ; i<0x4fff ; i++);00056 putchar(*((char *)buff+aux));00057 }00058 // spin_unlock(&candado);00059 00060 return largo;00061 } 00062

Page 233: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

sys_mem.c

00001 00008 #include "routix/system.h"00009 #include "routix/paging.h"00010 #include "routix/segm.h"00011 #include "routix/debug.h"00012 #include "routix/syscalls.h"00013 #include "sys/syscalls.h"00014 #include "error.h"00015 #include "routix/kalloc.h"00016 #include <routix/kstdio.h>00017 #ifndef __TASK00018 #include "routix/task.h"00019 #endif00020 00021 00022 //Nuevas00023 00024 extern task_struct_t *actual;00025 00026 00027 00028 // Vector de funciones de llamadas al sistema (grupo Timer)00029 int (*syscall_mem[MAX_SYSCALLS]) (void) = {00030 (int (*) (void)) sys_malloc_page,00031 (int (*) (void)) sys_free_page,00032 (int (*) (void)) sys_free_mem00033 };00034 00035 00036 00037 /* SYS_MALLOC_PAGE: Esta llamada tiene por función brindarle una pagina a un proceso de usuario, dandole la direccion00038 * virtual que le corresponde. Esta funcion se encarga también, de actualizar la task_Struct con los nuevos valores.00039 */00040 void *sys_malloc_page(void)00041 {00042 //Verificar que la tarea actual no sobrepase la cantidad máxima de páginas utilizadas00043 word npages_usadas = actual->num_code + actual->num_data;00044 00045 if ( npages_usadas >= MAX_PAGINAS_POR_TAREA )00046 return NULL; //No más memoria para esta tarea00047 00048 //Debo devolver la dirección mapeada en el espacio virtual de la tarea. Desde la dir virtual TASK_DATA me desplazo00049 //num_data paginas00050 addr_t dir_virtual = TASK_DATA + (actual->num_data * PAGINA_SIZE);00051 00052 struct user_page *mem;00053 00054 //Posicionarse en el ultimo nodo00055 for (mem=actual->mdata; mem->next ; mem=mem->next);00056 00057 //Pedir memoria al Memory Manager00058 mem->next = umalloc_page (PAGINA_ALLOC, dir_virtual, actual->cr3_backup); 00059

Page 234: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00060 //Si no hay disponible, nos vamos :-(00061 if (!mem->next)00062 return NULL;00063 00064 mem = mem->next;00065 /* 00066 if (kmapmem( mem->dir , dir_virtual, actual->cr3_backup , PAGE_PRES|PAGE_USER|PAGE_RW) != OK) {00067 kprintf("\nTEMP: KmapMem Retorno -1");00068 }00069 */ 00070 actual->num_data++;00071 00072 return (void *) dir_virtual;00073 } 00074 00075 00076 00077 /* Libera una pagina del User Space NO IMPLEMENTADA */00078 int sys_free_page(void *dir)00079 {00080 kprintf("SYS_FREE_PAGE\n");00081 while(1);00082 }00083 00084 00085 // Devuelve la cantidad de paginas libres (utilizada para propositos de depuración)00086 dword sys_free_mem (void)00087 {00088 return kmem_free();00089 }00090

Page 235: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

sys_misc.c

00001 00009 #include "routix/system.h"00010 #include "routix/paging.h"00011 #include "routix/segm.h"00012 #include "routix/debug.h"00013 #include "sys/syscalls.h"00014 #include "routix/syscalls.h"00015 #include "error.h"00016 #include "routix/kalloc.h"00017 #include <routix/kstdio.h>00018 #include "string.h"00019 #ifndef __TASK00020 #include "routix/task.h"00021 #endif00022 00023 #include "routix/misc.h"00024 #include "routix/device.h"00025 #include "fs/blockcache.h"00026 00027 extern task_struct_t *actual;00028 /*00029 int sys_setvar(char *nombre, int valor);00030 int sys_getvar(char *nombre);00031 00032 int find_var(char *nombre);00033 int find_empty_var(void);00034 */00035 // Vector de funciones de llamadas al sistema (grupo Misc)00036 int (*syscall_misc[MAX_SYSCALLS]) (void) = {00037 (int (*) (void)) sys_setvar,00038 (int (*) (void)) sys_getvar,00039 (int (*) (void)) sys_read_debug00040 00041 };00042 00043 00044 00045 // Aqui se definen unas estructuras para guardar los pares (Nombre, valor) de variables accesibles via00046 // setvar y getvar.00047 // Esto es solo momentaneo, no se encariñen. Utilizado para propositos de debug en tiempo real00048 00049 #define VARIABLES_MAX 1200050 #define VAR_NAME_MAX 1500051 struct {00052 char nombre[VAR_NAME_MAX + 1];00053 int valor;00054 } variables[VARIABLES_MAX];00055 00056 // Inicializar como vacias (-1) todas los pares (nombre, valor)00057 void init_var(void)00058 {00059 int i;00060 for (i=0 ; i<VARIABLES_MAX ; i++)00061 variables[i].valor = -1;00062 }00063 00064

Page 236: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00065 inline int sys_setvar(char *nombre, int valor)00066 {00067 return setvar(convertir_direccion (nombre , actual->cr3_backup), valor);00068 }00069 00070 inline int sys_getvar(char *nombre)00071 {00072 return getvar(convertir_direccion (nombre , actual->cr3_backup));00073 }00074 00075 00076 // Setea una variable en el array variables[] si no existe alli, y modifica su valor en caso de ya encontrarse00077 int setvar(char *nombre, int valor)00078 {00079 int i;00080 00081 if ( (i=find_var(nombre)) ==-1 ) { //Variable no esta definida. Agregarla00082 if ( (i = find_empty_var()) ==-1 ) {00083 if (getvar("vardebug")==1) // Imprimir info de debug ???00084 kprintf("SYS_SETVAR: no hay espacio libre\n");00085 return -1; //No hay un espacio libre00086 }00087 strncpy(variables[i].nombre, nombre, VAR_NAME_MAX);00088 variables[i].valor = valor;00089 if (getvar("vardebug")==1) // Imprimir info de debug ???00090 kprintf("SYS_SETVAR: no estaba definida... definiendola en indice: %d\n", i);00091 return 0;00092 }00093 00094 //Si llegó aquí, la variable esta definida en el indice "i", debo modificarla00095 if (getvar("vardebug")==1) // Imprimir info de debug ???00096 kprintf("SYS_SETVAR: estaba definida ... modificandola en indice: %d\n", i);00097 00098 variables[i].valor = valor;00099 return 0;00100 00101 }00102 00103 int getvar(char *nombre)00104 {00105 int i;00106 00107 if ( (i=find_var(nombre))!=-1) {00108 return variables[i].valor;00109 }00110 00111 return -1;00112 }

Page 237: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00113 00114 // Busca una variable en el array y retorna el indice en caso de exito, o -1 en caso de no encontrarse00115 int find_var (char *nombre)00116 {00117 int i=0;00118 for (i=0 ; i<VARIABLES_MAX ; i++)00119 if (strcmp(variables[i].nombre, nombre)==0)00120 return i;00121 00122 return -1;00123 }00124 00125 // Busca un espacio libre para definir una variable. Devuelve el indice en caso de encontrarlo o -1 en caso contrario00126 int find_empty_var (void)00127 {00128 int i=0;00129 for (i=0 ; i<VARIABLES_MAX ; i++)00130 if (variables[i].valor==-1)00131 return i;00132 return -1;00133 }00134 00135 /*00136 void sys_read_debug(int sector)00137 {00138 00139 kprintf("Leyendo sector %d\n",sector);00140 00141 buffer_block_t *buf = (buffer_block_t *) malloc(sizeof(buffer_block_t));00142 00143 byte *data = (byte *) malloc( 512 * sizeof(byte) );00144 00145 BUFFER_BLOCK_DEVICE(buf)=fd0;00146 BUFFER_BLOCK_PROCESO(buf)=actual;00147 BUFFER_BLOCK_SECTOR(buf)=sector;00148 BUFFER_BLOCK_OPERACION(buf)=IOREAD;00149 BUFFER_BLOCK_BUFFER(buf)=data;00150 00151 insertar_buffer_block(buf);00152 00153 kprintf("Voy a dormir un rato...\n");00154 dormir_task(actual);00155 00156 // Switcheamos de proceso mediante la macro _reschedule quien realiza una llamada00157 // a la interrupción 0x5100158 _reschedule();00159 00160 remover_buffer_block(buf);00161 00162 kprintf("Sector leido ok !!!\n");00163 00164 int i;00165 for(i=0; i<512; i++) {00166 kprintf("%c", data[i]);00167 }00168 00169 kprintf("\n");

Page 238: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00170 00171 }00172 */00173 00174 // Realiza la lectura de un sector lógico, desde el buffer de cache00175 void sys_read_debug(int sector)00176 {00177 device_t dev=fd0;00178 00179 kprintf("Leyendo sector %d\n",sector);00180 00181 byte *data = (byte *) malloc( 512 * sizeof(byte) );00182 00183 cache_read(dev,sector,0,data,512);00184 00185 free(data);00186 00187 kprintf("Sector leido ok !!!\n");00188 00189 /*00190 int i;00191 for(i=0; i<512; i++) {00192 kprintf("%c", data[i]);00193 }00194 00195 kprintf("\n");00196 */00197 00198 }00199

Page 239: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

sys_proc.c

00001 00007 #include <routix/system.h>00008 #include <routix/paging.h>00009 #include <routix/segm.h>00010 #include <routix/debug.h>00011 #include <routix/syscalls.h>00012 #include <sys/syscalls.h>00013 #include <routix/elf.h>00014 #include <routix/file.h>00015 #include <error.h>00016 #include <routix/timer.h>00017 #include <routix/kalloc.h>00018 #include <routix/kstdio.h>00019 #include <string.h>00020 #include <routix/task.h>00021 #include <sys/list.h>00022 #include <sys/types.h>00023 #include <routix/signal.h>00024 00025 #define RUNSTATS 100026 00028 #define START_PRIORITY 100029 00030 00032 extern task_struct_t *actual;00034 extern task_struct_t *init_task;00035 00036 int sys_execve (char *nombre, char **arg_p, char **env_p);00037 inline int count_elements (char **vector);00038 00039 // Funciones relacionadas con la llamada "exit"00040 int sys_exit_mm(void);00041 int sys_exit_notify(void);00042 int sys_exit_fs (void);00043 00044 00046 int (*syscall_process[MAX_SYSCALLS]) (void) = {00047 (int (*) (void)) sys_exec, 00048 (int (*) (void)) sys_void, 00049 (int (*) (void)) sys_fork, 00050 (int (*) (void)) sys_perror, 00051 (int (*) (void)) sys_renice, 00052 (int (*) (void)) sys_get_pid,00053 (int (*) (void)) sys_get_ppid,00054 (int (*) (void)) sys_exit,00055 (int (*) (void)) sys_show,00056 (int (*) (void)) sys_waitpid,00057 (int (*) (void)) sys_execve00058 };00059 00060 00062 int sys_void (void)00063 {00064 kprintf("\nLlamada a SYS Void\n");00065 unsigned long *_esp;00066 __asm__ __volatile__ ("movl %%esp, %0" : "=m" (_esp));00067 kprintf("VOIDO: valor de ESP: 0x%x\n", *(_esp));00068 kprintf("VOIDO: valor de ESP+1: 0x%x\n", *(_esp+1));00069 kprintf("VOIDO: valor de ESP+2: 0x%x\n", *(_esp+2));

Page 240: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00070 kprintf("VOIDO: valor de ESP+3: 0x%x\n", *(_esp+3));00071 kprintf("VOIDO: valor de ESP+4: 0x%x\n", *(_esp+4));00072 kprintf("VOIDO: valor de ESP+5: 0x%x\n", *(_esp+5));00073 kprintf("VOIDO: valor de ESP+6: 0x%x\n", *(_esp+6));00074 kprintf("VOIDO: valor de ESP+7: 0x%x\n", *(_esp+7));00075 kprintf("VOIDO: valor de ESP+8: 0x%x\n", *(_esp+8));00076 kprintf("VOIDO: valor de ESP+9: 0x%x\n", *(_esp+9));00077 kprintf("VOIDO: valor de ESP+10: 0x%x\n", *(_esp+10));00078 kprintf("VOIDO: valor de ESP+11: 0x%x\n", *(_esp+11));00079 kprintf("VOIDO: valor de ESP+12: 0x%x\n", *(_esp+12));00080 kprintf("VOIDO: valor de ESP+13: 0x%x\n", *(_esp+13));00081 kprintf("VOIDO: valor de ESP+14: 0x%x\n", *(_esp+14));00082 kprintf("VOIDO: valor de ESP+15: 0x%x\n", *(_esp+15));00083 kprintf("VOIDO: valor de ESP+16: 0x%x\n", *(_esp+16));00084 kprintf("VOIDO: valor de ESP+17: 0x%x\n", *(_esp+17));00085 00086 unsigned long *p = (unsigned long *) *(_esp+9);00087 p = convertir_direccion (p, actual->cr3_backup);00088 00089 00090 return OK;00091 } 00092 00095 struct int_regs00096 {00097 dword ebx;00098 dword ecx;00099 dword edx;00100 dword edi;00101 dword esi;00102 dword ebp;00103 dword eip;00104 dword cs;00105 dword eflags;00106 dword esp;00107 dword ss;00108 };00109 00110 00112 int sys_fork (void)00113 {00114 cli();00115 00116 struct task_struct_t *new_task;00117 // Punteros al contexto de la tarea (en el stack de modo kernel)00118 struct int_regs *new, *current;00119 struct int_regs_ext *new_ext;00120 word i;00121 00122 // init_new_task devuelve la tarea creada como TASK_STOPPED, la mantendremos así hasta el final 00123 new_task = init_new_task (0,0,0,0,0, actual->descripcion, actual->prioridad);00124 00125 current = (struct int_regs *) ((actual->esp0 & 0xfffff000) + PAGINA_SIZE - sizeof(struct int_regs));00126 new = (struct int_regs *) ((new_task->esp0 & 0xfffff000) + PAGINA_SIZE - sizeof(struct int_regs));00127

Page 241: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00128 new_ext = (struct int_regs_ext *) ((new_task->esp0 & 0xfffff000) + PAGINA_SIZE - sizeof(struct int_regs_ext));00129 new_ext = GET_CONTEXT(new_task);00130 00131 new_ext->ds = DESC_DATA_USUARIO;00132 new_ext->es = DESC_DATA_USUARIO;00133 new_ext->fs = DESC_DATA_USUARIO;00134 new_ext->gs = DESC_DATA_USUARIO;00135 00136 new_task->esp0 = (new_task->esp0 & 0xfffff000) + PAGINA_SIZE - 64;00137 00138 // Copiar los contextos00139 memcpy(new, current, sizeof (struct int_regs) );00140 00141 // Duplicar los indicadores de cantidad de paginas usadas por los segmentos00142 new_task->num_code = actual->num_code;00143 new_task->num_data = actual->num_data;00144 new_task->num_stack = actual->num_stack;00145 00146 struct user_page *mem;00147 mem = new_task->mcode = actual->mcode;00148 00149 //Mapear las direcciones del segmento de codigo en memoria virtual, e incrementar el contador de procesos (count)00150 for ( i=0 ; i < new_task->num_code ; i++,mem=mem->next ) {00151 if ( kmapmem( mem->dir , mem->vdir , new_task->cr3 ,PAGE_PRES|PAGE_USER|PAGE_RW)!=OK ){00152 kprintf("Kmapmem TASK_TEXT error\n");00153 return -1;00154 }00155 mem->count++;00156 }00157 00158 struct user_page *src = actual->mdata;00159 struct user_page *dest;00160 00161 //Para datos y bss debo pedir memoria, copiar la del proceso actual en ella, y finalmente mapearla00162 for( i=0 ; i < new_task->num_data ; i++) {00163 if (i==0)00164 dest = umalloc_page ( src->flags, src->vdir, new_task->cr3 );00165 else {00166 dest->next = umalloc_page ( src->flags, src->vdir, new_task->cr3 );00167 dest = dest->next;00168 }00169 if (!dest) { //liberar00170 actual->err_no = ENOMEM;00171 return -1;00172 }00173 if (i==0) //Apuntar el mdata al comienzo de la lista00174 new_task->mdata = dest;00175 00176 // Copiar el Stack del padre00177 copy_page ( (void *)dest->dir, (void *)src->dir);00178 src = src->next;

Page 242: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00179 }00180 00181 // Pido lugar para las páginas de stack y las copio00182 src = actual->mstack;00183 for( i=0 ; i < new_task->num_stack ; i++) {00184 if (i==0)00185 dest = umalloc_page ( src->flags, src->vdir, new_task->cr3 );00186 else {00187 dest->next = umalloc_page ( src->flags, src->vdir, new_task->cr3 );00188 dest = dest->next;00189 }00190 if (!dest) { //liberar00191 actual->err_no = ENOMEM;00192 return -1;00193 }00194 if (i==0) //Apuntar el mdata al comienzo de la lista00195 new_task->mstack = dest;00196 00197 copy_page ( (void *)dest->dir, (void *)src->dir);00198 src = src->next;00199 }00200 00201 TASK_SIGNALS_ALLOC(new_task);00202 memcpy(TASK_SIGNALS(new_task), TASK_SIGNALS(actual), sizeof(struct task_signals));00203 00204 new_task->pid = get_new_pid();00205 TASK_PARENT(new_task) = actual;00206 new_task->padre = actual;00207 00208 00209 // Inicializo el header de la lista de hijos00210 LIST_INIT (new_task->childs);00211 // Me agrego en la lista de hijos de mi padre00212 LIST_ADD_TAIL(actual->childs, brothers, new_task);00213 00214 // Inicializo el header de la lista de hijos zombies00215 // LIST_INIT (new_task->zombie_header);00216 00217 // Poner en eax del hijo un 0, para que tome 0 como el retorno de fork00218 new_ext->eax = 0;00219 00220 // Despertamos la nueva tarea, recordemos que init_new_task crea las tareas en estado TASK_STOPPED00221 despertar_task( new_task );00222 sti();00223 00224 return (new_task->pid);00225 }00226 00227 00234 int sys_exec (char *nombre)00235 {00236 // kprintf("Esta llamada al sistema no se encuentra disponible, por favor, utilizar execve\n");00237 //}

Page 243: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00238 00239 #ifdef RUNSTATS00240 long long counter;00241 00242 if ( getvar("debugexec") == 2 ) {00243 rdtscl(counter);00244 }00245 #endif00246 00247 00248 nombre = convertir_direccion( nombre , actual->cr3_backup);00249 00250 int fd;00251 byte buff_aux[100]; //WARNING, agota el stack00252 word i;00253 00254 struct coff_header *p;00255 struct coff_sections sec_text, sec_data, sec_bss;00256 00257 int bytes_leidos;00258 00259 fd = open(nombre);00260 if (fd < 0) {00261 actual->err_no = ENOENT;00262 return -1;00263 }00264 00265 // Leer cabecera basica del COFF3200266 read(fd, buff_aux, sizeof(struct coff_header));00267 p = (struct coff_header *) buff_aux;00268 00269 if (p->f_magic != COFF32_TYPE) { // Verificar numero magico00270 actual->err_no = ENOEXEC;00271 close(fd);00272 return -1;00273 }00274 byte num_secciones;00275 if ( (num_secciones = p->f_nscns)!= 3) {00276 actual->err_no = ENOEXEC;00277 close(fd);00278 return -1;00279 }00280 // Pararse donde comienzan las estructuras de las secciones ( header + datos_opcionales)00281 lseek (fd, sizeof(struct coff_header) + p->f_opthdr , SEEK_SET);00282 00283 word verificacion = 0; // Flag usado para verificar la existencia de .TEXT, .DATA y .BSS00284 00285 struct coff_sections *q;00286 //Levantar las 3 secciones que debe tener el ejecutable00287 while (num_secciones--) {00288 read(fd, buff_aux, sizeof(struct coff_sections));00289 q = (struct coff_sections *) buff_aux;00290 00291 if ( q->s_flags == COFF32_TEXT ) {00292 memcpy ( &sec_text , q , sizeof(struct coff_sections) );

Page 244: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00293 verificacion = verificacion | COFF32_TEXT;00294 }00295 else if ( q->s_flags == COFF32_DATA ) {00296 memcpy ( &sec_data , q , sizeof(struct coff_sections) );00297 verificacion = verificacion | COFF32_DATA;00298 }00299 else if ( q->s_flags == COFF32_BSS ) {00300 memcpy ( &sec_bss , q , sizeof(struct coff_sections) );00301 verificacion = verificacion | COFF32_BSS;00302 }00303 else { //No se puede identificar el tipo de seccion00304 close(fd);00305 actual->err_no = ENOEXEC;00306 return -1;00307 }00308 }00309 00310 //Verificar que posea una seccion de codigo, una de datos inicializados y sin inicializar00311 if (verificacion != (COFF32_TEXT | COFF32_DATA | COFF32_BSS) ) {00312 close(fd);00313 actual->err_no = ENOEXEC;00314 return -1;00315 }00316 00317 //Verificar que haya memoria suficiente 00318 if (kmem_free() < ((actual->open_files[fd]->size / PAGINA_SIZE)+8) ) {00319 actual->err_no = ENOMEM;00320 close(fd);00321 return -1;00322 }00323 00324 // Aca voy a guardar la cantidad de paginas requeridas por cada segmento00325 word paginas_texto, paginas_datos;00326 00327 paginas_texto = sec_text.s_size / PAGINA_SIZE;00328 if ( sec_text.s_size % PAGINA_SIZE ) {00329 paginas_texto++;00330 }00331 //Tamaño en bytes del .DATA + .BSS00332 int size_datos = sec_data.s_size + sec_bss.s_size;00333 00334 //Cantidad de paginas requeridas por .DATA + .BSS00335 paginas_datos = size_datos / PAGINA_SIZE;00336 if ( size_datos % PAGINA_SIZE )00337 paginas_datos++;00338 00339 paginas_datos++; // Uso una pagina de datos para (argc, **argv, **env) y llamada implicita a EXIT00340 00341 //Cantidad de paginas requeridas solo por .DATA00342 int paginas_data = sec_data.s_size / PAGINA_SIZE;00343 if ( sec_data.s_size % PAGINA_SIZE )00344 paginas_data++;00345

Page 245: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00346 00347 task_struct_t *new_task;00348 struct user_page *mem;00349 00350 // Poner el nombre de archivo como descripcion00351 char nuevo_nombre[13];00352 tomar_nombre_tarea(nombre, nuevo_nombre);00353 00354 // init_new_task devuelve la tarea creada como TASK_STOPPED, la mantendremos así hasta el final 00355 new_task = init_new_task(DESC_CODE_USUARIO, DESC_DATA_USUARIO, TASK_TEXT, TASK_STACK + 4096 - 16, 0x202,\00356 nuevo_nombre, START_PRIORITY);00357 00358 if (!new_task) { //liberar00359 return -1;00360 }00361 00362 new_task->mstack = umalloc_page (PAGINA_STACK, TASK_STACK, new_task->cr3);00363 if (!new_task->mstack) //liberar00364 return -1;00365 00366 new_task->num_code = paginas_texto;00367 new_task->num_data = paginas_datos;00368 new_task->num_stack = 1;00369 00370 // Levantar el .TEXT00371 lseek(fd, sec_text.s_scnptr,SEEK_SET);00372 new_task->mcode = umalloc_page (PAGINA_CODE,TASK_TEXT, new_task->cr3);00373 if (!new_task->mcode) //liberar00374 return -1;00375 mem = new_task->mcode;00376 bytes_leidos = read( fd, (void *)mem->dir, PAGINA_SIZE);00377 00378 for( i=1 ; i < paginas_texto ; i++) {00379 mem->next = umalloc_page (PAGINA_CODE, TASK_TEXT + (i*PAGINA_SIZE) , new_task->cr3);00380 mem = mem->next;00381 bytes_leidos = read(fd, (void *)mem->dir , PAGINA_SIZE);00382 if (bytes_leidos < 0) { //error de algo.... liberar memoria00383 actual->err_no = EIO;00384 close(fd);00385 return -1;00386 }00387 }00388 00389 //Pedir memoria para los datos (.DATA + .BSS)00390 new_task->mdata = umalloc_page (PAGINA_DATA, TASK_DATA, new_task->cr3);00391 if (!new_task->mdata) //liberar00392 return -1;00393 for ( mem=new_task->mdata,i=1 ; i<paginas_datos ; i++, mem=mem->next ) {00394 mem->next = umalloc_page (PAGINA_DATA, TASK_DATA + (i*PAGINA_SIZE) , new_task->cr3);00395 if (!mem->next) //liberar00396 return -1;

Page 246: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00397 }00398 00399 //Levantar .DATA00400 lseek(fd, sec_data.s_scnptr,SEEK_SET);00401 for( i=0, mem=new_task->mdata ; i < paginas_data ; i++, mem=mem->next ) {00402 bytes_leidos = read(fd, (void *)mem->dir, PAGINA_SIZE);00403 if (bytes_leidos < 0) { //error de algo.... liberar memoria00404 actual->err_no = EIO;00405 close(fd);00406 return -1;00407 }00408 };00409 00410 // En esa página extra que pedimos para datos, vamos a ubicar una llamada a EXIT00411 // y los argumentos de main y variables de entorno que recibe la tarea00412 // Me ubico en la ultima pagina (la cual usare para exit, argv, etc, etc)00413 00414 for( mem=new_task->mdata ; mem->next ; mem=mem->next);00415 00416 unsigned char *ptr_exit = (unsigned char *) mem->dir;00417 00418 // Ubicamos en el wrapper el codigo de libreria routstd de llamada EXIT:00419 *ptr_exit = 0xb8; // Codigo de operacion: "mov eax, "00420 *(unsigned long *)(ptr_exit+1) = SYS_PROCESS | SYS_EXIT; 00421 *(ptr_exit+5) = 0xbb; // "mov ebx, "00422 *(unsigned long *)(ptr_exit+6) = 0; // parametro que recibe la función EXIT... 0 en este caso00423 *(ptr_exit+10) = 0xcd; // int00424 *(ptr_exit+11) = 0x50; // 0x5000425 00426 // Hardcodeo la llamada al sistema sys_signal_check, la cuál se ejecutará luego de cada handler de seña00427 *(ptr_exit+12) = 0xb8; // Codigo de operacion: "mov eax, "00428 *(unsigned long *)(ptr_exit+13) = SYS_SIGNALS | SYS_SIGNAL_CHECK; 00429 *(ptr_exit+17) = 0xcd; // int00430 *(ptr_exit+18) = 0x50; // 0x5000431 *(ptr_exit+19) = 0x5e; // pop esi // Con estos popeos recupero los registros de propósito general00432 *(ptr_exit+20) = 0x5f; // pop edi // que fueron pusheados antes de ejecutar un handler de señal00433 *(ptr_exit+21) = 0x5a; // pop edx00434 *(ptr_exit+22) = 0x59; // pop ecx00435 *(ptr_exit+23) = 0x5b; // pop ebx00436 *(ptr_exit+24) = 0x58; // pop eax00437 *(ptr_exit+25) = 0xc3; // retn00438 00439 // Aloco la estructura que almacena info de señales00440 TASK_SIGNALS_ALLOC(new_task);00441 memset (TASK_SIGNALS(new_task), 0, sizeof(struct task_signals));

Page 247: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00442 TASK_SIGADDR(new_task) = GET_OFFSET(ptr_exit + 12) + mem->vdir;00443 00444 // new_task->sigcheck_addr = GET_OFFSET(ptr_exit + 12) + mem->vdir;00445 00446 // Argumentos y demas facturetas 00447 unsigned int argc = 0;00448 char **argv, **envp;00449 00450 argv = NULL;00451 envp = NULL;00452 00453 // Mando al fondo del Stack a envp00454 unsigned long *qwe = (unsigned long *) (new_task->mstack->dir + 4096 - 4);00455 *(qwe--) = (unsigned long) envp;00456 *(qwe--) = (unsigned long) argv;00457 *(qwe--) = (unsigned long) argc;00458 *qwe = (unsigned long) mem->vdir;00459 00460 if (actual==pre_init_task) { // Si el proceso es init, caso particular ya que init no tiene formato de tarea00461 TASK_PARENT(new_task) = actual;00462 new_task->pid = get_new_pid();00463 new_task->padre = pre_init_task;00464 // A los procesos que "executa init" le inicializo la lista de hijos, ya que no la van a reemplazar00465 // a init00466 LIST_INIT (new_task->childs);00467 // Agregarse como hijo de init00468 LIST_ADD (actual->childs, brothers, new_task);00469 }00470 else { // Si es cualquier otro proceso, el nuevo proceso debe heredar su pid y ppid00471 TASK_PARENT(new_task) = TASK_PARENT(actual);00472 new_task->pid = actual->pid;00473 new_task->padre = actual->padre;00474 // El nuevo proceso se hace cargo de todos los hijos00475 // new_task->zombie_header = actual->zombie_header;00476 //LIST_REPLACE(brothers, actual, new_task);00477 // START_TICKS_COUNT();00478 LIST_DEL(actual->padre->childs, brothers, actual);00479 LIST_ADD_TAIL(actual->padre->childs, brothers, new_task);00480 // END_TICKS_COUNT();00481 // PRINT_TICKS_COUNT();00482 }00483 00484 close(fd);00485 00486 // Despertamos la nueva tarea, recordemos que init_new_task crea las tareas en estado TASK_STOPPED00487 despertar_task( new_task );00488 00489 #ifdef RUNSTATS00490 if ( getvar("debugexec") == 2 ) {

Page 248: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00491 long long int counterfinal;00492 rdtscl(counterfinal);00493 kprintf("0x%llx ",counterfinal-counter);00494 } 00495 #endif00496 00497 // Recordemos que el proceso que ejecuto el exec debe terminar (excepto que sea el init)00498 if (actual->pid!=1) {00499 00500 cli();00501 sys_exit_mm(); // libero la memoria00502 remover_task (actual); // lo saco de la lista de tareas del scheduler00503 kfree_page ((addr_t)actual); // libero el task_struct00504 sti();00505 _reschedule(); 00506 }00507 00508 00509 return OK;00510 }00511 00512 00513 00514 00516 void sys_perror (char *str)00517 {00518 str = convertir_direccion( str , actual->cr3_backup);00519 perror(str);00520 }00521 00526 int sys_renice (word pid, word prioridad)00527 {00528 // kprintf("TEMP SYS_RENICE. PID: %d\tPRI: %d\n", pid, prioridad);00529 task_struct_t *tmp;00530 if ( (tmp = encontrar_proceso_por_pid(pid))==NULL ) {00531 actual->err_no = ESRCH;00532 return -1;00533 }00534 // Esto es solo a modo de prueba ya que en routix por ahora el TASK_STOPPED cumple las veces de TASK_INTERRUMIPLE00535 if (prioridad < 1)00536 dormir_task(tmp);00537 tmp->prioridad = prioridad; 00538 return OK;00539 }00540 00542 inline pid_t sys_get_pid (void)00543 {00544 return actual->pid;00545 }00546 00548 inline pid_t sys_get_ppid (void)00549 {00550 return TASK_PPID(actual);00551 }00552

Page 249: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00554 // Llamada al sistema Exit y funciones relacionadas00555 //00557 00559 int zombie_queue_len = 0;00560 00561 00567 /*00568 * \relates sys_exit_notify00569 * \relates sys_exit_mm00570 * \relates sys_wait00571 */00572 void sys_exit (int valor)00573 {00574 cli();00575 actual->retorno = valor; 00576 00577 sys_exit_mm();00578 sys_exit_notify();00579 sys_exit_fs();00580 dormir_task(actual);00581 actual->estado = TASK_ZOMBIE;00582 sti();00583 _reschedule();00584 } 00585 00588 int sys_exit_mm(void)00589 {00590 // Libero la memoria utilizada por los handlers de señales (antes esto lo ejcutaba al final de esta función00591 // y a veces me cagaba todo.... averiguar porque !!!00592 TASK_SIGNALS_FREE(actual);00593 00594 00595 struct user_page *aux, *tmp;00596 // Liberar las paginas de código00597 for (aux=tmp=actual->mcode ; aux && tmp ; aux=tmp) {00598 tmp=aux->next;00599 // Desmapear la direccion fisica de la logica00600 kunmapmem(aux->vdir, actual->cr3_backup);00601 // Si Esta habilitada la variable de entorno "__exit", imprimir info00602 if (getvar("__exit")==1)00603 kprintf("Liberando Codigo dir: 0x%x\tvdir: 0x%x\n", aux->dir,aux->vdir);00604 ufree_page(aux);00605 }00606 // Liberar de esta tarea las paginas de datos00607 for (aux=tmp=actual->mdata ; aux && tmp ; aux=tmp) {00608 tmp=aux->next;00609 kunmapmem(aux->vdir, actual->cr3_backup);00610 if (getvar("__exit")==1)00611 kprintf("Liberando Datos dir: 0x%x\tvdir: 0x%x\n", aux->dir,aux->vdir);00612 ufree_page(aux);00613 }00614 // Liberar de esta tarea las paginas de codig00615 for (aux=tmp=actual->mstack ; aux && tmp ; aux=tmp) {00616 tmp=aux->next;00617 kunmapmem(aux->vdir, actual->cr3_backup);00618 if (getvar("__exit")==1)

Page 250: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00619 kprintf("Liberando Stack dir: 0x%x\tvdir: 0x%x\n", aux->dir,aux->vdir);00620 ufree_page(aux);00621 }00622 // Desmapear del directorio la pagina usada para los wrappers (de exit por ej)00623 kunmapmem (TASK_TEXT - PAGINA_SIZE, actual->cr3_backup);00624 00625 00626 // Libero el directorio de páginas utilizado por la tarea00627 kfree_page (actual->cr3_backup);00628 return 0;00629 }00630 00635 int sys_exit_notify (void)00636 {00637 // Aumento la cuenta que lleva el sistema sobre zombies (proposito de debug)00638 zombie_queue_len++;00639 00640 int value;00641 pid_t pid;00642 task_struct_t *child, *aux;00643 // Tomar la condición de salida de mis hijos zombies00644 _LIST_FOREACH(child, actual->childs, brothers) {00645 aux = LIST_NEXT(brothers, child);00646 00647 // Si el proceso está zombie, tomo su condidción de salida y lo libero00648 if (child->estado == TASK_ZOMBIE) {00649 if (getvar("exit")==1)00650 kprintf("Esperando al hijo: %d\n", child->pid);00651 // Liberar el primer hijo que se encuentre00652 pid = sys_waitpid(-1,&value,WNOHANG);00653 00654 if (getvar("exit")==1)00655 kprintf("EXIT_NOTIFY: termino hijo %d con: %d\n", pid, value);00656 }00657 // Si está en otro estado, se lo paso a init00658 else {00659 LIST_DEL(actual->childs, brothers, child);00660 LIST_ADD_TAIL(init_task->childs, brothers, child);00661 child->padre = init_task;00662 }00663 00664 child = aux;00665 }00666 // Envio la señal SIGCHLD al padre00667 _sys_kill(actual->padre, SIGCHLD);00668 00669 // Despertar a init 00670 wakeup_init();00671 return 0;00672 } 00673

Page 251: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00676 int sys_exit_fs ()00677 {00678 int i;00679 for (i=0 ; i < MAX_FILES_POR_TAREA ; i++)00680 if (actual->open_files[i]) {00681 free(actual->open_files[i]);00682 file_free++;00683 }00684 00685 return 0;00686 }00687 00688 00694 pid_t sys_waitpid (pid_t pid, int *status, int options)00695 {00696 _cli();00697 status = convertir_direccion( status , actual->cr3_backup);00698 00699 struct task_struct_t *child;00700 00701 int zombie_found = 0;00702 00703 while (1) {00704 // Recorrer la lista de procesos hijos, en busca de zombies00705 LIST_FOREACH (child, actual->childs, brothers) {00706 // Si el hijo no es zombie, seguir buscando00707 if (TASK_STATE(child)!=TASK_ZOMBIE)00708 continue;00709 // Buscar cualquier hijo (pid=-1) o alguno en particular (pid>1)? 00710 if (pid>1 && pid!=TASK_PPID(child))00711 break;00712 zombie_found = 1;00713 break;00714 }00715 if (zombie_found==1) 00716 break;00717 if (getvar("__wait")==1)00718 kprintf("SYS_WAIT: Mi PID es: %d\tNo encontre hijo zombie\n", actual->pid);00719 00720 // Si es no bloqueante, debo irme con -1 al no haberlo encontrado00721 if (options==WNOHANG) { 00722 if (getvar("__wait")==1)00723 kprintf("SYS_WAIT: Me voy por el WNOHANG....\n");00724 actual->err_no = ECHILD;00725 _sti();00726 return -1;00727 }00728 _sti();00729 _reschedule(); // espero un rato00730 _cli();00731 }00732 00733 // Mientras que aux queda apuntando al nodo anterior, tmp lo hace al nodo en cuestión00734 pid_t child_pid = TASK_PID(child);

Page 252: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00735 if (getvar("__wait")==1) 00736 kprintf("SYS_WAIT:Mi hijo zombie es: %d\n", child->pid);00737 00738 // Valor de retorno del hijo00739 *status = child->retorno;00740 remover_task (child);00741 00742 // Quitar al nodo de la lista00743 LIST_DEL (actual->childs,brothers, child);00744 00745 // Liberar el task struct utilizado00746 kfree_page ((addr_t)child);00747 // free (aux);00748 zombie_queue_len--;00749 00750 _sti();00751 return child_pid;00752 }00753 00754 00755 00756 //Cantidad de veces que la función malloc llamo a morecore solicitandole una página00757 extern word morecores;00758 extern struct floppy_cache *header_floppy_cache;00759 00760 void *punteros[1000];00761 00765 void sys_show (int valor)00766 {00767 int xx;00768 int mem_before = kmem_free();00769 int veces;00770 int i;00771 switch (valor) {00772 case 1: 00773 kprintf ("Cantidad de paginas asignadas via Morecores: %d\n", morecores);00774 break;00775 case 2:00776 kprintf("Sectores en cache: ");00777 struct floppy_cache *aux;00778 for (aux = header_floppy_cache, i=0 ; aux ; aux=aux->next, i++)00779 kprintf("%d ", aux->sector);00780 kprintf("\nSizeof floppy_cache: %d\n", sizeof(struct floppy_cache));00781 kprintf("Sectores cacheados: %d\tPaginas usadas: %d\n", i, sizeof(struct floppy_cache) * i / 4096 + 1);00782 break;00783 case 3:00784 kprintf ("Cantidad de procesos zombies: %d\n", zombie_queue_len);00785 break;00786 case 4:00787 if ((veces=getvar("veces"))==-1)00788 veces = 10;00789 00790 for (xx=0 ; xx<veces ; xx++) {

Page 253: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00791 if ((punteros[xx]=malloc(300))==NULL) {00792 kprintf("MALLOC ERROR\n");00793 return;00794 }00795 }00796 00797 for (xx=0 ; xx<veces ; xx++) {00798 free(punteros[xx]);00799 }00800 00801 kprintf("Veces: %d\tMemoria antes: %d\tdespues: %d\n", veces, mem_before, kmem_free());00802 break;00803 00804 case 5:00805 num_mallocs = num_frees = 0;00806 task_signals_alloc = task_signals_free = 0;00807 umalloc_alloc = umalloc_free = 0;00808 file_alloc = file_free = 0;00809 break;00810 case 6:00811 kprintf("Cantidad de Mallocs: %d\tFrees: %d\n", num_mallocs, num_frees);00812 kprintf("Allocs de task_Signals: %d\tFrees: %d\n", task_signals_alloc, task_signals_free);00813 kprintf("Allocs de User_page: %d\tFrees: %d\n", umalloc_alloc, umalloc_free);00814 kprintf("Allocs de File: %d\tFrees: %d\n", file_alloc, file_free);00815 break;00816 case 7:00817 task_signals_alloc = task_signals_free = 0;00818 break;00819 case 8:00820 kprintf("Cantidad de Mallocs de task_Signals: %d\tFrees: %d\n", task_signals_alloc, task_signals_free);00821 break;00822 default:00823 00824 break;00825 }00826 00827 }00828 00829 00830 00831 00840 int sys_execve (char *nombre, char **arg_p, char **env_p)00841 {00842 nombre = convertir_direccion( nombre , actual->cr3_backup);00843 00844 int fd;00845 byte buff_aux[100]; //WARNING, agota el stack00846 word i;00847 00848 struct coff_header *p;

Page 254: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00849 struct coff_sections sec_text, sec_data, sec_bss;00850 00851 int bytes_leidos;00852 00853 fd = open(nombre);00854 if (fd < 0) {00855 actual->err_no = ENOENT;00856 return -1;00857 }00858 00859 // Leer cabecera basica del COFF3200860 read(fd, buff_aux, sizeof(struct coff_header));00861 p = (struct coff_header *) buff_aux;00862 00863 if (p->f_magic != COFF32_TYPE) { // Verificar numero magico00864 actual->err_no = ENOEXEC;00865 close(fd);00866 return -1;00867 }00868 byte num_secciones;00869 if ( (num_secciones = p->f_nscns)!= 3) {00870 actual->err_no = ENOEXEC;00871 close(fd);00872 return -1;00873 }00874 // Pararse donde comienzan las estructuras de las secciones ( header + datos_opcionales)00875 lseek (fd, sizeof(struct coff_header) + p->f_opthdr , SEEK_SET);00876 00877 word verificacion = 0; // Flag usado para verificar la existencia de .TEXT, .DATA y .BSS00878 00879 struct coff_sections *q;00880 //Levantar las 3 secciones que debe tener el ejecutable00881 while (num_secciones--) {00882 read(fd, buff_aux, sizeof(struct coff_sections));00883 q = (struct coff_sections *) buff_aux;00884 00885 if ( q->s_flags == COFF32_TEXT ) {00886 memcpy ( &sec_text , q , sizeof(struct coff_sections) );00887 verificacion = verificacion | COFF32_TEXT;00888 }00889 else if ( q->s_flags == COFF32_DATA ) {00890 memcpy ( &sec_data , q , sizeof(struct coff_sections) );00891 verificacion = verificacion | COFF32_DATA;00892 }00893 else if ( q->s_flags == COFF32_BSS ) {00894 memcpy ( &sec_bss , q , sizeof(struct coff_sections) );00895 verificacion = verificacion | COFF32_BSS;00896 }00897 else { //No se puede identificar el tipo de seccion00898 close(fd);00899 actual->err_no = ENOEXEC;00900 return -1;

Page 255: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00901 }00902 }00903 00904 //Verificar que posea una seccion de codigo, una de datos inicializados y sin inicializar00905 if (verificacion != (COFF32_TEXT | COFF32_DATA | COFF32_BSS) ) {00906 close(fd);00907 actual->err_no = ENOEXEC;00908 return -1;00909 }00910 00911 //Verificar que haya memoria suficiente 00912 if (kmem_free() < ((actual->open_files[fd]->size / PAGINA_SIZE)+8) ) {00913 actual->err_no = ENOMEM;00914 close(fd);00915 return -1;00916 }00917 00918 // Aca voy a guardar la cantidad de paginas requeridas por cada segmento00919 word paginas_texto, paginas_datos;00920 00921 paginas_texto = sec_text.s_size / PAGINA_SIZE;00922 if ( sec_text.s_size % PAGINA_SIZE ) {00923 paginas_texto++;00924 }00925 //Tamaño en bytes del .DATA + .BSS00926 int size_datos = sec_data.s_size + sec_bss.s_size;00927 00928 //Cantidad de paginas requeridas por .DATA + .BSS00929 paginas_datos = size_datos / PAGINA_SIZE;00930 if ( size_datos % PAGINA_SIZE )00931 paginas_datos++;00932 00933 paginas_datos++; // Uso una pagina de datos para (argc, **argv, **env) y llamada implicita a EXIT00934 00935 //Cantidad de paginas requeridas solo por .DATA00936 int paginas_data = sec_data.s_size / PAGINA_SIZE;00937 if ( sec_data.s_size % PAGINA_SIZE )00938 paginas_data++;00939 00940 task_struct_t *new_task;00941 struct user_page *mem;00942 00943 // Poner el nombre de archivo como descripcion00944 char nuevo_nombre[13];00945 tomar_nombre_tarea(nombre, nuevo_nombre);00946 00947 // init_new_task devuelve la tarea creada como TASK_STOPPED, la mantendremos así hasta el final 00948 new_task = init_new_task(DESC_CODE_USUARIO, DESC_DATA_USUARIO, TASK_TEXT, TASK_STACK + 4096 - 16, 0x202,\00949 nuevo_nombre, START_PRIORITY);00950 00951 if (!new_task) { //liberar00952 return -1;00953 }00954

Page 256: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00955 new_task->mstack = umalloc_page (PAGINA_STACK, TASK_STACK, new_task->cr3);00956 if (!new_task->mstack) //liberar00957 return -1;00958 00959 new_task->num_code = paginas_texto;00960 new_task->num_data = paginas_datos;00961 new_task->num_stack = 1;00962 00963 // Levantar el .TEXT00964 lseek(fd, sec_text.s_scnptr,SEEK_SET);00965 new_task->mcode = umalloc_page (PAGINA_CODE,TASK_TEXT, new_task->cr3);00966 if (!new_task->mcode) //liberar00967 return -1;00968 mem = new_task->mcode;00969 bytes_leidos = read( fd, (void *)mem->dir, PAGINA_SIZE);00970 00971 for( i=1 ; i < paginas_texto ; i++) {00972 mem->next = umalloc_page (PAGINA_CODE, TASK_TEXT + (i*PAGINA_SIZE) , new_task->cr3);00973 mem = mem->next;00974 bytes_leidos = read(fd, (void *)mem->dir , PAGINA_SIZE);00975 if (bytes_leidos < 0) { //error de algo.... liberar memoria00976 actual->err_no = EIO;00977 close(fd);00978 return -1;00979 }00980 }00981 00982 //Pedir memoria para los datos (.DATA + .BSS)00983 new_task->mdata = umalloc_page (PAGINA_DATA, TASK_DATA, new_task->cr3);00984 if (!new_task->mdata) //liberar00985 return -1;00986 for ( mem=new_task->mdata,i=1 ; i<paginas_datos ; i++, mem=mem->next ) {00987 mem->next = umalloc_page (PAGINA_DATA, TASK_DATA + (i*PAGINA_SIZE) , new_task->cr3);00988 if (!mem->next) //liberar00989 return -1;00990 }00991 00992 //Levantar .DATA00993 lseek(fd, sec_data.s_scnptr,SEEK_SET);00994 for( i=0, mem=new_task->mdata ; i < paginas_data ; i++, mem=mem->next ) {00995 bytes_leidos = read(fd, (void *)mem->dir, PAGINA_SIZE);00996 if (bytes_leidos < 0) { //error de algo.... liberar memoria00997 actual->err_no = EIO;00998 close(fd);00999 return -1;01000 }01001 };01002 01003 // **** A partir de aqui se ubica al fondo del stack el envp, argv, argc y el retorno del main **** //

Page 257: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

01004 01005 // Me ubico en la ultima pagina (la cual usare para exit, argv, etc, etc)01006 for( mem=new_task->mdata ; mem->next ; mem=mem->next);01007 01008 unsigned char *ptr_exit = (unsigned char *) mem->dir;01009 01010 // Ubicamos en el wrapper el codigo de libreria routstd de llamada EXIT:01011 *ptr_exit = 0xb8; // Codigo de operacion: "mov eax, "01012 *(unsigned long *)(ptr_exit+1) = SYS_PROCESS | SYS_EXIT; 01013 *(ptr_exit+5) = 0xbb; // "mov ebx, "01014 *(unsigned long *)(ptr_exit+6) = 0; // parametro que recibe la función EXIT... 0 en este caso01015 *(ptr_exit+10) = 0xcd; // int01016 *(ptr_exit+11) = 0x50; // 0x5001017 01018 // Hardcodeo la llamada al sistema sys_signal_check, la cuál se ejecutará luego de cada handler de seña01019 *(ptr_exit+12) = 0xb8; // Codigo de operacion: "mov eax, "01020 *(unsigned long *)(ptr_exit+13) = SYS_SIGNALS | SYS_SIGNAL_CHECK; 01021 *(ptr_exit+17) = 0xcd; // int01022 *(ptr_exit+18) = 0x50; // 0x5001023 *(ptr_exit+19) = 0x5e; // pop esi // Con estos popeos recupero los registros de propósito general01024 *(ptr_exit+20) = 0x5f; // pop edi // que fueron pusheados antes de ejecutar un handler de señal01025 *(ptr_exit+21) = 0x5a; // pop edx01026 *(ptr_exit+22) = 0x59; // pop ecx01027 *(ptr_exit+23) = 0x5b; // pop ebx01028 *(ptr_exit+24) = 0x58; // pop eax01029 *(ptr_exit+25) = 0xc3; // retn01030 01031 TASK_SIGNALS_ALLOC(new_task);01032 memset (TASK_SIGNALS(new_task), 0, sizeof(struct task_signals));01033 TASK_SIGADDR(new_task) = GET_OFFSET(ptr_exit + 12) + mem->vdir;01034 01035 #define EXIT_CALL_LEN 1201036 #define SIGNAL_CHECK_LEN 1401037 01038 // Traspaso de argumentos y variables de entorno01039 arg_p = convertir_direccion(arg_p, actual->cr3_backup);01040 env_p = convertir_direccion(env_p, actual->cr3_backup);01041 01042 char **argv, **envp; 01043 // Cantidad de argumentos, más el nombre del ejecutable01044 int argc = count_elements (arg_p) + 1;01045 // Cantidad de variables de entorno seteadas01046 int envc = count_elements (env_p);01047 01048 char *aux_dest;01049 argv = (char **) ptr_exit + EXIT_CALL_LEN + SIGNAL_CHECK_LEN;01050 aux_dest = (char *)(argv + argc + 1); // Empiezo a poner los strings despues del vector de punteros argv01051 strcpy(aux_dest, nuevo_nombre);

Page 258: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

01052 int z;01053 01054 for (z=0 ; z<argc ; z++) {01055 argv[z] = GET_OFFSET(aux_dest) + (char *) mem->vdir;01056 aux_dest += strlen(aux_dest) + 1;01057 strcpy(aux_dest, convertir_direccion(arg_p[z], actual->cr3_backup));01058 }01059 // Coloco el NULL como ultimo elemento de vector de punteros01060 argv[z+2] = NULL;01061 01062 // Alinear a 4 bytes01063 envp = (char **) ALINEAR_4(aux_dest + strlen(aux_dest) + 4);01064 01065 aux_dest = (char *) (envp + envc + 2);01066 for (z=0 ; z<envc ; z++) {01067 strcpy(aux_dest, convertir_direccion(env_p[z], actual->cr3_backup));01068 envp[z] = GET_OFFSET(aux_dest) + (char *) mem->vdir;01069 aux_dest += strlen(aux_dest) + 1;01070 }01071 // Coloco el NULL como ultimo elemento de vector de punteros01072 envp[z+1] = NULL;01073 // TEMPORAL (no recuerdo porque le puse temporal !!!)01074 argv = (char **)(GET_OFFSET(argv) + (char *) mem->vdir);01075 envp = (char **)(GET_OFFSET(envp) + (char *) mem->vdir);01076 01077 // Mando al fondo del Stack a envp, argv, argc y el RET a sys_exit01078 unsigned long *qwe = (unsigned long *) (new_task->mstack->dir + 4096 - 4);01079 *(qwe--) = (unsigned long) envp;01080 *(qwe--) = (unsigned long) argv;01081 *(qwe--) = (unsigned long) argc;01082 *qwe = (unsigned long) mem->vdir;01083 /*01084 // El nuevo proceso debe heredar el PID y el PPID del llamante, excepto que sea INIT01085 if (actual->pid==1) { // Si el proceso es init, caso particular ya que init no tiene formato de tarea01086 TASK_PARENT(new_task) = actual;01087 TASK_PPID(new_task) = actual->pid;01088 new_task->pid = get_new_pid();01089 new_task->padre = init_task;01090 }01091 else { // Si es cualquier otro proceso, el nuevo proceso debe heredar su pid y ppid01092 TASK_PARENT(new_task) = TASK_PARENT(actual);01093 new_task->pid = actual->pid;01094 new_task->padre = actual->padre;01095 }01096 */01097 if (actual==pre_init_task) { // Si el proceso es init, caso particular ya que init no tiene formato de tarea

Page 259: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

01098 TASK_PARENT(new_task) = actual;01099 new_task->pid = get_new_pid();01100 new_task->padre = pre_init_task;01101 // A los procesos que "executa init" le inicializo la lista de hijos, ya que no la van a reemplazar01102 // a init01103 LIST_INIT (new_task->childs);01104 // Agregarse como hijo de init01105 LIST_ADD (actual->childs, brothers, new_task);01106 }01107 else { // Si es cualquier otro proceso, el nuevo proceso debe heredar su pid y ppid01108 TASK_PARENT(new_task) = TASK_PARENT(actual);01109 new_task->pid = actual->pid;01110 new_task->padre = actual->padre;01111 // El nuevo proceso se hace cargo de todos los hijos01112 // new_task->zombie_header = actual->zombie_header;01113 //LIST_REPLACE(brothers, actual, new_task);01114 // START_TICKS_COUNT();01115 LIST_DEL(actual->padre->childs, brothers, actual);01116 LIST_ADD_TAIL(actual->padre->childs, brothers, new_task);01117 // END_TICKS_COUNT();01118 // PRINT_TICKS_COUNT();01119 }01120 01121 01122 close(fd);01123 01124 // Despertamos la nueva tarea, recordemos que init_new_task crea las tareas en estado TASK_STOPPED01125 despertar_task( new_task );01126 01127 // Recordemos que el proceso que ejecuto el exec debe terminar (excepto que sea el init)01128 if (actual->pid!=1) {01129 cli();01130 sys_exit_mm(); // libero la memoria01131 remover_task (actual); // lo saco de la lista de tareas del scheduler01132 kfree_page ((addr_t)actual); // libero el task_struct01133 sti();01134 _reschedule(); 01135 }01136 return OK;01137 }01138 01140 inline int count_elements (char **vector)01141 {01142 int i;01143 for ( i=0 ; vector[i]!=NULL && i<10 && vector; i++);01144 return i;01145 }

Page 260: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

sys_signal.c

00001 00006 #include "routix/system.h"00007 #include "routix/debug.h"00008 #include "sys/syscalls.h"00009 #include "routix/syscalls.h"00010 #include "error.h"00011 #include "string.h"00012 #include "routix/task.h"00013 #include "routix/signal.h"00014 00015 extern task_struct_t *actual;00016 00017 00018 int (*syscall_signals[MAX_SYSCALLS]) (void) = {00019 (int (*) (void)) sys_kill,00020 (int (*) (void)) sys_signal,00021 (int (*) (void)) sys_sigaction,00022 (int (*) (void)) sys_signal_check,00023 (int (*) (void)) sys_sigprocmask00024 00025 };00026 int _sys_kill(task_struct_t *proceso, int signo);00027 00028 00036 int sys_kill(pid_t pid, int signo)00037 { 00038 if (getvar("__sig")==1)00039 kprintf("Recibida la senal: %d para el proceso: %d\n", signo, pid);00040 // La señal que se intenta enviar, no existe00041 if (signo > SIGMAX) {00042 actual->err_no = EINVAL;00043 return -1;00044 }00045 00046 task_struct_t *proceso;00047 proceso = encontrar_proceso_por_pid(pid);00048 00049 return _sys_kill(proceso, signo);00050 } 00051 00052 00062 int _sys_kill(task_struct_t *proceso, int signo)00063 {00064 // Si el proceso no existe00065 if (!proceso) {00066 actual->err_no = ESRCH;00067 return -1;00068 }00069 00070 // Por ahora init solo puede recibir SIGCHLD00071 if (proceso==init_task && signo!=SIGCHLD) {00072 actual->err_no = ESRCH;00073 return -1;00074 }00075 00076 // Si la señal no se la está ignorando, marcarla como pendiente00077 if (TASK_SIGNAL_HANDLER(proceso, signo) != SIG_IGN) {

Page 261: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00078 TASK_SIGPENDING(proceso) = TASK_SIGPENDING(proceso) | (1 << signo);00079 // Aqui "encolo" las señales pendientes de un mismo tipo00080 TASK_SIGNAL_COUNT(proceso, signo)++;00081 }00082 return 0;00083 }00084 00085 00092 void *sys_signal (int signo, void (*func)()) 00093 {00094 void (*old_func)() = TASK_SIGNAL_HANDLER(actual, signo);00095 // Verificar si la función "func" pertenece al espacio de direcciones del usuario00096 TASK_SIGNAL_HANDLER(actual, signo) = func;00097 if (getvar("__sig")==1)00098 kprintf("Direccion de la funcion especificada: 0x%x\n", func);00099 return old_func;00100 }00101 00104 void sys_signal_correct(void)00105 {00106 //kprintf("SYS_SIGNAL_CORRECT");00107 00108 struct int_regs_ext *contexto = GET_CONTEXT(actual);00109 00110 contexto->esp += 4;00111 00112 //__debug();00113 }00114 00115 00121 void sys_signal_check (void)00122 {00123 struct int_regs_ext *context = GET_CONTEXT(actual);00124 00125 // Porque es esto ??? Bla bla... no estoy seguro...00126 context->esp += 4;00127 00128 // Obtener la dirección física del stack de la tarea00129 unsigned long *user_ptr = (unsigned long *) convertir_direccion( context->esp, actual->cr3_backup); 00130 00131 // Obtengo el valor de sigmask valido antes de ejecutar este handler que acaba de finalizar00132 TASK_SIGMASK(actual) = *(user_ptr++);00133 00134 // Si no hay otras selañes pendientes... reacomodo el stack y retorno00135 if (check_sigpending(actual, 0)<1) {00136 context->esp += 4;00137 // kprintf("SYS_SIGNAL_CHECK: No hay otras pendientes\n");00138 }00139 // Si hay otra señal pendiente, pongo el EIP del contexto para que apunte al nuevo handler00140 else {00141 // kprintf("SYS_SIGNAL_CHECK: HAY !!! pendientes\n");

Page 262: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00142 }00143 00144 }00145 00154 int sys_sigprocmask(int flag, sigset_t *set, sigset_t *old_set)00155 {00156 old_set = (old_set == NULL) ? NULL : convertir_direccion(old_set, actual->cr3_backup);00157 set = (set == NULL) ? NULL : (sigset_t *)convertir_direccion(set, actual->cr3_backup);00158 00159 // Si old_set no es NULL, retorno en el la máscaraa ctual00160 if (old_set) {00161 *old_set = TASK_SIGMASK(actual);00162 if (!set)00163 return 0;00164 }00165 00166 00167 switch (flag) {00168 case SIG_BLOCK:00169 TASK_SIGMASK(actual) |= *set;00170 break;00171 case SIG_UNBLOCK:00172 TASK_SIGMASK(actual) = TASK_SIGMASK(actual) & (~*set);00173 break;00174 case SIG_SETMASK:00175 TASK_SIGMASK(actual) = *set;00176 break;00177 default:00178 actual->err_no = EINVAL;00179 return -1;00180 00181 }00182 00183 //kpanic("sigprocmask");00184 return 0;00185 }00186 00194 int sys_sigaction (int signo, struct sigaction *act, struct sigaction *oact) 00195 {00196 00197 if (signo >= SIGMAX) {00198 actual->err_no = EINVAL;00199 return -1;00200 }00201 00202 oact = (oact == NULL) ? NULL : convertir_direccion(oact, actual->cr3_backup);00203 act = (act == NULL) ? NULL : convertir_direccion(act, actual->cr3_backup);00204 00205 if (oact)00206 memcpy (oact, &(TASK_SIGNAL(actual, signo)), sizeof (struct sigaction));00207 00208 if (act)

Page 264: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

sys_time.c

00001 00007 #include "routix/system.h"00008 #include "routix/paging.h"00009 #include "routix/segm.h"00010 #include "routix/debug.h"00011 #include "sys/syscalls.h"00012 #include "routix/syscalls.h"00013 #include "routix/elf.h"00014 #include "routix/file.h"00015 #include "error.h"00016 #include "routix/timer.h"00017 #include "routix/atomic.h"00018 #include "routix/kalloc.h"00019 #include <routix/kstdio.h>00020 00021 #ifndef __TASK00022 #include "routix/task.h"00023 #endif00024 00025 00026 //Nuevas00027 extern int sys_process (void);00028 extern int sys_console (void);00029 extern int sys_timer (void);00030 extern int sys_mem (void);00031 00032 extern task_struct_t *actual;00033 00034 // Acceso al listado00035 //extern timer_t *timer_inicio;00036 extern dword jiffies;00037 00038 00039 00040 // Vector de funciones de llamadas al sistema (grupo Timer)00041 int (*syscall_timer[MAX_SYSCALLS]) (void) = {00042 (int (*) (void)) sys_sleep,00043 (int (*) (void)) sys_proc_dump,00044 (int (*) (void)) sys_kill,00045 (int (*) (void)) sys_usleep,00046 (int (*) (void)) sys_proc_dump_v,00047 (int (*) (void)) sys_timer_dump00048 };00049 00050 00051 00052 // Funcion llamada por el timer en el retorno para sys_sleep y sys_usleep00053 static void despertar(timer_t *info)00054 {00055 if ( info != NULL ) {00056 despertar_task(TIMER_PROCESS(info));00057 }00058 }00059 00060 00061 int sys_sleep(int segundos)00062 {00063 sys_usleep(segundos*1000000);

Page 265: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00064 return OK;00065 }00066 00067 int sys_usleep(int usegundos)00068 {00069 timer_t *timer;00070 00071 // Creamos el timer00072 if ( (timer=create_timer(USECONDS_TO_TICKS(usegundos), actual, despertar, NULL))==NULL ) {00073 return -1;00074 }00075 00076 // Dormimos la tarea actual00077 dormir_task(actual);00078 00079 // Switcheamos de proceso mediante la macro _reschedule quien realiza una llamada00080 // a la interrupción 0x5100081 _reschedule();00082 00083 // Volvemos ! el timer se venció. Este es nuestro punto de retorno.00084 // todavía estamos en modo kernel en la llamada al sistema00085 00086 return OK;00087 }00088 00089 00090 00091 int sys_proc_dump(void)00092 {00093 task_struct_t *tmp;00094 00095 char *estados[] = { "TASK_RUNNING", "TASK_STOPPED", "TASK_SLEEPING", "TASK_ININTERRUMPIBLE", "TASK_ZOMBIE", \00096 "TASK_CLEAN" };00097 00098 kprintf("pid ppid descripcion estado pri cuenta cpu sigpending sigmask\n");00099 for (tmp = tareas_inicio; tmp != NULL ; tmp=tmp->proxima ) {00100 00101 kprintf("%d\t%d\t%s", tmp->pid, tmp->padre->pid, tmp->descripcion);00102 kprintf(" %s %d %d %d",estados[tmp->estado], tmp->prioridad,tmp->cuenta,tmp->tiempo_cpu);00103 kprintf(" 0x%x\t\t0x%x\n", TASK_SIGPENDING(tmp), TASK_SIGMASK(tmp));00104 00105 }00106 00107 return 0;00108 }00109 00110 // Sys Proc Dump Verbose00111 int sys_proc_dump_v(int pid)00112 {00113 task_struct_t *tmp;00114 //Ubicar el pid en la lista de procesos00115

Page 266: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00116 if ( (tmp=encontrar_proceso_por_pid(pid))==NULL ) {00117 actual->err_no = ESRCH; //proceso no existe00118 return -1;00119 }00120 00121 if (tmp->estado == TASK_ZOMBIE) { //Si el proceso es Zombie, no tiene que mostrar00122 actual->err_no = ESRCH; 00123 return -1;00124 }00125 00126 kprintf("Descripcion: %s\tPID: %d\n", tmp->descripcion, tmp->pid);00127 kprintf("Memoria utilizada: ");00128 kprintf("Codigo: %d\tDatos: %d\tStack: %d", tmp->num_code, tmp->num_data, tmp->num_stack);00129 kprintf("\nCR3: 0x%x\t", tmp->cr3_backup);00130 kprintf("Stack Kernel: 0x%x\t", tmp->esp0 & 0xfffff000);00131 struct user_page *mem;00132 kprintf("\nPaginas Codigo:\n");00133 for(mem=tmp->mcode ; mem ; mem=mem->next)00134 kprintf("Direccion: 0x%x\tDireccion logica: 0x%x\n", mem->dir, mem->vdir);00135 kprintf("Paginas Datos:\n");00136 for(mem=tmp->mdata ; mem ; mem=mem->next)00137 kprintf("Direccion: 0x%x\tDireccion logica: 0x%x\n", mem->dir, mem->vdir);00138 kprintf("Paginas Stack:\n");00139 for(mem=tmp->mstack ; mem ; mem=mem->next)00140 kprintf("Direccion: 0x%x\tDireccion logica: 0x%x\n", mem->dir, mem->vdir);00141 00142 kprintf("Hijos de la tarea:\n");00143 task_struct_t *hijo;00144 /* LIST_FOREACH(hijo, actual->childs, brothers) {00145 kprintf("PID: %d\t", TASK_PID(hijo));00146 }*/00147 char *estados[] = { "R", "ST", "SL", "U", "Z", \00148 "C" };00149 00150 for(hijo=tmp->childs.next ; hijo!=NULL; hijo=hijo->brothers.next)00151 kprintf("PID: %d-%s\t", TASK_PID(hijo), estados[hijo->estado]);00152 kprintf("\n");00153 00154 return OK;00155 } 00156 00157 00158 00159 int sys_timer_dump(void)00160 {00161 timer_dump();00162 00163 return 1;00164 }00165

Page 267: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

syscalls.c

00001 00007 #include "routix/system.h"00008 #include "routix/paging.h"00009 #include "routix/segm.h"00010 #include "routix/debug.h"00011 #include "sys/syscalls.h"00012 #include "routix/syscalls.h"00013 #include "routix/elf.h"00014 #include "routix/file.h"00015 #include "error.h"00016 #include "routix/timer.h"00017 #include <routix/kstdio.h>00018 #ifndef __TASK00019 #include "routix/task.h"00020 #endif00021 00022 00023 //Nuevas00024 extern int sys_process (void);00025 extern int sys_console (void);00026 extern int sys_signals (void);00027 extern int sys_timer (void);00028 extern int sys_mem (void);00029 extern int sys_misc (void); //Grupo de llamadas al sistema provisorias (cualquier fruta... va acá).00030 00031 extern task_struct_t *actual;00032 00033 00035 int (*syscall_group_vector[MAX_SYSCALLS]) (void) = {00036 (int (*) (void)) sys_process, 00037 (int (*) (void)) sys_console, 00038 (int (*) (void)) sys_signals, 00039 (int (*) (void)) sys_timer, 00040 (int (*) (void)) sys_mem, 00041 (int (*) (void)) sys_misc 00042 };00043 00047 unsigned int syscall_group_max[MAX_SYSCALLS] = {00048 SYS_PROCESS_MAX,00049 SYS_CONSOLE_MAX,00050 SYS_SIGNALS_MAX,00051 SYS_TIMER_MAX,00052 SYS_MEM_MAX,00053 SYS_MISC_MAX00054 };00055 00059 int sys_no_existe (dword numero)00060 {00061 kprintf("SysCall Inexistente: Grupo %d\tLlamada %d\n", numero>>16 , (word)numero);00062 actual->err_no = ENOSYS;00063 return -1;00064 } 00065

Page 268: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

syscalls.h

00001 00005 #ifndef _SYSCALLS_H00006 #define _SYSCALLS_H00007 00008 00009 #define _syscall0(numero,retorno) __asm__ __volatile__ ("int $0x50" : "=a" (retorno) : "a" (numero))00010 #define _syscall1(numero,retorno,param1) __asm__ __volatile__ ("int $0x50" : "=a" (retorno) : "a" (numero), "b" (param1))00011 #define _syscall2(numero,retorno,param1,param2) __asm__ __volatile__ ("int $0x50" : "=a" (retorno) : "a" (numero), \00012 "b" (param1), "c" (param2))00013 #define _syscall3(numero,retorno,param1,param2,param3) __asm__ __volatile__ ("int $0x50" : "=a" (retorno) : "a" (numero), \00014 "b" (param1), "c" (param2), "d" (param3))00015 00016 00017 #define MAX_SYSCALLS 15 00018 00019 // Definiciones de grupos00020 #define SYS_PROCESS 000021 #define SYS_CONSOLE (1 << 16)00022 #define SYS_SIGNALS (2 << 16)00023 #define SYS_TIMER (3 << 16)00024 #define SYS_MEM (4 << 16)00025 #define SYS_MISC (5 << 16)00026 00027 //El valor SYS_%_MAX determina cual es el número de llamadas al sistema para ese grupo, evitando problemas00028 // % equivale al nombre del grupo00029 00030 // Funciones de grupo PROCESS00031 #define SYS_EXEC 000032 #define SYS_VOID 100033 #define SYS_FORK 200034 #define SYS_PERROR 300035 #define SYS_RENICE 400036 #define SYS_GETPID 500037 #define SYS_GETPPID 600038 #define SYS_EXIT 700039 #define SYS_SHOW 800040 #define SYS_WAIT 900041 #define SYS_EXECVE 1000042 #define SYS_PROCESS_MAX 11 // Cantidad de llamadas en el grupo PROCESS. Debe ser siempre el ultimo valor00043 00044 // Funciones de grupo CONSOLE00045 #define SYS_PRINT 000046 #define SYS_GETS 100047 #define SYS_CLRSCR 200048 #define SYS_CONSOLE_MAX 3 // Cantidad de llamadas en el grupo CONSOLE. Debe ser siempre el ultimo valor00049 00050 // Funciones del grupo SIGNALS00051 #define SYS_KILL 0 //00052 #define SYS_SIGNAL 100053 #define SYS_SIGACTION 200054 #define SYS_SIGNAL_CHECK 300055 #define SYS_SIGPROCMASK 4

Page 269: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00056 #define SYS_SIGNALS_MAX 5 // Cantidad de llamadas en el grupo SIGNALS. Debe ser siempre el ultimo valor00057 00058 00059 // Funciones de grupo TIMER00060 #define SYS_SLEEP 000061 #define SYS_PROC_DUMP 100062 #define SYS_KILLL 2 //KILL no va aquí (debo crear un grupo SYS_SIGNAL o lo ubico en SYS_MEM ?)00063 #define SYS_USLEEP 300064 #define SYS_PROC_DUMP_V 400065 #define SYS_TIMER_DUMP 500066 #define SYS_TIMER_MAX 6 // Cantidad de llamadas en el grupo TIMER. Debe ser siempre el ultimo valor00067 00068 // Funciones de grupo MEM00069 #define SYS_MALLOC_PAGE 000070 #define SYS_FREE_PAGE 100071 #define SYS_FREE_MEM 200072 #define SYS_MEM_MAX 3 // Cantidad de llamadas en el grupo MEM. Debe ser siempre el ultimo valor00073 00074 // Funciones de grupo MISC00075 #define SYS_SETVAR 000076 #define SYS_GETVAR 100077 #define SYS_READ_DEBUG 2 00078 #define SYS_MISC_MAX 3 // Cantidad de llamadas en el grupo MEM. 00079 00080 void syscall (void);00081 int sys_no_existe (dword numero);00082 00083 #endif

Page 270: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

system.h

00001 /* system.h */00002 00003 #ifndef __ROUTIX_TYPES00004 #include "sys/types.h"00005 #endif00006 00007 #ifndef __SYSTEM00008 #define __SYSTEM00009 00010 #define rdtscl(low) \00011 __asm__ __volatile__ ("rdtsc" : "=A" (low))00012 00013 00014 /* Constantes de memoria física y virtual */00015 #define KERNEL_FCODE 000016 #define KERNEL_FDATA 0x10000000017 #define KERNEL_FSTACK_TOP 0x200000 00018 #define KERNEL_STACK_SIZE 0x2000000019 #define KERNEL_FSTACK KERNEL_FSTACK_TOP - KERNEL_STACK_SIZE00020 00021 #define KERNEL_END KERNEL_FSTACK_TOP00022 00023 #define KERNEL_CODE 0xc000000000024 #define KERNEL_DATA 0xc800000000025 #define KERNEL_STACK 0xd000000000026 #define KERNEL_STACK_TOP KERNEL_STACK + 0x800000000027 #define KERNEL_INTERRUPT KERNEL_STACK_TOP00028 00029 00030 #define DESC_CODE 1<<300031 #define DESC_DATA 2<<300032 #define DESC_CODE_USUARIO 3<<3 | 300033 #define DESC_DATA_USUARIO 4<<3 | 300034 #define DESC_TSS0 5<<300035 #define DESC_TSS1 6<<300036 00037 /* Variables Globales */00038 extern dword memoria;00039 00040 extern addr_t KERNEL_PDT;00041 extern addr_t USER_PDT;00042 00043 //Kernel PANIC (suceso inesperado o irrecuperable)00044 void kpanic(char *str);00045 00046 #define nop() __asm__ __volatile__ ("nop")00047 00048 #define cli() __asm__ __volatile__ ("pushf ; cli")00049 #define sti() __asm__ __volatile__ ("popf")00050 00051 #define _cli() __asm__ __volatile__ ("cli")00052 #define _sti() __asm__ __volatile__ ("sti")00053 00054 int getvar (char *);00055 int setvar (char *, int);00056 // Funciones de libreria00057 int sys_putc (char);00058 void kprintf ( char *string, ... );00059

Page 271: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00060 00061 #endif

Page 272: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

task.c

00001 00006 #include "routix/system.h"00007 #include "routix/task.h"00008 #include "routix/paging.h"00009 #include "routix/kalloc.h"00010 #include "error.h"00011 #include "routix/file.h"00012 #include "string.h"00013 00014 #include "sys/list.h"00015 00016 // Un solo tss00017 tss_t tss; 00018 00019 void inicializarTss(tss_t *tss, word cs, word ds, dword eip, dword esp, dword eflags)00020 {00021 tss->ss0 = DESC_DATA;00022 tss->cs=cs;00023 tss->ds=ds;00024 tss->es=ds;00025 tss->fs=ds;00026 tss->gs=ds;00027 tss->ss=ds;00028 tss->eip=eip;00029 tss->esp=esp;00030 tss->eflags=eflags;00031 tss->ldt=0;00032 tss->t=0;00033 tss->cr3=POSICION_DIR_PAGINAS;00034 }00035 00036 00037 //Agregado de ebp para facilitar el fork00038 dword *inicializar_task(dword *stack, word cs, word ds, dword eip, dword esp, dword eflags)00039 {00040 00041 /* Recordemos como se pushean los datos al stack00042 interrupcion00043 push eax00044 push ebx00045 push ecx00046 push edx00047 push ds00048 push es00049 push fs00050 push gs00051 push ebp00052 push esi00053 push edi00054 00055 o sea, tenemos en el siguiente orden:00056 Interrupción : ss, esp, eflags, cs, eip00057 Push manuales: eax, ebx, .... , edi00058 00059 debemos cargar el stack del kernel de la misma manera00060 */00061

Page 273: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00062 00063 stack--;00064 *stack-- = ds; //ss00065 *stack-- = esp;00066 *stack-- = eflags;00067 *stack-- = cs;00068 *stack-- = eip;00069 *stack-- = 0; //ebp00070 *stack-- = 0; //esi00071 *stack-- = 0; //edi00072 *stack-- = 0; //edx00073 *stack-- = 0; //ecx00074 *stack-- = 0; //ebx 00075 *stack-- = 0; //eax00076 *stack-- = ds; //ds00077 *stack-- = ds; //es00078 *stack-- = ds; //fs00079 *stack = ds; //gs00080 00081 return stack;00082 }00083 00084 /*00085 dword *inicializar_fork(dword *stack,word cs,word ds,dword eip,dword esp,dword eflags,dword ebp, dword eax, dword ebx, \00086 dword ecx, dword edx, dword edi, dword esi)00087 {00088 stack--;00089 *stack-- = ds; //ss00090 *stack-- = esp;00091 *stack-- = eflags;00092 *stack-- = cs;00093 *stack-- = eip;00094 *stack-- = eax; //eax00095 *stack-- = ebx; //ebx 00096 *stack-- = ecx; //ecx00097 *stack-- = edx; //edx00098 *stack-- = ds; //ds00099 *stack-- = ds; //es00100 *stack-- = ds; //fs00101 *stack-- = ds; //gs00102 *stack-- = ebp; //ebp00103 *stack-- = esi; //esi00104 *stack = edi; //edi00105 00106 return stack;00107 }00108 */ 00109 00110 00111 inline pid_t get_new_pid(void)00112 {00113 static pid_t pid=2;00114 00115 return(pid++);00116 }00117 00118 00119 00120 // Contador de tareas activas ( estado == TASK_RUNNING )00121 volatile int tareas_activas=0;

Page 274: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00122 00123 void inc_tareas_activas()00124 {00125 ++tareas_activas;00126 }00127 00128 inline void dormir_task(task_struct_t *tarea)00129 {00130 // No puede ser interrumpida por el TimerTick (Atomicidad)00131 cli();00132 00133 // Cambiamos su estado y le sacamos el resto de tiempo de cpu que le faltaba00134 tarea->estado = TASK_INTERRUMPIBLE;00135 tarea->cuenta=tarea->prioridad;00136 00137 --tareas_activas;00138 /*00139 if ( tareas_activas < 1 && init_task->estado!=TASK_RUNNING) {00140 init_task->estado=TASK_RUNNING;00141 tareas_activas++;00142 }00143 */00144 sti();00145 }00146 00147 inline void despertar_task(task_struct_t *tarea)00148 {00149 // No puede ser interrumpida por el TimerTick (Atomicidad)00150 cli();00151 00152 tarea->estado = TASK_RUNNING;00153 tareas_activas++;00154 /*00155 if ( tareas_activas > 1 && init_task->estado==TASK_RUNNING ) {00156 init_task->estado=TASK_STOPPED;00157 tareas_activas--; 00158 }00159 */00160 sti();00161 }00162 00163 00164 inline void sleep_init()00165 {00166 cli();00167 //if ( tareas_activas > 1 && init_task->estado==TASK_RUNNING ) {00168 if ( init_task->estado==TASK_RUNNING ) {00169 init_task->estado=TASK_STOPPED;00170 tareas_activas--; 00171 }00172 sti();00173 }00174 00175 inline void wakeup_init()00176 {00177 cli();

Page 275: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00178 if (init_task->estado!=TASK_RUNNING) {00179 init_task->estado=TASK_RUNNING;00180 tareas_activas++;00181 }00182 sti();00183 }00184 00185 00186 task_struct_t *init_new_task(word cs, word ds, dword eip, dword esp, dword eflags, char *descripcion, word prioridad)00187 {00188 task_struct_t *nueva;00189 dword esp0;00190 00191 // Alocamos una página completa (para el descriptor de tarea y el stack en modo kernel).00192 if ( (nueva = (task_struct_t *) kmalloc_page()) == NULL ) {00193 return NULL;00194 }00195 00196 //Provisorio, debe ser más performante !!!00197 memset(nueva, 0, PAGINA_SIZE);00198 00199 // Selector de Datos (DPL=0) y esp0 al final de la página00200 esp0 = (dword) nueva + 4092;00201 00202 // Crear un directorio de paginas y alojar su dir en cr300203 if ( (nueva->cr3 = (addr_t) make_pdt()) == NULL ) {00204 kfree_page((addr_t)nueva);00205 return NULL;00206 } 00207 00208 nueva->cr3_backup = nueva->cr3;00209 00210 // Esto debe hacerse sólo en la llamada a fork (o en exec si el que llama es init)00211 // nueva->pid = get_new_pid();00212 strcpy( nueva->descripcion, descripcion);00213 00214 // Ponemos la tarea a correr00215 //nueva->estado = TASK_RUNNING;00216 // Stoppeada hasta no terminar todo el proceso de creacion, la debe despertar otra funcion00217 // como por ejemplo sys_exec()00218 nueva->estado = TASK_STOPPED;00219 00220 nueva->prioridad = prioridad;00221 00222 nueva->err_no = 0;00223 00224 // Cantidad de ticks que tiene permitido usar la cpu en forma continua00225 nueva->cuenta = prioridad;00226 nueva->tiempo_cpu = 0;00227 00228 // Inicializamos la estructura que contiene el contexto de hardware de la tarea00229 nueva->esp0 = (dword) inicializar_task((dword *)esp0,cs,ds,eip,esp,eflags); //el ultimo 0 es ebp (provisorio)00230 00231 word j;

Page 276: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00232 for (j=0 ; j<MAX_FILES_POR_TAREA; j++)00233 nueva->open_files[j] = NULL;00234 00235 // Inicializo todos los handlers de señal a SIG_DFL00236 /*00237 int init_signo;00238 for (init_signo=0 ; init_signo<SIGMAX ; init_signo++)00239 (TASK_SIGNAL_HANDLER(actual, init_signo)) = SIG_DFL;00240 */00241 00242 00243 // Insertamos la tarea en la lista00244 if ( ! insertar_tarea(nueva) ) {00245 00246 kpanic("aca");00247 00248 00249 // No pudimos insertarla !! liberamos la memoria00250 kfree_page((addr_t)nueva);00251 00252 return NULL;00253 }00254 00255 // Si hay más de una tarea activa ponemos a dormir al idle task00256 //if ( ++tareas_activas > 1 ) {00257 // dormir_task( tareas_inicio );00258 //}00259 00260 return nueva;00261 }00262 00263 00264 00265 00266 00267 int insertar_tarea(task_struct_t *nueva)00268 {00269 task_struct_t *tmp;00270 00271 if ( nueva == NULL ) { return 0; }00272 00273 cli();00274 00275 // Nos paramos al ppio de la lista00276 tmp = tareas_inicio;00277 00278 if ( tareas_inicio == NULL ) { tareas_inicio = nueva; }00279 00280 else {00281 00282 // Buscamos la última tarea00283 for ( tmp = tareas_inicio; tmp->proxima != NULL ; tmp = tmp->proxima );00284 00285 // Nos colgamos de ella00286 tmp->proxima = nueva;00287 }00288 00289 // La nueva tarea queda apuntando a NULL00290 nueva->proxima = NULL;

Page 277: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00291 00292 sti();00293 return 1;00294 }00295 00296 00297 00298 task_struct_t *encontrar_proceso_por_pid(pid_t pid)00299 {00300 task_struct_t *tmp;00301 00302 for( tmp = tareas_inicio; tmp && (tmp->pid != pid); tmp = tmp->proxima) ;00303 00304 return tmp;00305 }00306 00307 00308 /* Esta funcion toma un path de archivo, y coloca en nuevo solo el nombre del archivo.00309 * Ej: viejo[]="/files/rotor.bin" ---> nuevo[]="rotor.bin"00310 * (usado por ejemplo en el "ps")00311 */ 00312 00313 void tomar_nombre_tarea (const char *viejo, char *nuevo)00314 {00315 char *aux = (char *) (viejo + strlen(viejo));00316 int i=12; //Cantidad maxima de caracteres de un archivo (11 ya que estamos en FAT)00317 for ( ; (aux > viejo) && (*aux!='/') && i>0 ; aux--);00318 00319 strcpy(nuevo, aux);00320 nuevo = str_to_lower (nuevo);00321 } 00322 00325 int remover_task (task_struct_t *tarea)00326 {00327 task_struct_t *aux;00328 00329 for ( aux = tareas_inicio ; aux!=NULL ; aux=aux->proxima) {00330 if (aux->proxima == tarea) { //La encontre00331 aux->proxima = tarea->proxima;00332 return 0;00333 }00334 }00335 return -1;00336 }

Page 278: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

task.h

00001 /* task.h */00002 00003 #ifndef __SYSTEM00004 #include "routix/system.h"00005 #endif00006 00007 #include <routix/paging.h>00008 #include "sys/list.h"00009 00010 00011 #ifndef __ROUTIX_TYPES00012 #include <sys/types.h>00013 #endif00014 00015 #ifndef __SIGNAL00016 #include <signal.h>00017 #endif00018 00019 #ifndef __ROUTIX_TASK00020 #define __ROUTIX_TASK00021 00022 #include "routix/file.h"00023 00024 00025 #define MAX_TASKS 700026 00027 typedef struct task_t {00028 word previos_task_link;00029 dword esp0;00030 word ss0;00031 dword esp1;00032 word ss1;00033 dword esp2;00034 word ss2;00035 dword cr3;00036 dword eip;00037 dword eflags;00038 dword eax;00039 dword ecx;00040 dword edx;00041 dword ebx;00042 dword esp;00043 dword ebp;00044 dword esi;00045 dword edi;00046 word es;00047 word cs;00048 word ss;00049 word ds;00050 word fs;00051 word gs;00052 word ldt;00053 word t;00054 word iomap;00055 } task_t;00056 00057 00058 typedef struct tss_t {00059 word previos_task_link;

Page 279: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00060 word reservado0;00061 dword esp0;00062 word ss0;00063 word reservado1;00064 dword esp1;00065 word ss1;00066 word reservado2;00067 dword esp2;00068 word ss2;00069 word reservado3;00070 dword cr3;00071 dword eip;00072 dword eflags;00073 dword eax;00074 dword ecx;00075 dword edx;00076 dword ebx;00077 dword esp;00078 dword ebp;00079 dword esi;00080 dword edi;00081 word es;00082 word reservado4;00083 word cs;00084 word reservado5;00085 word ss;00086 word reservado6;00087 word ds;00088 word reservado7;00089 word fs;00090 word reservado8;00091 word gs;00092 word reservado9;00093 word ldt;00094 word reservado10;00095 word t;00096 word iomap;00097 } tss_t;00098 00100 struct int_regs_ext00101 {00102 dword gs;00103 dword fs;00104 dword es;00105 dword ds;00106 dword eax;00107 dword ebx;00108 dword ecx;00109 dword edx;00110 dword edi;00111 dword esi;00112 dword ebp;00113 dword eip;00114 dword cs;00115 dword eflags;00116 dword esp;00117 dword ss;00118 };00119 00120 00121 extern tss_t tss;

Page 280: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00122 extern task_t tarea[];00123 void inicializarTss(tss_t *tss, word cs, word ds, dword eip, dword esp, dword eflags);00124 00125 inline pid_t get_new_pid(void);00126 00127 #define ltr(selector) __asm__ __volatile__("ltr %w0" : : "a" (selector));00128 00129 00130 00131 #define MAX_PAGINAS_POR_TAREA 1600132 #define MAX_DESCRIPTION 6400133 00134 struct task_signals {00135 struct sigaction signal[SIGMAX];00136 unsigned char sigcount[SIGMAX];00137 unsigned long sigpending; //Señales pendientes00138 sigset_t sigmask;00139 addr_t sigcheck_addr; //Aca guardo la dir del hardcode de la llamada a SYS_SIGNALS | SYS_SIGNAL_CHECK 00140 };00141 00142 // Estas variables contienen la cantidad de alocaciones y liberacion de estructuras de señales00143 // (solo para control de leaks)00144 extern unsigned int task_signals_alloc, task_signals_free;00145 00146 extern unsigned int umalloc_alloc, umalloc_free;00147 extern unsigned int file_alloc, file_free;00148 00149 00150 #define TASK_SIGNALS(task) (task->_signals)00151 #define TASK_SIGPENDING(task) (TASK_SIGNALS(task)->sigpending)00152 #define TASK_SIGMASK(task) (TASK_SIGNALS(task)->sigmask)00153 #define TASK_SIGADDR(task) (TASK_SIGNALS(task)->sigcheck_addr)00154 #define TASK_SIGNAL(task, signo) (TASK_SIGNALS(task)->signal[signo])00155 #define TASK_SIGNAL_HANDLER(task,signo) (TASK_SIGNAL(task,signo).sa_handler)00156 #define TASK_SIGNAL_MASK(task,signo) (TASK_SIGNAL(task,signo).sa_mask)00157 #define TASK_SIGNAL_FLAGS(task,signo) (TASK_SIGNAL(task,signo).sa_flags)00158 00159 #define TASK_SIGNALS_ALLOC(task) TASK_SIGNALS(task) = (struct task_signals *) \00160 malloc(sizeof(struct task_signals)); \00161 task_signals_alloc++; 00162 #define TASK_SIGNALS_FREE(task) free(TASK_SIGNALS(task)); \

Page 281: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00163 task_signals_free++; 00164 #define TASK_SIGNALS_INIT(task) memset(TASK_SIGNALS(task), 0, sizeof(struct task_signals))00165 00166 #define TASK_SIGNAL_COUNT(task, signo) ((TASK_SIGNALS(task)->sigcount)[signo])00167 00168 struct std_header {00169 struct std_header *next;00170 struct std_header *prev;00171 }; 00172 00173 00174 typedef struct task_struct_t00175 {00176 dword esp0;00177 dword cr3;00178 dword cr3_backup;00179 pid_t pid;00180 struct task_struct_t *proxima;00181 char descripcion[MAX_DESCRIPTION];00182 byte estado;00183 word prioridad;00184 word cuenta;00185 dword tiempo_cpu;00186 struct file *open_files [MAX_FILES_POR_TAREA]; //definido en file.h00187 word num_code, num_data, num_stack; //Cantidad de paginas de Codigo, Datos y stack00188 int err_no;00189 struct user_page *mcode;00190 struct user_page *mdata;00191 struct user_page *mstack;00192 struct task_struct_t *padre;00193 int retorno;00194 // LIST_NEW(struct zombie_queue) zombie_header;00195 LIST_DATA(task_struct_t) io_pending; // Este proceso puede pertenecer a una lista00196 // de entrada/salida, estando pendiente (mientras00197 // se lee o escribe de disco por medio de disco)00198 // ver "blockcache.c".00199 LIST_NEW(struct task_struct_t) childs; // Header de una lista con los hijosl proceso00200 LIST_DATA(task_struct_t) brothers; // Nodo de la lista que contiene a todos sus "bros"00201 00202 struct task_signals *_signals;00203 /*00204 struct sigaction signals[SIGMAX];00205 unsigned long sigpending; //Señales pendientes00206 addr_t sigcheck_addr; //Aca guardo la dir del hardcode de la llamada a SYS_SIGNALS | SYS_SIGNAL_CHECK 00207 sigset_t sigmask;00208 */00209

Page 282: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00210 } task_struct_t ;00211 00212 #define TASK_STACK_USER(t) (t->esp0)00213 #define TASK_CR3(t) (t->cr3)00214 #define TASK_CR3_BACKUP(t) (t->cr3_backup)00215 #define TASK_PID(t) (t->pid)00216 #define TASK_DESCRIPTION(t) (t->descripcion)00217 #define TASK_STATE(t) (t->estado)00218 #define TASK_PRIORITY(t) (t->prioridad)00219 #define TASK_COUNT(t) (t->cuenta)00220 #define TASK_CPUTIME(t) (t->tiempo_cpu)00221 #define TASK_CODEPAGES(t) (t->num_code)00222 #define TASK_DATAPAGES(t) (t->num_data)00223 #define TASK_STACKPAGES(t) (t->num_stack)00224 #define TASK_ERRNO(t) (t->err_no)00225 #define TASK_PPID(t) (t->padre->pid)00226 #define TASK_PARENT(t) (t->padre)00227 00228 enum estado { TASK_RUNNING, TASK_STOPPED, TASK_INTERRUMPIBLE, TASK_ININTERRUMPIBLE, TASK_ZOMBIE, TASK_CLEAN };00229 00230 extern task_struct_t *init_task, *pre_init_task;00231 inline void sleep_init();00232 inline void wakeup_init();00233 00234 // Estructura que describe las paginas utilizadas por las tareas00235 #define PAGINA_DATA 0 //pagina de datos00236 #define PAGINA_CODE 1 //pagina de codigo00237 #define PAGINA_STACK 0 //pagina de stack 00238 #define PAGINA_ALLOC 2 //pagina alocada dinamicamente00239 00240 struct user_page00241 {00242 addr_t dir, vdir;00243 word count;00244 dword flags;00245 struct user_page *next;00246 };00247 00248 00249 00250 00251 // Variables externas00252 extern task_struct_t *tareas_inicio;00253 extern task_struct_t *actual;00254 00255 // Funciones para el manejo de tareas00256 task_struct_t *init_new_task(word cs, word ds, dword eip, dword esp, dword eflags, char *descripcion, word prioridad);00257 task_struct_t *encontrar_proceso_por_pid(pid_t pid);00258 void tomar_nombre_tarea (const char *viejo, char *nuevo);00259 inline void dormir_task(task_struct_t *tarea);00260 inline void despertar_task(task_struct_t *tarea);00261 int insertar_tarea(task_struct_t *nueva);00262 int remover_task (task_struct_t *tarea);00263 00264 00265 // Macro para reschedulear, genera una llamada a la int 0x51 quien busca la próxima tarea a correr00266 #define _reschedule() __asm__ __volatile__("int $0x51")

Page 283: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00267 00268 00269 // Direcciones logicas de los segmentos del espacio de usuario00270 #define TASK_TEXT 0x8000000000271 #define TASK_DATA 0x8800000000272 #define TASK_STACK 0x9000000000273 00274 // Ubicacion logica de una pagina de kernel que poseera permisos de usuario para contener algunos wrappers 00275 // (como por ejemplo, una llamada a Syscall EXIT cuando termina el main de una tarea).00276 // EL pedido de la pagina, y la asignacion del código de EXIT está realizado en Kmain.c00277 #define EXIT_TASK (TASK_TEXT - PAGINA_SIZE)00278 00279 // Estructura utilizada para almacenar una cola de procesos zombies (Siempre hay un primer nodo)00280 struct zombie_queue00281 {00282 pid_t ppid; // padre del proceso zombiee00283 task_struct_t *task_struct; // task struct del proceso00284 LIST_DATA (zombie_queue) zombie_queue; 00285 };00286 00287 00288 #define GET_CONTEXT(task) ((struct int_regs_ext *) ((task->esp0 & 0xfffff000) + PAGINA_SIZE - sizeof(struct int_regs_ext)))00289 00290 // Definiciones para debuggear memory leaks00291 00292 extern int num_mallocs, num_frees;00293 extern int num_alloc_signals, num_free_signals;00294 00295 #endif

Page 284: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

teclado.c

00001 00004 #include "routix/system.h"00005 #include "drivers/teclado.h"00006 #include "drivers/video.h"00007 #include "routix/atomic.h"00008 #include "routix/event.h"00009 #include "routix/8259.h"00010 #include <routix/kstdio.h>00011 00013 unsigned int *keymap = keymap_std;00014 00016 #define MAX_BUFF_TECLADO 1600017 char buff_teclado[MAX_BUFF_TECLADO + 2];00018 char *buff_head = buff_teclado; /* Apunta al lugar donde debo guardar el prox caracter */00019 char *buff_tail = buff_teclado; /* apunta al caracter que debo sacar primero */00020 word buff_cant = 0;00021 00022 char shift=0, alt=0, ctrl=0;00023 char num_lock, caps_lock, scr_lock;00024 00026 #define MAX_BUFF_CONSOLA 3200027 char buff_consola[MAX_BUFF_CONSOLA + 2];00028 char *consola_head = buff_consola; /* Apunta al lugar donde debo guardar el prox caracter */00029 char *consola_tail = buff_consola; /* apunta al caracter que debo sacar primero */00030 word consola_cant = 0;00031 00032 00035 void Teclado(void) 00036 {00037 byte scode;00038 scode = inportb (TECLADO_PORT);00039 00040 if ( buff_cant >= MAX_BUFF_TECLADO ) /* Buffer lleno, no puede guardarse el scancode */00041 goto salir_int_teclado;00042 00043 unsigned int car = _getascii (scode & 0x7F);00044 00045 if (scode >= 0x80 ) /* Breakcode */00046 if ( car!=CTRL && car!=ALT && car!=SHIFT )00047 goto salir_int_teclado; /* Fue el release de un caracter normal... me voy */00048 00049 /* Se presiono alguna combinacion de ALT+F ,switchear de tty en consola*/00050 00051 /*00052 if ( car==F1 && alt) {00053 unsigned long _pos, _cur;00054 _pos = pos;00055 _cur = cursorr;00056 kprintf("Pos: %d Cursor: %d\n", _pos, _cur);00057 }00058 */

Page 285: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00059 /* (TEMPORAL) Si se presiona CTRL + F, poner al shell en ForeGround */00060 /* 00061 if (toupper(car)=='F' && ctrl) {00062 shell_to_fg(); 00063 goto salir_int_teclado;00064 }00065 */ 00066 *buff_head = scode;00067 buff_head++;00068 buff_cant++;00069 if (buff_head == (buff_teclado + MAX_BUFF_TECLADO) ) {00070 buff_head = buff_teclado;00071 }00072 00073 salir_int_teclado:00074 endOfInterrupt(); 00075 }00076 00079 void leer_buff_teclado (void)00080 {00081 unsigned int car;00082 cli(); 00083 while ( (consola_cant <= MAX_BUFF_CONSOLA) && (buff_cant > 0) ) {00084 car = getascii (*buff_tail++);00085 if (buff_tail == (buff_teclado + MAX_BUFF_TECLADO) )00086 buff_tail = buff_teclado;00087 buff_cant--;00088 00089 if (car > 0xff) /* Si el codigo levantado del buffer pertenece a alguna tecla de función */00090 continue; /* o ALT, CTRL, NUM_LOCK, por ahora, no la tengo en cuenta */00091 00092 *consola_head++ = (unsigned char) car;00093 consola_cant++;00094 if (consola_head >= (buff_consola + MAX_BUFF_CONSOLA) ) {00095 consola_head = buff_consola;00096 }00097 }00098 // if (consola_cant>0)00099 // Actualizamos los eventos de TECLADO00100 // actualizar_eventos( TECLADO );00101 00102 sti();00103 00104 }00105 00107 inline unsigned int _getascii (unsigned char code)00108 {00109 return keymap[code];00110 }00111 00116 unsigned int getascii (unsigned char code)00117 {00118 unsigned int *_keymap = keymap;00119 if (shift==1)00120 _keymap = keymap_std_shift;00121

Page 286: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00122 char presionada = 1;00123 unsigned int car = _keymap[code & 0x7F];00124 if ( code >= 0x80 ) { /* tecla fue soltada */00125 presionada = 0; 00126 }00127 00128 switch (car) {00129 case ALT:00130 alt = TRUE & presionada; 00131 car = TECLA_MODIFICADORA;00132 break;00133 case CTRL:00134 ctrl = TRUE & presionada; 00135 car = TECLA_MODIFICADORA;00136 break;00137 case SHIFT: 00138 shift = TRUE & presionada;00139 car = TECLA_MODIFICADORA;00140 break;00141 default: 00142 car = car | alt | ctrl;00143 }00144 00145 return car; 00146 00147 }00148 00149 00150 unsigned char getchar(void)00151 {00152 unsigned char car;00153 while ( consola_cant <= 0 );00154 cli();00155 car = *consola_tail++;00156 if (consola_tail == (buff_consola + MAX_BUFF_CONSOLA) )00157 consola_tail = buff_consola;00158 consola_cant--;00159 sti();00160 return car;00161 }00162 00163 00164 00165 00166 00167 00168 00169 00170 00171 /*00172 unsigned char getchar(void)00173 {00174 event_t *nuevo;00175 char caracter;00176 00177 // Si hay un caracter en el buffer lo devolvemos00178 if ( ptrbufferTeclado >= bufferTeclado ) {00179 __asm__ __volatile__("cli");00180 --ptrbufferTeclado;00181 caracter = *ptrbufferTeclado;00182 __asm__ __volatile__("sti");

Page 287: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00183 return(caracter); 00184 }00185 00186 // Sino agregamos un nodo a la lista de eventos y esperamos00187 00188 // Alocamos un nuevo nodo en memoria00189 nuevo = (event_t *) malloc( sizeof(event_t) );00190 00191 // Error al intentar alocar memoria (setear errno)00192 if ( nuevo == NULL ) {00193 return -1;00194 }00195 00196 // Dispositivo TECLADO00197 nuevo->dispositivo = TECLADO;00198 nuevo->proceso=actual;00199 00200 // Finalmente lo agregamos a la lista de eventos00201 insertar_evento(nuevo);00202 00203 // y nos ponemos a dormir00204 dormir_task(actual);00205 00206 // Switcheamos de proceso mediante la macro _reschedule quien realiza una llamada00207 // a la interrupción 0x5100208 _reschedule();00209 00210 // Volvimos ! Hay por lo menos una tecla en el buffer, eliminamos el nodo de la lista de eventos00211 remover_evento(nuevo);00212 00213 // Liberamos el espacio00214 free(nuevo);00215 00216 // Devolvemos finalmente la tecla ingresada00217 __asm__ __volatile__("cli");00218 --ptrbufferTeclado;00219 caracter = *ptrbufferTeclado;00220 __asm__ __volatile__("sti");00221 00222 return(caracter);00223 }00224 */00225 char *gets(char *s)00226 {00227 unsigned char valor;00228 char *string=s;00229 char flag=1;00230 00231 while ( flag ) {00232 valor = getchar();00233 00234 if ( valor == '\b' ) {00235 if ( string != s ) {00236 string--;00237 putchar(valor);00238 }00239 } 00240 else if ( valor == '\0' ) { flag--; }00241

Page 288: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00242 else {00243 *string++=valor;00244 putchar(valor);00245 if ( valor == '\n' ) { string--; flag--; }00246 }00247 00248 }00249 00250 if ( string == s ) { s=NULL; }00251 else { *string = '\0'; }00252 00253 return s;00254 }00255

Page 289: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

teclado.h

00001 /* teclado.h */00002 00003 #ifndef _TECLADO_H00004 #define _TECLADO_H00005 #define TECLADO_PORT 0x6000006 00007 #define ALT 0x010000008 #define CTRL 0x020000009 #define SHIFT 0x030000010 #define TECLA_MODIFICADORA 0xff0000011 00012 #define CARACTER_LIMITE 0x040000013 00014 #define HOME 000015 #define CURSOR_UP 000016 #define CURSOR_DOWN 000017 #define CURSOR_LEFT 000018 #define CURSOR_RIGHT 000019 00020 #define PAGE_UP 000021 #define PAGE_DOWN 000022 #define INSERT 000023 #define DELETE 000024 #define END 000025 #define ENTER 000026 00027 #define F1 0x100000028 #define F2 (F1 + 1)00029 #define F3 (F1 + 2)00030 #define F4 (F1 + 3)00031 #define F5 (F1 + 4)00032 #define F6 (F1 + 5)00033 #define F7 (F1 + 6)00034 #define F8 (F1 + 7)00035 #define F9 (F1 + 8)00036 #define F10 (F1 + 9)00037 #define F11 (F1 + 10)00038 #define F12 (F1 + 11)00039 00040 #define CAPS_LOCK 0xD00000041 #define NUM_LOCK 0xE00000042 #define SCR_LOCK 0xF00000043 00044 /* Obtiene el ascii de un scancode (en crudo) */00045 inline unsigned int _getascii (unsigned char code);00046 00047 /* Obtiene el ascii de un scancode, teniendo en cuenta los modificadores (CAPS_LOCK, SHIFT, CTRL, etc) */00048 unsigned int getascii (unsigned char code);00049 00050 /* Tabla de caracteres ASCII de un teclado standar */00051 unsigned int keymap_std[] = 00052 {00053 0, 0, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 225, 39, '\b',00054 0, 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '´', '+', '\n',00055 CTRL, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 148, '{', '}', SHIFT, '}',

Page 290: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00056 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '-', SHIFT,00057 '*', ALT, ' ', CAPS_LOCK, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, NUM_LOCK, SCR_LOCK, HOME, CURSOR_UP, PAGE_UP, '-',00058 CURSOR_LEFT, 0, CURSOR_RIGHT, '+', END, CURSOR_DOWN, PAGE_DOWN, INSERT, DELETE, ENTER, 0, '<', F11, F1200059 };00060 00061 /* Tabla de caracteres ASCII (con shift presionado) de un teclado standar */00062 unsigned int keymap_std_shift[] = 00063 {00064 0, 0, '!', '"', '#', '$', '%', '&', '/', '(', ')', '=', 225, 39, '\b',00065 0, 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '¨', '*', '\n',00066 CTRL, 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 148, '[', '^', SHIFT, ']',00067 'Z', 'X', 'C', 'V', 'B', 'N', 'M', ',', ':', '_', SHIFT,00068 '*', ALT, ' ', CAPS_LOCK, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, NUM_LOCK, SCR_LOCK, HOME, CURSOR_UP, PAGE_UP, '-',00069 CURSOR_LEFT, 0, CURSOR_RIGHT, '+', END, CURSOR_DOWN, PAGE_DOWN, INSERT, DELETE, ENTER, 0, '<', F11, F1200070 };00071 00072 #endif

Page 291: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

time.c

00001 /* time.c */00002 00003 #include "routix/time.h"00004 #include "routix/8254.h"00005 #include <routix/kstdio.h>00006 00007 #ifndef __SYSTEM00008 #include "routix/system.h"00009 #endif00010 00011 00012 static char dias_por_mes[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };00013 enum { ENERO, FEBRERO, MARZO, ABRIL, MAYO, JUNIO, JULIO, AGOSTO, SEPTIEMBRE, OCTUBRE, NOVIEMBRE, DICIEMBRE };00014 static time_t reloj=0;00015 00016 00017 byte get_value(word registro)00018 {00019 outportb_p(CMOS_C, registro);00020 return(inportb_p(CMOS_V));00021 }00022 00023 void set_value(word registro, byte valor)00024 {00025 outportb_p(CMOS_C, registro);00026 outportb_p(CMOS_V, valor);00027 }00028 00029 00030 void init_time()00031 {00032 00033 struct tm tm;00034 00035 int year = get_year();00036 year = ( year >= 1970 ) ? 1900+year : 2000+year;00037 year -= 1900;00038 00039 tm.tm_sec = get_sec();00040 tm.tm_min = get_min();00041 tm.tm_hour = get_hour();00042 tm.tm_mday = get_dayofmonth();00043 tm.tm_mon = get_month() - 1;00044 tm.tm_year = year ;00045 tm.tm_wday = get_dayofweek();00046 tm.tm_yday = day_of_year(tm.tm_year, tm.tm_mon, tm.tm_mday);00047 tm.tm_isdst = 0; // Cero por ahora00048 00049 00050 // Seteamos el valor del reloj00051 reloj = mktime( &tm );00052 kprintf("Seteando reloj: %d\n",reloj);00053 }00054 00055 00056

Page 292: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00057 inline void actualizar_reloj()00058 {00059 reloj++;00060 }00061 00062 00063 struct tm *localtime(const time_t *clock)00064 {00065 static struct tm tm;00066 time_t tod;00067 00068 // Valores del momento actual00069 if ( ! clock ) {00070 kprintf("localtime: null tod, seteando tod=reloj (%d ticks)\n",reloj);00071 tod = reloj;00072 }00073 00074 // Hay un tod especificado00075 else {00076 kprintf("localtime: tod especificado, tod=*clock (%d ticks)\n",*clock);00077 tod = *clock;00078 }00079 00080 // Calculamos el año00081 for ( tm.tm_year=ANIO_INICIO; (tod -= SEC_PER_YEAR(1900+tm.tm_year)) > 0; tm.tm_year++ ) ;00082 // Corregimos por el error en la última resta del for00083 tod += SEC_PER_YEAR(1900+tm.tm_year);00084 00085 // Calculamos el mes00086 for ( tm.tm_mon=MES_INICIO; (tod -= SEC_PER_MONTH(tm.tm_year,tm.tm_mon)) > 0; tm.tm_mon++ ) ;00087 // Corregimos por el error en la última resta del for00088 tod += SEC_PER_MONTH(tm.tm_year,tm.tm_mon);00089 00090 00091 tm.tm_mday = (time_t) (tod / SEC_PER_DAY);00092 tod -= (tm.tm_mday * SEC_PER_DAY);00093 tm.tm_mday++;00094 00095 tm.tm_hour = (time_t) (tod / SEC_PER_HOUR);00096 tod -= (tm.tm_hour * SEC_PER_HOUR);00097 00098 tm.tm_min = (time_t) (tod / SEC_PER_MIN);00099 tm.tm_sec = tod - (tm.tm_min * SEC_PER_MIN);00100 00101 return &tm;00102 }00103 00104 00105 00106 int day_of_year(int anio, int mes, int dia)00107 {00108 int tmp;00109 int dias=dia;00110 00111 // Recorremos los meses00112 for ( tmp=0; tmp < mes; tmp++)00113 dias += dias_por_mes[tmp];

Page 293: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00114 00115 // Correcion por año bisiesto00116 if ( (mes > FEBRERO) && es_bisiesto(1900+anio) ) dias++;00117 00118 return dias;00119 }00120 00121 00122 00123 // Calculo del tod00124 // el tod representa la cantidad de segundos transcurridos desde un momento hasta el00125 // 1 de enero de 1970.00126 // Para entender la forma de calcularlo veamos un ejemplo:00127 // queremos calcular el tod de la fecha: 25/09/1979 07:49:1500128 //00129 // bien, primero que todo:00130 //00131 // 1979 - 1970 = 9 años transcurridos00132 // 70-71 -- 71-72 -- 72-73 -- 73-74 -- 74-75 -- 75-76 -- 76-77 -- 77-78 -- 78-7900133 // o sea que la cantidad de segundos hasta el inicio del 79 son:00134 //00135 // tod += 9 * 365 * 24 * 60 * 6000136 //00137 // bien, no olvidemos los años bisiestos, que desde el 70 al 78 son 1972 - 197600138 // con lo que ajustando el tod anterior tenemos:00139 //00140 // tod += 2 * 1 * 24 * 60 * 60 dos días de ajuste00141 //00142 // Bien, ahora debemos calcular la cantidad de segundos desde el Enero de 1979 hasta Septiembre de 197900143 // tod += dias_por_mes[ENERO] * 24 * 60 * 60 + dias_por_mes[FEB] * 24 * 60 * 60 + ... + dias_por_mes[AGOS] * 24 * 60 * 6000144 // como antes, si el año es bisiesto y SI PASAMOS POR FEBRERO debemos corregir:00145 // tod += 1 * 24 * 60 * 6000146 //00147 // Ahora, la cantidad de segundos desde el 1ero de Septiembre al 25 de Septiembre00148 // tod += 24 * 24 * 60 * 6000149 // 00150 //00151 // Ahora la cantidad de segundos desde las 00:00 del 25 de Septiembre a las 07:00 del mismo00152 // tod += 7 * 60 * 6000153 //00154 // Ahora la cantidad de segundos desde los 0 minutos hasta los 49 minutos00155 // tod += 49 * 60;00156 //00157 // Finalmente sumamos la cantidad de segundos:00158 // tod += 1500159 //00160 // y obtuvimos el tod buscado.00161 time_t mktime(struct tm *tm)00162 {00163 int tmp;00164 time_t tod=0;

Page 294: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00165 00166 for ( tmp=ANIO_INICIO; tmp < tm->tm_year ; tmp++ )00167 tod += SEC_PER_YEAR(1900+tmp);00168 00169 for ( tmp=MES_INICIO; tmp < tm->tm_mon ; tmp++ )00170 tod += SEC_PER_MONTH(tm->tm_year,tmp);00171 00172 tod += (tm->tm_mday - 1) * SEC_PER_DAY + tm->tm_hour * SEC_PER_HOUR + tm->tm_min * SEC_PER_MIN + tm->tm_sec;00173 00174 return tod;00175 }00176 00177 00178 00179 00180 00181 // Los años bisiestos son todos los divisibles por 4 suprimiendo los divisibles por 10000182 // y no divisibles por 400 ( la regla de calculo es válida desde 1582 ).00183 int es_bisiesto(int year)00184 {00185 if ( (!(year%4)) && (year%100) ) { return 1; }00186 else if ( !(year%400) ) { return 1; }00187 else return 0;00188 }00189 00190 char *dias[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };00191 char *mes[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };00192 00193 00194 char *asctime(const struct tm *tm)00195 {00196 00197 static char string[26];00198 00199 //kprintf("%s %s %d %d:%d:%d %d\n", dias[tm->tm_wday], mes[tm->tm_mon], tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, (1900 + tm->tm_year) );00200 kprintf("%s %s %d %d:%d:%d %d\n", dias[0], mes[tm->tm_mon], tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, (1900 + tm->tm_year) );00201 00202 string[26]='\0';00203 00204 return string;00205 }00206

Page 295: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

time.h

00001 /* time.h */00002 00003 #ifndef __SYSTEM00004 #include "routix/system.h"00005 #endif00006 00007 #define CMOS_C 0x7000008 #define CMOS_V 0x7100009 00010 00011 #define CUR_SEC 000012 #define CUR_MIN 200013 #define CUR_HOUR 400014 #define CUR_DAYOFWEEK 600015 #define CUR_DAYOFMONTH 700016 #define CUR_MONTH 800017 #define CUR_YEAR 900018 #define STAT_REG_A 0xa00019 #define STAT_REG_B 0xb 00020 00021 #define bcdtochar(valor) (valor - 6 * (byte) (valor/16))00022 #define chartobcd(valor) (valor % 10 + ( ( (byte) valor / 10 ) << 4 ))00023 00024 #define get_hour() bcdtochar(get_value(CUR_HOUR))00025 #define get_min() bcdtochar(get_value(CUR_MIN))00026 #define get_sec() bcdtochar(get_value(CUR_SEC))00027 #define get_dayofweek() bcdtochar(get_value(CUR_DAYOFWEEK))00028 #define get_dayofmonth() bcdtochar(get_value(CUR_DAYOFMONTH))00029 #define get_month() bcdtochar(get_value(CUR_MONTH))00030 #define get_year() bcdtochar(get_value(CUR_YEAR))00031 #define get_stat_reg_a() get_value(STAT_REG_A)00032 #define get_stat_reg_b() get_value(STAT_REG_B)00033 00034 #define set_hour(valor) set_value(CUR_HOUR, chartobcd(valor))00035 00036 00037 // Defines de funciones de tiempo00038 #define ANIO_INICIO 7000039 #define MES_INICIO 000040 #define DIA_INICIO 100041 00042 #define SEC_PER_MIN (60)00043 #define SEC_PER_HOUR (60 * SEC_PER_MIN)00044 #define SEC_PER_DAY (24 * SEC_PER_HOUR)00045 #define SEC_PER_YEAR(anio) ( ( 365 + es_bisiesto(anio) ) * SEC_PER_DAY )00046 #define SEC_PER_MONTH(anio,mes) ( dias_por_mes[mes] + ( ( (mes == FEBRERO) && es_bisiesto(1900+anio) ) ? 1 : 0 ) ) * SEC_PER_DAY00047 00048 00049 // Estructura tm00050 struct tm {00051 int tm_sec; /* seconds after the minute - [0, 61] */00052 /* for leap seconds */

Page 296: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00053 int tm_min; /* minutes after the hour - [0, 59] */00054 int tm_hour; /* hour since midnight - [0, 23] */00055 int tm_mday; /* day of the month - [1, 31] */00056 int tm_mon; /* months since January - [0, 11] */00057 int tm_year; /* years since 1900 */00058 int tm_wday; /* days since Sunday - [0, 6] */00059 int tm_yday; /* days since January 1 - [0, 365] */00060 int tm_isdst; /* flag for alternate daylight savings time */00061 };00062 00063 typedef int time_t;00064 00065 // Definimos los tipos00066 struct tm *localtime(const time_t *clock);00067 time_t mktime(struct tm *tm);00068 int day_of_year(int anio, int mes, int dia);00069 char *asctime(const struct tm *tm);00070 00071 inline void actualizar_reloj();00072 int es_bisiesto(int year);00073

Page 297: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

timer.c

00001 /* timer.c */00002 00003 /* Manejo de la interrupcion de timertick y timers */00004 00005 #include <routix/system.h>00006 #include <routix/8254.h>00007 #include <routix/8259.h>00008 #include <routix/debug.h>00009 #include <routix/task.h>00010 #include <routix/kalloc.h>00011 #include <routix/time.h>00012 #include <routix/sched.h>00013 #include <routix/atomic.h>00014 #include <routix/timer.h>00015 #include <sys/list.h>00016 00017 // ojo que los jiffies podrian tener un overflow !00018 // a los 497 dias de estar corriendo00019 dword jiffies=0;00020 00021 // Puntero al inicio de la lista de timers00022 volatile timer_t *timer_inicio=NULL;00023 00024 // Lista de timers00025 LIST_NEW(timer_t) timer_list = LIST_INITIALIZER;00026 00027 void actualizar_timers(void);00028 inline static int insert_timer(timer_t *nuevo);00029 inline static int remove_timer(timer_t *timer);00030 00031 00032 void timertick_handler()00033 {00034 00035 endOfInterrupt();00036 00037 // Incrementamos el contador de jiffies00038 jiffies++;00039 00040 // Actualizamos el reloj00041 if ( ! (jiffies % FINTERRUPCION) ) actualizar_reloj(jiffies);00042 00043 // Revisamos los timers00044 actualizar_timers();00045 00046 // Chequeamos si el floppy tiene algo pendiente, en realidad colocarlo00047 // aca tiene un bajo rendimiento, solo para pruebas00048 floppy_procesar_buffer();00049 00050 // Verificamos si hay actualmente una tarea corriendo antes de modificar00051 // sus estadisticas00052 if ( actual ) {00053 // Actualizamos la cuenta del proceso actual00054 actual->cuenta -= 1;00055 actual->tiempo_cpu++;00056

Page 298: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00057 // Si se venció la cuenta, la reestablecemos y pasamos el control al scheduler00058 if ( actual->cuenta <= 0 ) {00059 // Reiniciamos la cuenta00060 actual->cuenta = actual->prioridad;00061 scheduler();00062 __asm__ ("nop");00063 }00064 }00065 00066 // Si no la hubiese, devolvemos el control al scheduler00067 else {00068 scheduler();00069 }00070 00071 }00072 00073 /*00074 void actualizar_timers(void)00075 {00076 timer_t *tmp;00077 00078 // Chequeamos si hay timers activos00079 if ( timer_inicio == NULL ) {00080 return;00081 } 00082 00083 for ( tmp=timer_inicio; tmp != NULL; tmp = tmp->proximo ) {00084 00085 // Debe estar pendiente (ver timer.h) y haber vencido su cuenta00086 if ( (tmp->estado==PENDIENTE) && (--(tmp->ticks) <= 0) ) {00087 00088 // Ejecutamos la funcion establecida00089 (*(tmp->func))(tmp);00090 00091 // Seteamos su estado como finalizado00092 tmp->estado=FINALIZADO;00093 }00094 00095 }00096 00097 }00098 */00099 00100 00101 void actualizar_timers(void)00102 {00103 timer_t *tmp;00104 timer_t *toclean;00105 00106 // Recorremos la lista procesando los timers vencidos hasta encontrar uno más grande00107 for(tmp=HEADER_NEXT(timer_list); tmp ;) {00108 00109 if ( TIMER_TICKS(tmp) > jiffies )00110 break;00111 00112 // Llamamos a la función seteada en el timer00113 (*(TIMER_FUNCTION(tmp)))(tmp);00114

Page 299: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00115 // Lo elimina de la lista00116 LIST_DEL(timer_list,timer_list,tmp);00117 00118 toclean=tmp;00119 00120 // buscamos el nodo siguiente00121 tmp=LIST_NEXT(timer_list,tmp);00122 00123 // y lo eliminamos00124 clean_timer(toclean);00125 00126 }00127 00128 }00129 00130 00131 spinlock_t timer_lock = 1;00132 00133 /*00134 int insertar_timer(timer_t *nuevo)00135 {00136 // Deshabilitamos Interrupciones00137 cli();00138 00139 timer_t *tmp;00140 00141 if ( nuevo == NULL ) { return 0; }00142 00143 // Nos paramos al ppio de la lista00144 tmp = timer_inicio;00145 00146 if ( timer_inicio == NULL ) { timer_inicio = nuevo; }00147 00148 else {00149 00150 // Buscamos la última tarea00151 for ( tmp = timer_inicio; tmp->proximo != NULL ; tmp = tmp->proximo );00152 00153 // Nos colgamos de ella00154 tmp->proximo = nuevo;00155 }00156 00157 // La nueva tarea queda apuntando a NULL00158 nuevo->proximo = NULL;00159 00160 // Pendiente de ejecucion00161 nuevo->estado=PENDIENTE;00162 00163 // Habilitamos Interrupciones00164 sti();00165 00166 return 1;00167 }00168 */00169 00170 00171 inline static int insert_timer(timer_t *nuevo)00172 {00173 // Deshabilitamos Interrupciones00174 START_ATOMIC_OPERATION;

Page 300: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00175 00176 timer_t *tmp;00177 00178 if ( nuevo == NULL ) { return 0; }00179 00180 // Buscamos el primer nodo que posea un tiempo mayor al tiempo del nodo nuevo00181 // de manera que la lista siempre este ordenada de menor a mayor00182 00183 // Si la lista está vacia lo insertamos al ppio00184 //if ( LIST_EMPTY(timer_list) ) {00185 // LIST_ADD(timer_list,timer_list,nuevo);00186 //}00187 00188 // Sino buscamos en el listado de timers00189 //else {00190 00191 LIST_FOREACH(tmp,timer_list,timer_list) {00192 00193 // Dejamos ">=" como criterio así la búsqueda concluye lo antes posible, ya que no importa00194 // si queda al ppio o final de un grupo de nodos con el mismo tiempo.00195 if ( TIMER_TICKS(tmp) >= TIMER_TICKS(nuevo) )00196 break;00197 }00198 00199 // Si no encontramos ningún nodo con tiempo mayor colocamos nuestro nuevo nodo al final de la lista00200 if ( tmp==NULL ) {00201 LIST_ADD_TAIL(timer_list,timer_list,nuevo);00202 }00203 00204 // lo insertamos antes de nuestro nodo encontrado00205 else {00206 LIST_INSERT_BEFORE(timer_list,timer_list,tmp,nuevo);00207 }00208 00209 //}00210 00211 // Habilitamos Interrupciones00212 FINISH_ATOMIC_OPERATION;00213 00214 return 1;00215 }00216 00217 /*00218 int remover_timer(timer_t *timer)00219 {00220 cli();00221 00222 timer_t *tmp;00223 00224 // Es el primer timer ?00225 if ( timer == timer_inicio ) {00226 timer_inicio = timer->proximo;

Page 301: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00227 sti();00228 return 0;00229 }00230 00231 // Buscamos nuestro timer entonces00232 for ( tmp=timer_inicio; (tmp->proximo != timer) && (tmp != NULL) ; tmp = tmp->proximo ) ;00233 00234 // Si no encontramos el timer devolvemos error00235 if ( tmp == NULL ) {00236 // Lo tengo que reemplazar por la constante correcta según la definición de errno.h00237 sti();00238 return -1;00239 }00240 00241 else {00242 tmp->proximo = timer->proximo;00243 }00244 00245 // Lo tengo que reemplazar por la constante correcta según la definición de errno.h00246 sti();00247 return 0;00248 00249 }00250 00251 */00252 00253 inline static int remove_timer(timer_t *timer)00254 {00255 // Deshabilitamos Interrupciones00256 START_ATOMIC_OPERATION;00257 00258 timer_t *tmp;00259 00260 // Este bloque de cod es opcional y permite que se realice un chequeo adicional00261 // a la hora de borrar un timer, verificando que exista en la lista00262 #ifdef SECURE_TIMER_OPER00263 // Buscamos si realmente existe el timer, para evitar problemas de inconsistencias00264 LIST_FOREACH(tmp,timer_list,timer_list) {00265 if ( tmp==timer )00266 break;00267 }00268 00269 // EL timer no existe en la lista !!00270 if ( tmp==NULL ) {00271 FINISH_ATOMIC_OPERATION;00272 return -1; 00273 }00274 00275 #endif00276 00277 // Lo eliminamos00278 LIST_DEL(timer_list,timer_list,timer);00279 00280 // Habilitamos Interrupciones00281 FINISH_ATOMIC_OPERATION;

Page 302: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00282 00283 return 0;00284 00285 }00286 00287 00288 inline timer_t *create_timer(dword ticks, task_struct_t *proceso, void (*func)(struct timer_t *info), void *data)00289 {00290 timer_t *timer = (timer_t *) malloc(sizeof(timer_t));00291 00292 if ( timer==NULL)00293 return NULL;00294 00295 TIMER_TICKS(timer)=jiffies+ticks;00296 TIMER_PROCESS(timer)=proceso;00297 TIMER_FUNCTION(timer)=func;00298 TIMER_DATA(timer)=data;00299 00300 insert_timer(timer);00301 00302 return timer;00303 }00304 00305 inline int clean_timer(timer_t *timer)00306 {00307 // Chequeamos primero que recibimos un timer 00308 if ( timer==NULL )00309 return -1;00310 00311 // Lo sacamos de la lista de timers00312 00313 // Si no lo pudimos remover (no existe por ejemplo) retornamos con error00314 if ( remove_timer(timer) == -1 )00315 return -1;00316 00317 // Liberamos la memoria la memoria00318 free(timer);00319 00320 return 1;00321 }00322 00323 00326 inline void timer_dump(void)00327 {00328 timer_t *tmp;00329 00330 START_ATOMIC_OPERATION;00331 00332 kprintf("Pid\n");00333 LIST_FOREACH(tmp,timer_list,timer_list) {00334 kprintf("%d\n", TASK_PID(TIMER_PROCESS(tmp)));00335 }00336 00337 FINISH_ATOMIC_OPERATION;00338 00339 }

Page 303: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

timer.h

00001 /* timer.h */00002 00003 #include <routix/system.h>00004 #include <routix/task.h>00005 00006 00007 #ifndef __TIMER00008 #define __TIMER00009 00010 extern dword jiffies;00011 00012 00013 // Habilitamos el modo seguro de remoción de timers donde se realiza00014 // su búsqueda previa antes de eliminarse00015 #define SECURE_TIMER_OPER00016 00017 00018 typedef struct timer_t {00019 dword ticks;00020 task_struct_t *process;00021 void (*func)(struct timer_t *); 00022 00023 void *data; 00024 00025 LIST_DATA(timer_t) timer_list; 00026 00027 } timer_t; 00028 00029 #define TIMER_TICKS(t) ((t)->ticks)00030 #define TIMER_PROCESS(t) ((t)->process)00031 #define TIMER_FUNCTION(t) ((t)->func)00032 #define TIMER_DATA(t) ((t)->data)00033 #define TIMER_STATE(t) ((t)->state)00034 00035 00036 void actualizar_timers(void);00037 inline timer_t *create_timer(dword ticks, task_struct_t *proceso, void (*func)(struct timer_t *info), void *data);00038 inline int clean_timer(timer_t *timer);00039 00040 inline void timer_dump(void);00041 00042 00043 #define TIMER_USEGUNDOS(segundos) (segundos/10000)00044 #define USECONDS_TO_TICKS(useconds) ((useconds)/10000)00045 00046 #endif

Page 304: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

types.h

00001 00002 00003 #ifndef __ROUTIX_TYPES00004 #define __ROUTIX_TYPES00005 00006 #define NULL 000007 00008 #define TRUE 100009 #define FALSE 000010 00011 #define OK 000012 00013 00014 typedef unsigned char byte;00015 typedef unsigned short word;00016 typedef unsigned long dword;00017 typedef unsigned long long qword;00018 00019 typedef dword addr_t;00020 typedef long size_t;00021 typedef unsigned long ssize_t;00022 00023 typedef short int pid_t;00024 00025 typedef unsigned long long int ticks_t;00026 00027 #endif

Page 305: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

video.c

00001 00005 #include "routix/system.h"00006 #include <routix/kstdio.h>00007 #include <drivers/video.h>00008 00009 #define VIDEO (0xb8000)00010 00011 #define TAB_SPACES 400012 00013 unsigned char *pos = (unsigned char *) VIDEO;00014 unsigned char cursor_caracteristicas = 2;00015 00016 #define VIDEO_LAST_LINE 384000017 00018 #define nextpos(pos) if ( (pos+=2) > (unsigned char *) VIDEO+4000 ) { \00019 scroll_up(); \00020 pos = (unsigned char *) (VIDEO + VIDEO_LAST_LINE); \00021 } 00022 00023 00024 00025 int putchar ( int a )00026 {00027 00028 // __asm__ __volatile__("cli");00029 00030 if ( a == '\n' ) {00031 int frac;00032 int newpos;00033 frac = (int) (pos-VIDEO)/160;00034 newpos = (VIDEO+160*(frac+1)); 00035 if ( newpos >= VIDEO+4000 ) {00036 scroll_up();00037 pos = (unsigned char *) ( VIDEO + VIDEO_LAST_LINE );00038 }00039 else 00040 pos=(unsigned char *) newpos;00041 }00042 else if ( a == '\t' ) {00043 int i;00044 for (i=0; i<4; i++ ) 00045 // pos=nextpos(pos);00046 nextpos(pos);00047 }00048 else if ( a == '\b' ) {00049 pos-=2;00050 *pos=' ';00051 *(pos+1) = cursor_caracteristicas;00052 }00053 00054 else { 00055 *pos = (unsigned char) a; 00056 *(pos+1) = cursor_caracteristicas;00057 // pos=nextpos(pos);

Page 306: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00058 nextpos(pos);00059 }00060 00061 // __asm__ __volatile__("sti");00062 00063 refresh_cursor( ((pos - (unsigned char *)VIDEO) /2) );00064 00065 // refresh_cursor( getvar("cursor"));00066 return a;00067 }00068 00069 00070 00071 00072 int puts ( const char *s )00073 {00074 int cantidad=0;00075 00076 while ( *s ) {00077 putchar(*s++);00078 cantidad++;00079 }00080 00081 return cantidad;00082 }00083 // VIDEO_LAST_LINE 80*24*200084 /*00085 #define VIDEO_LAST_LINE 384000086 00087 unsigned char *nextpos ( unsigned char *posicion )00088 {00089 unsigned char *pos=posicion;00090 00091 pos += 2;00092 00093 if ( pos >= (unsigned char *) VIDEO+4000 ) {00094 scroll_up();00095 pos = (unsigned char *) ( VIDEO + VIDEO_LAST_LINE );00096 }00097 return pos;00098 }00099 */00100 00101 00102 00103 void clrscr (void)00104 {00105 int i;00106 unsigned char *ptr;00107 00108 ptr = (unsigned char *) VIDEO;00109 00110 for (i=0; i<4000; i+=2 ) {00111 *(ptr+i) = ' ';00112 *(ptr+i+1) = 2;00113 }00114 00115 pos = (unsigned char *) VIDEO;00116 }00117

Page 307: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

00118 void scroll_up ( void )00119 {00120 unsigned char *inicio =(unsigned char *) VIDEO + 160;00121 unsigned char *destino=(unsigned char *) VIDEO;00122 int count;00123 00124 cli();00125 00126 __asm__ __volatile__ ("cld ; rep ; movsw" : : "c" (VIDEO_LAST_LINE), "S" (inicio) , "D" (destino));00127 /*00128 for ( count=0; count < VIDEO_LAST_LINE; count++ ) {00129 *destino++ = *inicio++;00130 }00131 */ 00132 00133 00134 destino += VIDEO_LAST_LINE;00135 for ( count=0; count < 80; count ++ ) {00136 *destino++ = ' ';00137 *destino++ = cursor_caracteristicas;00138 }00139 00140 sti();00141 }00142 00143 00144 00145 00146 unsigned char *gotoxy ( int fila, int columna)00147 {00148 if ( (fila > 25) || (columna > 80) ) { return NULL; }00149 pos = (unsigned char *) (VIDEO + (fila-1)*2*80+2*(columna-1) );00150 return pos;00151 }00152 00153

Page 308: Universidad Tecnológica Nacional Web viewint kmapmem ( addr_t fisica, addr_t logica, addr_t directorio, word atributo Existen bastantes funciones auxiliares dentro del memory manager,

video.h

00001 /* video.h */00002 00003 #define VIDEO_BASE 0xB800000004 00005 /* Registros del Controlador de Video (escritura)*/00006 #define PORT_VIDEO_REG_WR 0x3d400007 #define PORT_VIDEO_VALUE_WR 0x3d500008 00009 /* Registros del Controlador de Video (de lectura)*/00010 #define PORT_VIDEO_REG_RD 0x3d400011 #define PORT_VIDEO_VALUE_RD 0x3d500012 00013 #define VIDEO_LOCATION 0xc00014 #define CURSOR_LOCATION 0xe00015 00016 /* Enviar el word "valor" al "registro" del 6845 */00017 #define setword_vga(registro,valor) {cli(); \00018 outportb (PORT_VIDEO_REG_WR, registro); \00019 outportb (PORT_VIDEO_VALUE_WR, (((word)valor)>>8) & 0xFF); \00020 outportb (PORT_VIDEO_REG_WR, registro + 1); \00021 outportb (PORT_VIDEO_VALUE_WR, (byte) (valor) ); \00022 sti(); }00023 00024 /* Enviar el byte "valor" al "registro" del 6845 */00025 #define setbyte_vga(registro,valor) {cli(); \00026 outportb (PORT_VIDEO_REG_WR, registro); \00027 outportb (PORT_VIDEO_VALUE_WR, valor ); \00028 sti(); } 00029 00030 /* Ubica al cursor en la posicion indicada por "cursor_video" */00031 //#define refresh_cursor() setword_vga(CURSOR_LOCATION, consola->posicion_cursor);00032 #define refresh_cursor(offset) setword_vga(CURSOR_LOCATION, offset)00033 00034 #define video_location(pos) setword_vga(VIDEO_LOCATION, pos)