Se muestra el número de proceso, el nombre y el número de mensajes enviados.
Imagen en grande: LINK.
Cualidades:
1.- Muestra solo los procesos QUE EXISTEN ACUALMENTE.
2.- Muestra el nombre de los procesos para no estar constantemente pulsando F1 o F3.
3.- Cada vez que se crea un proceso BORRA su contador.
4.- Actualiza el contador no solo al enviar un menaje sino tambien al RECIBIR. (Acordaros de que estamos en rendevouz).
En mi caso yo he realizado una copia del CODIGO FUENTE para mostraros más tarde una cosilla interesante.
Todo el texto que está antes del punto 5.1 es conveniente leerlo para saber de que estamos hablando pero aún asi y todo comenzamos:
5.1 Lo primero que vamos a hacer es proporcionar una funcionalidad sencilla a una tecla de función (F8) que originalmente no tenía ninguna acción asociada. Las teclas de función están definidas bajo el servidor IS en el directorio /usr/src/servers/is. El fichero a modificar para ello se llama dmp.c. Una prueba sencilla de definición de la tecla de función puede ser utilizar la tecla F8 para duplicar la funcionalidad de una ya definida (por ejemplo, F9). Es importante también incrementar la constante que representa el número de enganches definidos (NHOOKS) en el mismo fichero, ya que dicha constante refleja el tamaño del array hooks de teclas de función. Cuando hayamos realizado estos cambios en el fichero dmp.c, recompilaremos el sistema y probaremos su nuevo funcionamiento.
Una vez que modificamos NHOOKS y que duplicamos para la tecla F8 continuamos.
5.2 En este paso vamos a definir las variables y código necesario para contar dentro del kernel el número de mensajes que ha enviado un proceso. Para contar el número de mensajes, una posible solución sería añadir un nuevo campo a los descriptores de la Tabla de procesos, llamado por ejemplo messg_sn. El problema es que estaríamos modificando una estructura muy delicada del kernel de MINIX, de la que también depende el código ensamblador. Por ello, a continuación recomendamos un solución alternativa.
5.2.1 Vamos a definir un array messg_sn con el mismo número de elementos que la tabla de procesos. Este array contendrá el contador de mensajes enviados por cada proceso, de tipo long. La declaración de este array se realizará en el fichero /usr/src/kernel/proc.h como sigue:
EXTERN long messg_sn[NR_TASKS+NR_PROCS];
Además, bastará con pasar una copia íntegra de este array al IS cuando éste lo solicite para efectuar el volcado por pantalla.
Nos quedaremos con éste párrafo ya que será importante para el final de la práctica.
5.2.2 A continuación debemos dar el valor inicial 0 a todos los elementos del array de “mensajes enviados” en el fichero /usr/src/kernel/main.c.
Para esto no hace falta que os diga nada, ya sabeis como poner un array a 0. Solo teneis que tener en cuanta que aquí se debe de inicializar TODO el array.
5.3 En el apartado anterior se han inicializado los contadores de mensajes de los procesos. Ahora vamos a introducir la actualización de dichos contadores de acuerdo con los mensajes enviados en el fichero /usr/src/kernel/proc.c.
En este apartado vamos a tener en cuenta el siguiente gráfico.
5.3.1 El contador de mensajes enviados por un proceso debe incrementarse cada vez que se llame al procedimiento mini_send. Si quisiéramos hacer un control más exacto de los mensajes enviados, deberíamos tener en cuenta cuáles son realmente recibidos pero, por simplicidad, vamos a mantener la solución indicada.
Mas o menos lo que intento decir es que si un proceso NO ESTÁ ESPERANDO un mensaje, el emisor se bloquea y al revés, si no está esperando recibirlo se bloquea el emisor hasta que el receptor quiera.
En la práctica solo se pide que contabilizar cuando un proceso envía, pero tambien sería conveniente aunque no es estrictamente lo que se pide, contabilizar cuando un proceso recibe, la explicación es la siguiente:
Si un proceso A intenta enviar un mensaje un proceso B y éste último no está esperando recibirlo, el proceso A se bloquea. En el supuesto solicitado en la práctica este mensaje enviado se pierde (su cuenta) ya que, el receptor recibe el mensaje cuando hace un mini_receive. Digamos que la práctica solo pide que se contabilice cuando un mensaje es enviado directamente de a un receptor que está esperando recibirlo.
5.3.2 Lo siguiente que nos interesa es posibilitar que el núcleo proporcione al IS información sobre los contadores de mensajes enviados, para que éste pueda proporcionársela, a su vez, a los procesos de usuario. El núcleo proporciona una llamada al sistema sys_getinfo para poder extraer distintas informaciones internas del mismo. Esta llamada se implementa en /usr/src/kernel/system/do_getinfo.c, a través de una sentencia case (switch en C) que extrae la información especificada. Vamos
a definir una nueva etiqueta GET_MESSGSN para indicar en la sentencia case que queremos obtener información sobre los
contadores de mensajes enviados por los procesos. En do_getinfo.c vamos a añadir un nuevo caso etiquetado con la constante GET_MESSGSN. Para dar valor a esta constante, debemos tener en cuenta cuál es el siguiente valor disponible una vez
definidas todas las anteriores etiquetas de la sentencia case. El esqueleto de la sentencia a incluir sería:case GET_MESSGSN: {
length = ......;
src_phys = vir2phys(......);
break;
}
donde debemos indicar en length la longitud de nuestro array de contadores y como parámetro de vir2phys la dirección física de
messg_sn para que luego se envíe con phys_copy.
En este caso no hace falta comentar mucho, los puntos suspensivos son para decir que en LENGTH se debe poner la longitud del array, si no somos muy listos vamos un par de páginas antes y vemos ejemplos de como se hace y veremos lo siguiente:
Ehhhh que nuestro array no es un STRUCT, no vaya a ser que alguno pongo lo que no es.
En el siguiente apartado tenemos que poner la dirección física y todos sabemos que la dirección física de algo en C se obtiene con:
5.3.3 Al tratarse de una constante que debe importarse desde el kernel y desde el IS, la constante GET_MESSGSN debe definirse en el fichero /usr/src/include/minix/com.h, y su valor debe ser diferente al de otras etiquetas ya definidas.
Aquí puede pasarte que en vez de poner:
#define GET_MESSGSN .........
pongas
#define GET_MESSGSN 16
y que MINIX al compilar te de un error de identificador por duplicado, PUES NO TE PREOCUPES, me pasó a mi y a un montón de gente, incluso algún profesor seguro que también ha picado. Cuando te dice que el valor debe ser diferente pones uno más al que existe como último, en este caso el último es 16, pues tu sabrás cual es el siguiente.
5.3.4 El fichero /usr/src/include/minix/syslib.h contiene prototipos para permitir que algunos componentes del sistema operativo puedan acceder a los servicios de otros componentes. Por cuestiones estéticas y por seguir el método utilizado por los desarrolladores de MINIX, recomendamos definir en dicho fichero la siguiente macro:#define sys_getmessgsn(dst) sys_getinfo(GET_MESSGSN,dst,0,0,0)
Esta es una de las líneas más interesantes de la práctica y ya sabrás al final porque, ahora acuerdate que unas lineas arriba dije que recordaras un párrafo, pues este el segundo párrafo que debes recordar.
5.4 Para poder probar que el código introducido es correcto, vamos a conectar la tecla de función que definimos en el paso 1
con la impresión de los contadores de mensajes enviados. Para ello, vamos a empezar por definir una función que nos permita
imprimir los contadores de mensajes enviados.
5.4.1 Tomando como modelo las funciones xxxxdmp del fichero /usr/src/servers/is/dmp_kernel.c, vamos a definir una función
messgsn_dmp que traiga los contadores del kernel y los imprima.
Pues eso te vas al fichero dmp_kernel.c y te creas una función que por ejemplo su ÚNICO codigo para probar sea:
printf("\nMI PRIMER PROGRAMA EN C");
jejejejej
El resultado saldrá cuando COMPILES, REINCIES CON LA OPCIÓN 3 Y PULSES F8.
5.4.2 Para poder definir la función messgsn_dmp en un fichero y asociarla a una tecla en otro, es necesario definir un prototipo
para la misma en /usr/src/servers/is/proto.h.
Pues más de lo mismo, te vas al fichero proto.h y haces un COPY & PASTE de alguna función similar.
5.4.3 Ahora sólo nos queda enganchar la tecla F8 en el fichero /usr/src/servers/is/dmp.c a la nueva función messgsn_dmp.
Esta es la parte más delicada, si no haces esto todo lo que has leído no sirve para nada. Lo que tienes que hacer es decirle a la tecla F8 que ahora su función ya no es la que definistes en el punto 5.1 sino la que tu has creado en el punto 5.4.1
5.4.4 Vamos a compilar en este punto para comprobar si podemos mostrar el array de contadores en su estado actual. Tras
compilar, ejecutaremos los comandos:
halt
boot
Esta parte no necesita explicación.
Una vez dentro de MINIX, teclearemos F8 y veremos si los contadores se han actualizado de forma razonable.
Mi aportación personal es:
1.- Que a la hora de hacer fork se borre el contador de ese proceso.
2.- Mostrar el nombre del proceso i-ésimo.
3.- Mostar solo los proceso NO MUERTOS, es decir VIVOS.
Ahora vienen los párrafos que os decía que recordárais:
1.- El primero es muy importante ya que sin esta pequeña aclaración NO COMPILA. El erro que da es el siguiente:
Para solucionarlo tienes 2 opciones:
A) Hacer la variable MESSG_SN global en GLO.H (esta opción no la he probado).
B) Hacer la variable MESSG_SN pública en DMP_KERNEL.C (esto es lo que yo hice).
2.- Lo segundo que teneis que tener en cuenta es que por mucho que hagamos público el array hay que llenarlo de datos. Mas concretamente os digo que para hacer que el array tenga datos, hay que llamar a la función SYS_GETMESSGSN, esta macro llamará a SYS_GETINFO y con eso obtenemos en MESSG_SN el array deseado.
Esto es todo, espero haber sido claro al 99,9% tampoco quiero serlo al 100% ya que me llevaría a malo entendidos.
Resultado:
Archivo completo: LINK.
Salu2.
dios mio! mil gracias
ResponderEliminaraun no entiendo como existe gente como tu, yo pido ayuda a muchos compañeros y pasan de mi :(
Muchas gracias por tu aportacion...sin duda nos viene muy bien a muchos (sobre todo el ultimo parrafo!!! xDDDD)
ResponderEliminarSaludos y Feliz Navidad
Se agrade cualquier apoyo, esto lo hago solo porque me gusta y si puedo ayudar a los demás mejor que mejor.
ResponderEliminarSalu2
Buenas, muchas gracias por la aportación, pero una preguntilla, donde pones que hay que pasar la dirección física del array utilizando el &, no sería necesario pues una variable que es un array en C es ya de por si un puntero y por lo tanto ya se pasaría directamente la dirección física. lo puedes comprobar en IRQ_HOOKS que lo pasa sin & porque cuando lo recibe es un array. No estoy muy seguro de esto xo a mi me ha funcionado sin el & aunque no se como realizar una prueba xa comprobar que el código este bien. Y otra cosilla xa pasar los nombres te has creado un array de estructuras o algo asi en vez de solo un array de long en el que le metes el nombre del proceso. Gracias
ResponderEliminarBueno, como seguro que cualquiera sabe más C que yo, no hace falta que te explique esos pequeños detalles que me comentas, no lo he probado pero ciertamente DEBE funcionar así ya que en C los array en realidad son direcciones de memoria, aunque yo no pongo la mano en el fuego ni por mi ..., resumiendo que si te funciona COJONU... pero yo lo intenté hacer de forma que el 100% de la gente se enterara de como iba, sin tener que dar explicaciones superfluas, de todas formas, si te fijas los ejemplos de &... son iguales en todos los CASE excepto en algunos casos, por lo que si TANENBAUM lo hace así añadiendo & yo tambien lo hcie para que la gente no se perdiera.
ResponderEliminarPara los nombre no fue muy complicado, es más ha sido muy sencillo. En el ejemplo que teníamos que desarrollar solo se nos pedía una copia de un array el que nosotros habíamos creado, pero si ves el fichero donde implementas la funcion F8 comprenderás que ahí está implementado F1, F2, .... por lo que tambien verás como hace MINIX para por ejemplo en F1 mostrar los nombres de los procesos, yo solo hice lo mismo.
Hice una copia de ese array el que contiene los nombre que creo que se llama PROCS y luego mostré los nombres:
printf( "proceso: %s", procs[i]);
donde la variable i, pertenece al bucle para recorrer mi array.
Es eso basicamente, fíjate como lo hace MINXI para F1 y verás que solo tienes que hacer una copia del array de procesos para poder acceder a él y listo.
Yo tengo aun una duda, vereis despues de modificar la imagen compilo y no me da un error pero a la ra de arrancar minix otra vez se me queda pillado y no responde, alguien sabe q puedo haber tocado?
ResponderEliminarGracias x el manual ya de paso
La duda anterior he conseguido arreglarla pero ahora cuando ejecuta dmp_kernel, mi funcion messgsn_dmp en r siempre toma valor -22 luego me da error y se queda parado. De antemano digo q declaro PUBLIC messg_sn...... y pongo if r = SYS_GETMESSGSN(&messg_sn) != OK pero siempre me entra en este bucle y me da error, sabriais decirme xq
ResponderEliminarBucle ahí no hay ninguno, me explico, lo primero que tienes que hacer es lo que tu has hecho, r = ..... con esa comprobación tenemos en messg_sn creo recordar que una copia de nuestro array.
ResponderEliminarSi todo va bien y pasa ese if ya entramos en un bucle for que recorrería el array y nos muestra lo que nos pide la práctica.
Perdona por mi exactitud pero hace casi un mes que hice la práctica y no me acuerdo de mucho y las vacaciones hacen huella en mi memoria.
Si tienes más dudas miraré mi codigo para ver si puedo ayudarte.
Pues mi error debe star ahi, porque no pasa el if, luego nunca hace el bucle for y la verdad he seguido todos los pasos q ponia en la practica
ResponderEliminarsoy principiante en esto y queria saber como se inicializa un array a ,en la practica que tengo yo tengo q inicializar el array numMensajes a 0. Gracias por cierto muy buen post! xD
ResponderEliminar