Ejercicio S.O. multiusuario y multitarea Un sistema operativo multiusuario y multitarea almacena la siguiente información sobre sus usuarios: uid nombre ppaso flogin dia mes año hh mm ss 0 18 0 25 39 ... ******* ****** ***** ****** **** 12 07 12 16 16 04 07 04 07 07 2002 2002 2002 2002 2002 22 09 08 16 17 34 30 24 32 05 23 34 16 23 51 sistema monica sistema belen vanesa hlogin pids 12333 3245 1735 34567 0 2351 3566 0 ... ... 13444 16335 0 0 ... 0 3625 2561 12667 ... 2398 0 3352 0 ... ... y sus procesos: pid 34567 3566 0 12667 0 2351 3352 16335 ... prog dirIni dirFin t_ejec mm 12 36 ss 42 34 estado Dormido Espera eudora netscape 2566600 3006000 hh 0004 0008 cc 0671000 1002000 0000 01 44 Activo emacs vi csh 3100300 3340000 0406200 0408000 0000 0001 0011 23 16 25 26 16 18 Espera Dormido Activo ... Se pide diseñar e implementar: a) Las dos estructuras de datos correspondientes; TUsuarios y TProcesos; b) Un subprograma, UsuariosGolosos, que escriba en pantalla los usuarios que estén ocupando mucha memoria (por encima de m_umbral) o hayan usado más de ¾ t medio de CPU. Notas. 1. Los identificadores de usuario (uid) y los de procesos (pid) son únicos. No tener en cuenta el usuario sistema (uid=0). 2. dirIni y dirFin son direcciones de memoria. 3. Suponed que los procesos dormidos están en memoria secundaria y no ocupan memoria principal. /* * Sistema operativo multiusuario y multitarea. */ CONST N MaxProcesos=16535, MaxProcUsr=128 N MaxUsuarios=128, MaxCadena=250 TIPOS C TCadena[1..MaxCadena] ENUM { Activo, Espera, Dormido } TEstado // los Dormidos no ocupan Mem. Principal ENUM { Enero, Febrero, Marzo, Abril, Mayo, Junio, Julio, Agosto, Septiembre, Octubre, Noviembre, Diciembre } TMes REGISTRO THora N hh, mm, ss FINREGISTRO REGISTRO TFecha N dia TMes mes N año FINREGISTRO N TArrayN[1..MaxProcUsr] REGISTRO UnUsuario N uid // User IDentificator 0->sistema TCadena nombre // Nombre de usuario TCadena pp // Palabra de Paso TFecha flogin // Fecha entrada al sistema THora hlogin // Hora entrada al sistema TArrayN pids // Procesos en ejecución (>0) FINREGISTRO UnUsuario TUsuarios[1..MaxUsuarios] REGISTRO UnProceso N pid // Process IDentificator (>0) TCadena prog // Nombre del programa N dirIni // Byte inicial en memoria N dirFin // Byte final en memoria THora t_ejec // Tiempo en ejecución TEstado estado // Estado del proceso FINREGISTRO UnProceso TProcesos[1..MaxProcesos] /* * Busca la posición de un UID en tabla usuarios. * Devuelve 0 si no se ha encontrado. */ ALGORITMO N BuscarUsuario(E N ui; E TUsuarios uss) VAR N i; B encontrado INICIO i=1; encontrado=FALSO MIENTRAS NO encontrado Y i<=MaxUsuarios HACER SI uss[i].uid==ui ENTONCES encontrado = VERDADERO SINO i = i+1 FINSI FINMIENTRAS SI NO encontrado ENTONCES i = 0 FINSI DEVOLVER i FIN BuscarUsuario /* * Busca la posición de un PID en tabla procesos. * Devuelve 0 si no se ha encontrado. */ ALGORITMO N BuscarProceso(E N pi; E TProcesos pss) VAR N i; B encontrado INICIO i=1; encontrado=FALSO MIENTRAS NO encontrado Y i<=MaxProcesos HACER SI pss[i].pid==pi ENTONCES encontrado = VERDADERO SINO i = i+1 FINSI FINMIENTRAS SI NO encontrado ENTONCES i = 0 FINSI DEVOLVER i FIN BuscarProceso /* * Memoria en bytes que ocupa un proceso (ó 0 si hay error). */ ALGORITMO N MemoriaProceso(E UnProceso proc) VAR N nbytes INICIO SI proc.estado==Activo O proc.estado==Espera ENTONCES SI proc.dirIni < proc.dirFin ENTONCES nbytes = proc.dirFin-proc.dirIni SINO nbytes = 0 FINSI SINO nbytes = 0 FINSI DEVOLVER nbytes FIN MemoriaProceso /* * Memoria (en bytes) de los procesos de un usuario. */ ALGORITMO N MemoriaUsuario( E N usid; // usuario en cuestión E TProcesos procs; // Tabla información procesos E TUsuarios uss; // Tabla información usuarios S B error) // VERDADERO si el usid no existe VAR N i, i_uid, i_pid // posiciones en tablas N mem // memoria en segundos INICIO i_uid = BuscarUsuario(usid, uss) SI i_uid==0 ENTONCES mem = 0; error = VERDADERO SINO error = FALSO; mem = 0 PARA i=1 HASTA MaxProcUsr HACER SI uss[i_uid].pids[i] != 0 ENTONCES i_pid = BuscarProceso(uss[i_uid].pids[i], procs) SI i_pid!=0 ENTONCES mem = mem+MemoriaProceso(procs[i_pid]) FINSI FINSI FINPARA FINSI DEVOLVER mem FIN MemoriaUsuario /* * Tiempo de ejecución actual de un proceso (en seg) */ ALGORITMO N TEjecProceso(E UnProceso proc) VAR N t INICIO // en el laboratorio, ¡ojo con los rangos! t = proc.t_ejec.hh*3600 t = t + proc.t_ejec.mm*60 t = t + proc.t_ejec.ss DEVOLVER t FIN TEjecProceso /* * Calcula la media de ejecución de todos * los procesos en segundos. */ ALGORITMO R TEjecMedio(E TProcesos procs) VAR N i, contador R t_total INICIO t_total = 0.0; contador=0 PARA i=1 HASTA MaxProcesos HACER SI procs[i].pid !=0 ENTONCES t_total = t_total + R(TEjecProceso(procs[i])) contador = contador+1 FINSI FINPARA DEVOLVER t_total/R(contador) FIN TEjecMedio /* * Tiempo (en seg) de los procesos de un usuario */ ALGORITMO N TEjecTotUsuario( E N usid; // usuario en cuestión E TProcesos procs; // Tabla información procesos E TUsuarios uss; // Tabla información usuarios S B error) // VERDADERO si el usid no existe VAR N i, i_uid, i_pid, t // posiciones en tablas y t en seg. INICIO i_uid = BuscarUsuario(usid, uss) SI i_uid==0 ENTONCES t = 0; error = VERDADERO SINO error = FALSO; t = 0 PARA i=1 HASTA MaxProcUsr HACER SI uss[i_uid].pids[i] != 0 ENTONCES i_pid = BuscarProceso(uss[i_uid].pids[i], procs) SI i_pid != 0 ENTONCES t = t + TEjecProceso(procs[i_pid]) FINSI FINSI FINPARA FINSI DEVOLVER t FIN TEjecTotUsuario /* * Devuelve el número de procesos de un usuario */ ALGORITMO N NumProcsUsuario(E N ui; E TUsuarios uss) VAR N i, np=0, i_ui INICIO i_ui = BuscarUsuario(ui, uss) SI i_ui != 0 ENTONCES PARA i=1 HASTA MaxProcUsr HACER SI uss[i_ui].pids[i] != 0 ENTONCES np = np+1 FINSI FINPARA FINSI DEVOLVER np // =0 si el usuario no existe FIN NumProcsUsuario /* * Escribe los usuarios que estén ocupando mucha * memoria (por encima de “m_umbral”) o el tiempo medio * de sus procesos superen los ¾ del t medio de CPU total. * No se tiene en cuenta el usuario “sistema” (uid=0). */ ALGORITMO UsuariosGolosos( E TProcesos procs; // Tabla información procesos E TUsuarios uss; // Tabla información usuarios E N m_umbral) // Más se considera mucha memoria VAR N u, m; R t, t_umbral; B error_t, error_m INICIO t_umbral = TEjecMedio(procs)*3.0/4.0 PARA u=1 HASTA MaxUsuarios HACER SI uss[u].uid !=0 ENTONCES t = R(TEjecTotUsuario(uss[u].uid,uss,procs,error_t))/ R(NumProcsUsuario(uss[u].uid, uss)) m = Memoriasuario(uss[u].uid, uss, procs, error_m) SI (NO error_t Y t>t_umbral) O (NO error_m Y m>m_umbral) ENTONCES Escribir(uss[u].nombre) FINSI FINSI FINPARA FIN UsuariosGolosos Modularización: UsuariosGolosos TEjecMedio TEjecProceso TEjecTotUsuario BuscarProceso BuscarUsuario MemUsuario MemProceso