Tras mucho tiempo inactivo doi por finalizada esta práctica poniendo las claves que la desarrollan aunque algunos ya la hayan entegregado.
Los cambios han de realizarse en los ficheros:
proc.h
main.c
do_fork.c
proc.c
Yo opino que el orden de los ficheros a modificar debe ser ese para poder comprender el resultado de las pruebas.
Antes de comenzar a desarrollar la prácita se me pasaron por la cabeza una solución así que os la voy a contar para que veais porque no la he utilizado.
SOLUCIÓN 1 (NO APTA)
Se nos pide asignar a cada proceso una antiguedad, y a mi se ocurrió después de observar el fichero PROC.H que podía añadir un campo al registro que identificaba a cada descriptor de proceso.
Mi idea era "idealmente" correcta pero tenía 1 defecto: NO EREA VIABLE.
Pensando, pensando se me ocurrió que podría no funcionar por 2 motivos:
PRIMER MOTIVO:
Que en algún sitio se compruebe el tamaño de la estructura con el que TANENBAUM espera que tenga por ejemplo con la sentencia
sizeof.
sizeof ( struct proc );
Este primer dilema no he podido demostrarlo ya que no me puesto a buscarlo, así que vamos por el siguiente.
SEGUNDO MOTIVO:
Minix es un Sistema Operativos por lo tanto a veces las estructuras que nosotros vemos como tales, él no las interpreta como estructuras, sino que no siempre se accede a un registro de la siguiente forma:
REGISTRO.CAMPO
Como parte del código de MINIX está escrito en ensamblador, y éste no conoce de registros y campos, para acceder a ellos se hace lo siguiente BASE + DESPLAZAMIENTO y así obtiene el campo que está buscando, logicamente BASE es la dirección de la estructura y desplazamiento hace referencia al campo que está buscando.
La BASE será la dirección del puntero struct proc y el desplazamiento para acceder al primer campo será 0 al segundo el tamaño del campo 1 ... y así sucesivamente. Espero no haberme equivocado.
Como esto es en realidad lo que ocurre, no podemos añadir un campo a STRUCT PROC cuando a nosotros nos de la gana ya que el código ensamblador no está informado de esos cambios y accede de la forma BASE + DESPLAZAMIENTO y entonces se hace la picha un lío.
Como ya sabemos por que falla la solución 1, vamos a redarctar la solución 2.
SOLUCIÓN 2 (LA CORRECTA):
En esta solución vamos a dividirla en varios pasos:
1.- Modificar proc.h
2.- Modificar main.c
3.- Modificar do_fork.c
4.- Modificar proc.c
5.- Prueba 1
6.- Prueba 2
7.- Prueba 3
8.- Conclusiones
1.- Modificar proc.h
En este caso debemos crearnos la estructura que nos indique como guardar la antiguedad. Digamos que el dibujo podría ser un array y la flecha una variable que nos indique cual ha sido la última antiguedad que hemos asignado.
2.- Modificar main.c
Aquí debemos solamente hacer 2 cosas inicializar procesos de la imagen de memoria, y establecer cual va a ser la antiguedad del siguiente proceso que se ejecute.
Vamos por pasos, en la imagen se ve el bucle que recorre los 12 procesos que tiene MINIX en memoria, y vosotros os preguntareis porque 12 y no 345432 procesos, pues muy facil, utilizamos el script de siempre:
find . -name '*.[ch]' -exec grep 'NR_BOOT_PROC' \; -print
Se obtiene como resultado:
Como vemos está formado por
NR_TASKS + INIT_PROC_NR + 1
Otra vez seguimos sin saber el valor de INIT_PROC_NR pues a lo mismo:
find . -name '*.[ch]' -exec grep 'INIT_PROC_NR' \; -print
Dando como resultado:
4 + 7 + 1 = 12
Si queremos estar seguros de que hay 12 procesos en memoria y que el resto ya son procesos de usuario nos aseguramos de que estamos en el primer tty, por lo que pulsamos ALT+F1, ahora pulsamos F1 y vemos la tabla de procesos:
Como vemos en la siguiente imagen los procesos residentes en memoria estan marcados del -4 al 17 (12 procesos)
El proceso IDLE aparece entre paréntesis, las tareas entre corches y el resto son valores del 0 a ..., como vemos esto nos ayuda bastante a la realización de la práctica. Además si pulsamos F3 vemos con más exactitud los procesos de la imagen de memoria.
Ahora que ya sabemos lo que hay que hacer en main.c podemos continuar, pero sin antes hacer un pequeño resumen. Primero debemos recorrer los procesos de la imagen de memoria y darles su prioridad y por último indicarle a nuestra variable cual es la última prioridad que hemos indicado.
Esta forma de hacerla no es la ideal tambien podemos guardar en nuestra variable la prioridad siguiente o lo que queramos. Además debemos saber que no es necesario inicializar todo el array a 0 es decir los 104 elementos.
3.- Modificar do_fork.c
En este apartado que es el más sencillo debemos decirle al array que el proceso que se acaba de crear (RPC) tiene una prioridad de ....
Aquí teneis que tener en cuenta el desplazamiento que se produce con los procesos. Los procesos empiezan a numerarse por el -4 y nuestro array comienza a numerarse por 0, por lo que debemos ser cuidadosos de no hacer los siguiente:
ARRAY[ -4 ] = PRIORIDAD
Como vemos esto es absurdo y hay que tenerlo en cuenta, para solucionarlos sabed que la constante del kernel NR_TASKS tiene valor 4.
4.- Modificar proc.c
En el proc.c también la modificacion es muy sencilla pero debemos acordarnos de ESTRUCTURA DE DATOS I y II y de los punteritos, aquí debemos hacer un algoritmo que ordene elementos en una lista con cabecera y final pero teniendo en cuenta que el ultimo proceso de la lista no a punta a FINAL sino a NIL_PROC.
Mi recomendación es que os aprovecheis del código de MINIX y hagais solo la parte complicada dejando por ejemplo el código original para rellenar la lista cuando está vacia. En el siguiente código de MINIX que se muestra he dejado la función ENQUEUE peladita para que vosotros solo toqueis la parte que está en rojo y creeis el código necesario para insertar de forma ordenada.
5.- Prueba 1
Para realizar la primera prueba:
cc -o p1.out prueba-1.c
Para ejecutarla:
./p1.out
El resultado que debe dar es:
1.....................2........................
Porque pues basicamente ya que lo que hace el código es dado un proceso padre con número 1 crear un proceso hijo con índice 2 y logicamente el padre se debe mostrar antes que el hijo ya que nuestra prioridad es por orden de creación, el que antes se cree antes se debe ejecutar y el padre ha sido creado antes que el hijo.
6.- Prueba 2
cc -o p2.out prueba-2.c
Para ejecutarla:
./p2.out
El resultado que debe dar es:
Se crea el proceso padre.
Se crea el proceso hijo.
Se ejecuta antes el padre que el hijo.
El padre espera un segundo.
Se ejecuta el hijo e imprime 11111111...
Se ejecuta el padre e imprime 222222222.....
Temina de ejecutar se el hijo con 111111....
7.- Prueba 3
cc -o p3.out prueba-3.c
Para ejecutarla:
./p3.out
El resultado que debe dar es:
El proceso padre crea un total de n hijos por los que el resulado debe ser:
Primero el padre, luego el primer hijo, despues el segundo, .... es decir:
111...222...333...444...555...666...777...nnn
Sabía que se me olvidaba algo, en la función ENQUEUE hay que hacer una cosita con la llamada a la función SCHED, dicha función lo que hacía era modificar la prioridad de un proceso, es decir mover a un proceso de su cola, por lo que hay que acordarse de eso si vemos que hace cosas raras, ya que solo debe existir una cola. ESPERO ESTAR SEGURO DE TODO ESTO LO QUE DIGO.
8.- Conclusiones
Esto es todo amigos hasta nuestra siguiente entrega.
Sau2.
Muchas gracias por el curro, como guía viene fenomenal para centrarse exactamente en lo que tenemos que hacer. Lo dicho, MUCHAS GRACIAS
ResponderEliminarEntonces la funcion sched se deja como *front = TRUE ¿?.
ResponderEliminarVas a tener q ingresarlo en la lista igual, con o sin quantum ...
Vamos a ver si dejas *FRONT a TRUE le estas indicando que inserte en la cola correspondiente por delante, esa es la filosofía de esa variable, pero el sentido de esta práctica es totalmente diferente, esa variable es indiferente, ya que tu tienes que insertar elementos en la cola de forma ordenada. Tanto por delante como por detras como en medio.
ResponderEliminarLa función SCHED básicamente lo que es hace o no modifica la priridad de un proceso o le baja la prioridad, entonces como nosotros queremos insertar todos los procesos en la misma prioridad, ó eliminas la línea donde se le baja la prioridad o le dices a la función ENQUEUE que Q es la prioridad de RP.
Espero haberte ayudado, ya que blanco y en botella ....
Pues si me has ayudado, descarto que sched tenga algo que ver en que no funcione la planificacion...
ResponderEliminarMi problema está en el bucle para recorrer la lista , sobre todo porque no es fácil hacer una traza para hacer un mínimo seguimiento.
Seguiré en ello.
Gracias ael!
Pues por eso no te preocupes, lo que tienes que hacer es cojerte un algoritmo de inserción en una lista y ya está, además en esta profesión NUNCA HAGAS ALGO QUE YA ESTÉ HECHEO, es decir que si puedes ahorrarte desarrollar un windows version XXXXPPPPP pues mejor.
ResponderEliminarEn EDI o EDII seguro que habrás hecho miles de algoritmos de ese estilo. O por internet.
jajaja, recibido.
ResponderEliminarEse era el planB, con lo cuco que me habia quedado lo mio...
Una vez mas... muchas gracias !
No desesperes si te dijera yo la de cosas que se me habían ocurrido para esta práctica.... y tube de desechar.
ResponderEliminarHola.
ResponderEliminarNo entiendo muy bien cómo modificas el proc.h.
Un array de qué? si es con todos los procesos qué tamaño le pones?
un saludo y gracias por el excelente trabajo y ayuda
Tienes que poner un array de enteros con tamaño (num_tareas+num_procesos), en el cual metemos el orden de creación (antigüedad) de cada proceso.
ResponderEliminarTambien necesitamos un variabe global que nos indique el último número utilizado (antigüedad).
Hola.
ResponderEliminarYo sigo sin entender porque hay que crear un array de enteros con tamaño (num_tareas+numprocesos) ya que el numero de procesos que manejaremos es variable y nunca sabremos el tamaño fijo del array.
Y si vamos a usar una variable para movernos dentro del array simplemente para meter dentro del array ese mismo numero (antiguedad) ¿por que creamos ese array y no nos quedamos solo con esa variable que nos dice la antiguedad?
Como ves haelsite estoy bastante perdido con eso el resto de la practica creo que no tiene mayor complicacion.
Gracias.
CREO QUE ME HE PASAO CON ESTE COMENTARIO DE TOCHO QUE ES.
ResponderEliminarNOOOOOOOOOOOOOOOOOO, en minix no puede haber infinitos procesos, solo puede HABER 104, 100 procesos y 4 tareas. Lógicamente cuando arrancas minix hay procesos y se eestán ejectando siempre y otro que no creo recordar que eran unos 83 los que se creaban al arrancar MINIX pero mas tarde morían la mayoría y al final solo quedan unos 30.
Pero en definitiva solo PUEDE HABER 104, 4 que no puedes tocar y 100 que posiblemente mueran y nazcan de nuevo, te pongo un ejemplo sencillo, con 4 tareas y solo 10 procesos COMO MÁXIMO EN MINIX (es un MINIX QUE ME ACABO DE INVENTAR)
-4, -3, -2, -1, 0, 1, 2, 3 (al arrancar justo antes de tener que escribir root se crean estos procesos)
-4, -3, -2, -1, 0, 1, 3, 4, 5, 6 (escribes root y aparecen estos procesos)
-4, -3, -2, -1, 0, 1, 3 7, (el MINIX se queda esperando a que escribas algún comando solo tienes 14 procesos disponibles de los que 8 están en uso por el sistema).
Ahora ejecutas una práctica que crea 4 procesos por ejemplo
-4, -3, -2, -1, 0, 1, 3, proc1_enhueco4, proc2_enhueco5, proc3_enhueco6, proc4_enhueco7 (solo te quedan 3 huecos libres ya que como máximo mi minix que me acabo de inventar puede albergar 14 procesos = 4 tareas y 10 procesos) Los huecos que te quedan libres son el 2, el 8, y el 9, recuerda que en C los array empiezan en 0 y acaban en n-1.
Acaba la práctica y volvemos al estado anterio
-4, -3, -2, -1, 0, 1, 3
Ejecutamos una práctica con 7 procesos para ver lo que ocurre con todo el array ocupado.
Creo que en MINIX hay variable que indica donde debe insertarse un proceso que se acaba de crear y que apunta al siguiente hueco libre es decir el hueco 8, sino es así da igual vamos autilizar esa política
-4, -3, -2, -1, 0, 1, 3, proc1_enhueco8,
-4, -3, -2, -1, 0, 1, 3, proc1_enhueco8, proc2_enhueco9
-4, -3, -2, -1, 0, 1, proc3_enhueco2, 3, proc1_enhueco8, proc2_enhueco9
-4, -3, -2, -1, 0, 1, proc3_enhueco2, 3, proc4_enhueco4, proc1_enhueco8, proc2_enhueco9
-4, -3, -2, -1, 0, 1, proc3_enhueco2, 3, proc4_enhueco4, proc5_h5, proc1_enhueco8, proc2_enhueco9 (voy a abreviar)
-4, -3, -2, -1, 0, 1, proc3_enhueco2, 3, proc4_enhueco4, proc5_h5, p6_h6, proc1_enhueco8, proc2_enhueco9
-4, -3, -2, -1, 0, 1, proc3_enhueco2, 3, proc4_enhueco4, proc5_h5, p6_h6, p7_h7, proc1_enhueco8, proc2_enhueco9
Como ves he ido creando un proceso cada vez y MINIX lo asiguna en cada hueco libre que hay en el descritor.
Cuando se acaba el array del descritor empieza por el principio a buscar un hueco y el primero que encuentra está en el hueco 2, y ahí inserta el PROC3.
No se si lo has entendido.
Otra razón es por que se te fijas hay una estructura en minix *proc que es el descritor de procesos definida en el /usr/src/kernel/proc.h,
EXTERN struct proc *proc[NR_TASKS+NR_PROCS]; (creo que esta era la definición).
Como ves como máximo el array de descritores de procesos puede tener 104 elementos 100 procesos y 4 tareas.
MINIX no crea procesos dinamicamente sino que los almacena en una estructura de 104 elementos, por diseño, imágínate que el MINIX se vuelve loco y empieza a acrear procesos a lo loco, que pasaría, además si un sistema funciona bien no tiene por que tener 10.0000.00000000 proceos si funciona correctament con 20 pues ale, 20 y si funciona con 100 tambien, por esos MINIX por fiabilidad creo que decidió poner un límite ya que su sistema va que te cagas con 104 como máximo, posiblemente en las próximas versiones de minix aumente ese número.
Ahora te preguntarías cuantos proceos puede crear WINDOWS XP pues yo díría que no más de (2^16)-1, y si crea más mi equipo no puede con ellos, jejejjeje.
Buenas
ResponderEliminaruna preguntita de última hora, una vez que mi código compila perfectamente y rearranco MINIX el sistema no me llega ni al root, se queda en una linea que indica que ha arrancado init(), y si mal no recuerdo init era el padre de todos los procesos posteriores, pero ¿porque peta ahí y no al crear los procesos IDLE, etc...? no lo entiendo, estoy convencido que inicializo bien la antigüedad de los 12 procesos iniciales del sistema, dejo la variable antigüedad preparada para que fork la use y la incremente, y el código de inserción en la cola ... como esté mal me corto ....
Alguna idea de última hora????
Mi recomendación:
ResponderEliminar1.- Bájate una nueva imagen de memoria de la web. (por si acaso, ya que los cambios que debes realizar en esta práctica son mínimos y en una hora tienes todo el código listo para compilar de nuevo)
2.- Pruébala para que veas que funcione.
3.- Ve modificando el código fichero a fichero en ESTE ORDEN:
3.1.- proc.h (definición de variables)
3.2.- main.c (inicialización del array para los elementos CARGADOS EN MEMORIA EXCLUSIVAMENTE).
3.3.- do_fork.c (Por cada proceso de usuario que se cree, meter su antiguedad en la posición del array que le corresponda).
3.4.- proc.c
En proc.c es el paso más delicado, posiblemente tu práctica falle aquí al ordenar mal los procesos. Si has llegado a este paso recompila el kernel antes de completarlo y después si todo va bien ponte con él.
Un detalle que tienes que tener en cuenta es que SCHED baja de prioridad a un proceso, por lo tanto los procesos se meten en diferentes colas, pero ordenado correctamente, es decir:
COLA7: 20, 30, 31
COLA8: 23, 78, 90
COLA9: 12, 13, 91,
Como ves están ordenados correctamente en cada cola, pero tu tienes que hacer que ocurra lo siguiente antes de ponerte a ordenar, decirle a SCHED que utilice una sola cola:
COLAX: 12, 13, 20, 23, 30, 31, 78, 90, 91
¿y como se hace eso? pues... SOLO TE PUEDO DECIR QUE LA COLA EN LA CUAL SE "ENCOLA" UN PROCESO ES SU PRIORIDA.
Si consigues que encole en una sola cola, ahora ya puedes ponerte a ordenarlos.
3.4.1.- Antes de empezar este apartado vamos intentar que se encoles en una sola cola, cuando creas que lo has conseguido, recompilas, reiniciar y ejecutas por ejemplo la prueba3 y pulsa F9, ahí verás si todos los procesos se enconlan siempre en una cola o en varias.
3.4.2.- Si todo ha ido bien solo te queda que ordene esa cola. Recompilar, reiniciar y probar por ejemplo la prueba3, pulsar F9, si ves que todos se encolan en un cola de forma ordenada has terminado.
3.4.3.- Recomendación las pruebas las ejecutas en la tty1 que se accede a ella con ALT+F2, entras como root y ejecutas esa prueba, rápidamente te vas a la tty1 con ALT+F1 y pulsas F9 veras que se está ejecutando algo y deberás ver como se encola todo correctamente en una sola cola.
3.5.- Has teminado y me debes dar las gracias.
4.- Espero haberte sido de ayuda.
muchas gracias por tu aclaracion haelsite me ha servido de mucho
ResponderEliminarBueno, era un problema al encolar, efectivamente, revisando y haciendo una traza manual del encolado me he dado cuenta porque lo del los ALT+... no lo pillo para lo que es y como va, además ya tengo también terminada la práctica 3, muchas gracias por todos tus tutoriales
ResponderEliminarEn Minux, Linux, ... existe la posibilidad de tener varias sesiones abiertas, cada una con un usuario distinto, y cada una en un ternminal, lo que pasa es que si solo tenemos un terminal podermos tener varias sesiones abierta distintas en un solo terminal y para cambiar de terminal (tty) pulsamos:
ResponderEliminarALT+F1 ... (accedesa al tty0)
ALT+F2 ... ( " tty1)
ALT+F3 ... ( " tty2)
ALT+F4 ... ( " tty3)
En minix hay posibilidad de tener 4 terminales distintos. Si por ejemplo en los 4 accedes con el usuario "root" puedes hacer los siguiente:
En el tty0 editar el proc.c
En el tty1 editar el proc.h
En el tty2 editar el main.c
En el tty3 compilar
Así puedes tener varias sesiones o ventanas en windows sin tener que estar saliendo de los ficheros y bla bla bala
Salu2
Hola quisiera saber con que compilador lo realizan antes de pasar al al qemu
ResponderEliminarse que en qemu es cc
pero no hay otro compilador que permite realizarlo antes y despues pasarlo al minix con qemu muchas gracias
Disculpa no me presente soy manu de jujuy y tambien estoy trabajando con minix pero un nivel inferior al de ustedes jujuy que da en ARGENTINA quisiera saber como puedo compilarlo antes de mandarlo al qemu y probarlo aqui tambien gracias nos vemos
ResponderEliminarestoy frito en la tarea de sistema operativo de modificar algo en el Minix
ResponderEliminar