Simulación de procesos del SO

Si has estudiado, o estudias, sobre sistemas operativos te debe ser familiar terminos como procesos, los procesos o tareas (aplicaciones en ejecución) que lleva a cabo el CPU y son administrados desde el sistema operativo, los procesos se administran ya que no son secuenciales sino que se ejecutan en forma intercalada a traves de ranuras de tiempo.

La planificación de procesos es importante ya que dado el tiempo de ranura usado por cada proceso y la cantidad de procesos corriendo en un momento dara como resultado un mayor o menor gasto tiempo de tiempo en la ejecucion completa de los procesos, hay distintos tipos de planificación y hay varios algoritmos para ello.

En la materia de SO que lleve en 5to semestre vimos esto y para hacerlo mas claro soliamos hacer varios ejemplos de ejecución de un conjunto de procesos con un tiempo determinado usando los algoritmos FCFS, SJF y Round Robin.



Una de las tareas fue crear un programa que simule el funcionamiento de los algoritmos mencionados.

El programa se debia ejecutar desde linea de comandos de la siguiente manera:

SimulaPlanificacion [ -F | -S | -R num ] nombre_archivo

nombre_archivo indica un archivo de texto que contiene la información de los procesos a ejecutar en nuestra simulación por ejemplo:
1,0,7
2,2,4
3,4,1
4,5,4

Se encuentra por cada línea la siguiente informacion de un proceso: identificador, tiempo de llegada, tiempo de rafaga
El identificador es un entero, y los otros dos datos pueden ser enteros o reales.
Los argumentos: -F, -S y -R num indican:
-F Usar algoritmo FCFS (default)
-S Usa algoritmo SJF
-R num Usar algoritmo Round Robin con una ranura de tiempo de duracion num

La salida se debe mostrar con el formato (los datos corresponden a una ejecución con FCFS)
PROCESO T_INICIO T_FIN
1 0 7
2 7 11
3 11 12
4 12 16

Use java para crear ese programa ya que debido al uso de estructuras de datos necesario java me parecio la mejor opcion.

El programa de dos clases simulaPlanificacion y colaProcesos, aqui el código fuente:

// Simulador de ejecucion de procesos por algoritmos FCFS SJF y RoundRobin
import java.io.*; //Para lectura de archivo
import java.util.*; //Para manejo de una lista dinamica
import java.text.DecimalFormat; //Para redondeo a dos decimales al imprimir resultados

public class simulaPlanificacion{

  double datos[][]; //Para cargar los datos leidos desde el archivo, cada reglon de la matriz representa un proceso
  // y cada representa: la 1ra numero de proceso, la 2da tiempo de llegada del proceso y la 3ra rafaga del proceso
  DecimalFormat redondeo = new DecimalFormat("###.##"); //Para redondear numeros de resultados

  public static void main(String args[]){
    simulaPlanificacion sP = new simulaPlanificacion();
    int algoritmo=0; // Segun su valor indica el algoritmo a utilizar: 1=FCFS; 2=SJF; 3=RoundRobin 
    double RR_ranura=0; // Si el algoritmo es el round robin indica la ranura de tiempo a utilizar 
    String archivo=null; // Nombre del archivo de datos de entrada 
    if(args.length==0) sP.error(1); // Si no hay argumentos indicarlo y terminar el programa 
    // Se revisaran los argumentos 1x1 solo se aceptara el primer indicativo de tipo de algoritmo a
    // utilizar (si es el rr se esperara a continuacion el valor de la ranura de tiempo), cualquier otra cadena
    // se tomara como nombre del archivo y solo se aceptara la primera, si se encuentra un argumento extra o un
    // indicativo (cadena iniciada por -) se considerar error en los argumentos 
    for(int contador=0;contador<args.length;contador++){
      if(args[contador].charAt(0)=='-' && algoritmo==0){ //Asignando el parametro de algoritmo a ejecutar
        if(args[contador].equals("-F")) algoritmo=1;
 else if(args[contador].equals("-S")) algoritmo=2;
 else if(args[contador].equals("-R") && contador<(args.length-1)) algoritmo=3;
 else sP.error(2);
      }
      else if(args[contador].charAt(0)=='-' && algoritmo!=0) sP.error(2); //Error el algoritmo ya fue asignado
      else if(contador>0 && args[contador-1].equals("-R")){ //Si el anterior fue RoundRobin cargando tiempo de ranura
        try{
   RR_ranura=Double.valueOf(args[contador]).doubleValue();
 }
 catch(NumberFormatException err){
   sP.error(2); //Si el dato no esta o es erroneo indicarlo
 }
      }
      else if(archivo==null) //Aun no hay archivo y no fue una de las anteriores opciones cargar el parametro actual
        archivo=args[contador];
      else //Cualquier otro caso es por que hay un error en los parametros
        sP.error(2);
    }
    algoritmo=(algoritmo==0?1:algoritmo); // Si no habia algoritmo especificado indicar el FCFS 
    if(archivo==null) sP.error(2); // Si no habia archivo especificado mandar a error 
    sP.cargaDatosArchivo(archivo); //Mandar cargar los datos desde el archivo y llamar al algoritmo correspondiente
    if(algoritmo==1) sP.FCFS();
    else if(algoritmo==2) sP.SJF();
    else sP.RR(RR_ranura);
  }

  public void error(int n_error){ // Funcion para los mensajes de error posibles 
    if(n_error==1) System.out.println(" No hay argumentos");
    else if(n_error==2) System.out.println(" Error en los argumentos");
    else if(n_error==3) System.out.println(" No se pudo leer el archivo");
    System.exit(0); //Terminar la ejecucion del programa
  }

  public void cargaDatosArchivo(String dir){
    List listaTemp = new ArrayList(); //Usar lista dinamica para ir cargando los datos ya que no sabemos cuantos seran
    int listaTam=-1; //Para llevar un conteo de elementos que se insertan en la lista
    String reglon; //Para leer reglon x reglon del archivo
    try{ //Intentar leer abrir y leer el archivo capturar posibles excepciones
      FileReader ar = new FileReader(dir); //Declarando objeto archivo de lectura
      BufferedReader lineaArchivo = new BufferedReader(ar); //Declarando objeto buffer de lectura
      while((reglon=lineaArchivo.readLine())!=null && reglon.length()>1) {
        //Leer reglon mientras este exista y tenga contenido
        listaTemp.add(++listaTam,reglon); //Agregar la cadena obtenida a la lista
      }
      lineaArchivo.close(); //Cerrar buffer de lectura
      ar.close(); //Cerrar archivo
    }
    catch(java.io.IOException ex0){ //Si ocurrio una excepcion informar y terminar
      error(3);
    }
    datos = new double[listaTemp.size()][3]; //Indicar el tamaño de la matriz de datos segun los datos obtenidos en la lista
    for(int cnt=0;cnt<listaTemp.size();cnt++){ //Convertir los datos de la lista String a valores double y cargar en datos
      datos [cnt][0]=extraeVal(1,(String)(listaTemp.get(cnt)));
      datos [cnt][1]=extraeVal(2,(String)(listaTemp.get(cnt)));
      datos [cnt][2]=extraeVal(3,(String)(listaTemp.get(cnt)));
    }
  }

  public double extraeVal(int val, String orig){
    //Este metodo recibe una cadena y extrae tres valores double que esten separados por una coma regresa el valor indicado en val
    String aux=""; //Cadena auxiliar
    int cont=-1; //Contador para ir recorriendo la cadena caracter por caracter
    while(orig.charAt(++cont)!=',') aux+=orig.charAt(cont); //Recorrer hasta la 1ra coma
    if(val==1)  return Double.valueOf(aux).doubleValue(); //Si se solicito el 1er valor regresalo
    aux=""; //Si no borrar contenido de aux y cargar siguiente valor
    while(orig.charAt(++cont)!=',' ) aux+=orig.charAt(cont); //Recorrer hasta la 2da coma
    if(val==2)  return Double.valueOf(aux).doubleValue(); //Si solicito 2do valor regresarlo
    aux=""; //Si no borrar contenido de aux y cargar ultimo valor
    while(++cont <=orig.length()-1) aux+=orig.charAt(cont); //Recorrrer hasta el final
    return Double.valueOf(aux).doubleValue(); //regresar 3er valor
  }

  public void FCFS(){
    //Este metodo trabaja asi: ordenar los datos por su tiempo de llegada, 2da columna de la matriz, e ir imprimiendo cada uno de ellos con su respectivo tiempo de inicio y final
    double lineaT=0; //Manejar el valor de la linea de tiempo de ejecucion
    mergeSort(1,datos.length,1); //Ordenar la matriz datos por su segunda columna, tiempo de llegada
    System.out.println("PROCESO \tT_INICIO \t\tT_FIN"); //Imprimir encabezado
    for(int i=0;i<datos.length;i++){
      //Recorrer cada proceso y calcular e imprimir su tiempo de inicio y su tiempo de fin
      System.out.println(redondeo.format(datos[i][0])+"\t\t"+redondeo.format(lineaT)+"\t\t"+redondeo.format((lineaT+=datos[i][2])));
    }
  }

  public void SJF(){
    //Este metodo trabaja asi: 1-. ordenar los datos por su tiempo de llegada, 2da columna de la matriz, 2.- imprimir
    // el primer proceso ha llegado, 3.- segun el tiempo de ejecucion transcurrido ver que nuevos han llegado y ordenarlos
    // por su menor tiempo de rafaga, 3ra columna de la matriz 4.- repetir desde el paso 3 hasta terminar
    double lineaT=0; //Manejar el valor de la linea de tiempo de ejecucion
    int hanLlegado; //Saber que nuevos procesos han llegado al terminar x proceso y ordenarlos por tiempo de rafaga
    mergeSort(1,datos.length,1); //Ordenar la matriz datos por su segunad columna, tiempo de llegada
    System.out.println("PROCESO \tT_INICIO \t\tT_FIN"); //Imprimir encabezado
    for(int i=0;i<datos.length;i++){
      //Recorrer cada proceso y calcular e imprimir su tiempo de inicio y su tiempo de fin
      System.out.println(redondeo.format(datos[i][0])+"\t\t"+redondeo.format(lineaT)+"\t\t"+redondeo.format((lineaT+=datos[i][2])));
      hanLlegado=0; //Vamos quienes han llegado partamos del caso de que ningun proceso ha llegado en este tiempo
      for(int j=(i+1);j<datos.length;j++)
        if(datos[j][1]<=lineaT) hanLlegado=j; //Si se cumple esta condicion el proceso subindice j ha llegado
      if(hanLlegado>(i+1)) mergeSort(i+2,hanLlegado+1,2); //Si han llegado >=2 procesos ordenarlos por tiempo de ragafa
    }
  }

  public void RR(double ranura){
    colaProcesos cola = new colaProcesos(); //Usaremos una cola en este metodo
    double lineaT=0; //Manejar el valor de la linea de tiempo de ejecucion
    double[] prosActual; //Para cargar el proceso que se saque de la cola y que se valla a ejecutar
    int encolados=1; //Llevar el conteo de cuantos procesos han entrado a la cola
    mergeSort(1,datos.length,1); //Ordenar la matriz datos por su segunad columna, tiempo de llegada
    cola.encolar(datos[0][0],datos[0][2]); //mandar a la cola el primer proceso que ha llegado
    System.out.print("PROCESO \tT_INICIO \t\tT_FIN\n"); //Imprimir encabezado
    do{
      prosActual=cola.desencolar(); //Sacar de la cola el siguiente proceso que este listo
      //Calcular e imprimir su tiempo de inicio y si se ejecuta hasta el fin o solo el tiempo de ranura
      System.out.println(redondeo.format(prosActual[0])+"\t\t"+redondeo.format(lineaT)+"\t\t"+redondeo.format((lineaT+=(prosActual[1]>ranura?ranura:prosActual[1]))));
      //Buscar procesos que hayan llegado mientras se ejecutaba el anterior y mandarlos a la cola
      for(int i=encolados;i<datos.length;i++)
        if(datos[i][1]<=lineaT){
          cola.encolar(datos[i][0],datos[i][2]);
          encolados++;
        }
      //Si el ultimo proceso ejecutado no ha terminado aun mandarlo, con el tiempo de rafaga que le quede, a la cola
      if((prosActual[1]-ranura)>0) cola.encolar(prosActual[0],prosActual[1]-ranura);
    }while(cola.nElementos>-1); //Repetir mientras haya elementos en la cola
  }
  
//Lo siguiente es adaptacion del mergesort para que ordene la matriz datos por reglones basandose en cualquier columna
   public void mergeSort(int l, int r, int col){
    int q;
    if(l<r){
      q=(int)(Math.floor((l+r)/2));
      mergeSort(l,q,col);
      mergeSort(q+1,r,col);
      merge(l,q,r,col);
    }
  }
  public void merge(int l, int q, int r, int col){
    int i;
    int j;
    int k = 0;
    int n = r-l+1;
    double[][] B = new double[n][3];
    for(i=l;i<=q;i++){
      B[k][0] = datos[i-1][0];
      B[k][1] = datos[i-1][1];
      B[k++][2] = datos[i-1][2];
    }
    for(j=r;j>=q+1;j--){
      B[k][0]=datos[j-1][0];
      B[k][1]=datos[j-1][1];
      B[k++][2]=datos[j-1][2];
    }
    i = 1; j = n; k = l;
    while (i<=j)
      if (B[i-1][col]<=B[j-1][col]){
        datos[(k)-1][0] = B[(i)-1][0];
        datos[(k)-1][1] = B[(i)-1][1];
        datos[(k++)-1][2] = B[(i++)-1][2];
      }
      else{
        datos[(k)-1][0] = B[(j)-1][0];
        datos[(k)-1][1] = B[(j)-1][1];
        datos[(k++)-1][2] = B[(j--)-1][2];
      }
  }
}

Clase colaProcesos

import java.util.*;

public class colaProcesos{

  List listaComoCola = new ArrayList(); // Usare una lista dinamica como cola
  int nElementos; // Para llevar el conteo de los elementos que existan dentro de la cola

  colaProcesos(){
    nElementos=-1; // Al iniciar la cola esta vacia
  }

  public void encolar(double val1, double val2){ // Al encolar solo se agregan los nuevos elementos
    listaComoCola.add(++nElementos,""+val1);
    listaComoCola.add(++nElementos,""+val2);
  }

  public double[] desencolar(){
    double[] temp = new double[2];
    if(nElementos==0) return null;
    // Al desencolar se sacan los dos primero elementos
    temp[0]=Double.valueOf((String)(listaComoCola.get(0))).doubleValue();
    temp[1]=Double.valueOf((String)(listaComoCola.get(1))).doubleValue();
    // Luego los restantes se recorren dos posiciones hacia atras
    for(int i=0;i<(listaComoCola.size()-2);i+=2){
      listaComoCola.set(i,listaComoCola.get(i+2));
      listaComoCola.set(i+1,listaComoCola.get(i+3));
    }
    // Los dos elementos finales se borran
    listaComoCola.remove(listaComoCola.size()-2);
    listaComoCola.remove(listaComoCola.size()-1);
    nElementos-=2; // Se reasigna el valor de elementos dentro de la cola
    return temp; // Se regresan los valores sacados de la cola
  }
}




Comentarios

  1. no se que tiene pero este codigo esta mal, no me imprime nada

    ResponderEliminar
    Respuestas
    1. Hola, acabo de checarlo por si se me hubiese pasado algun error y me funciono perfectamente.

      ¿Compilastes las dos clases? simulaPlanificacion y colaProcesos cada una en su archivo, la llamada a la ejecución es asi C:\>java simulaPlanificacion -F exa.txt
      Suponiendo que en C: esten los dos archivos compilados (simulaPlanificacion.class y colaProcesos.class) y suponiendo que el archivo con os datos se llama exa.txt

      Eliminar
    2. Este comentario ha sido eliminado por el autor.

      Eliminar
    3. ola gracias por tu codigo, esta perfecto. pero lo transcribi a netbeans pero al ejecutarlo no manda a imprimir nada a que se deve eso?? espero que me puedas responer amigo me salvarias de una muy grande

      Eliminar
    4. Hola, ejecultalo directamente desde una terminal, o checate en netbeans la salida estandar

      Eliminar
    5. sigo igual y en que programa lo ejecutaste?? para que lo pase en el mismo

      Eliminar
    6. hola, checa la respuesta que puse mas abajo (a vanessa) ve si es eso lo que pasa en tu caso, aca dicen como ejecutar java en la consola http://slash.blogcindario.com/2009/08/00001-compilar-e-interpretar-programas-java-desde-la-consola-de-comandos.html

      Eliminar
  2. hola no puedo ejecutarlo... me puedes guiar por favor demasiado bueno tu blogs

    ResponderEliminar
    Respuestas
    1. Hola, gracias por tu comentario, el programa se ejecuta directo en java, con las jsdk, directo en la consola o temirnal de comandos. NO es necesario netbeans ni eclipse ni todo eso (aunque se puede usar) Si no lo has podido ejecutar posiblemente sea que en tu consola de comando no tienes el path de java, si es eso aca dice como solucionarlo: [http://www.elmundoexterior.es/anadir-java-al-path-de-windows/] esatndo eso bien no hay pierde en la consola de comando pones:

      C:\>java simulaPlanificacion -F exa.txt

      Suponiendo que en C: esten los dos archivos compilados (simulaPlanificacion.class y colaProcesos.class) y suponiendo que el archivo con os datos se llama exa.txt
      y debe correr sin problemas, si sigue sin salir necesitaria saber que mnsaje de error te pone o que marca. Saludos.

      Eliminar
    2. Hola me prodrias ayudar con un pequeño programa ej java de grafos?? porfa es una tarea que me dejaron pero no entiendo bien ese tema y lo confundo mucho con arbol. saludos espero que me pueda ayudar

      Eliminar
  3. No me quiere corer el programa, que puedo hacer.

    ResponderEliminar
    Respuestas
    1. Pues... no se necesito mas datos para poder aconsejar, marca algun error? tiene java correctamente instalado? ??

      Eliminar
  4. no me corre solo envia mesaje que NO hay argumentos?? que puedo hacer?

    ResponderEliminar
    Respuestas
    1. No hay argumentos, no te leiste bien la explicación, hay que pasarle argumentos para que funcione, el programa se ejecuta desde linea de comandos de la siguiente manera:

      SimulaPlanificacion [ -F | -S | -R num ] nombre_archivo

      -F -S -R num y nombre_archivo son los argumentos, en el caso de -F -S y -R solo usa unos de esos (eso significa el | es el operador O) y en el nombre de archivo pones un archivo de texto que tengas con los datos, vuelvete a leer la entrada todo esta explicado.

      Eliminar
  5. grax me toco hacerle algunas modificaciones = mente muy bueno

    ResponderEliminar
  6. oie disculpa uso ios y mi entorno de trabajo es eclipse kisiera saber como es el funcionamiento para hacer la corrida de l programa ya q es en base a un archivo...

    ResponderEliminar
    Respuestas
    1. Hola, la verdad no tengo mucha experiencia en IOS pero seguro buscando en google habra la respuesta, saludos.

      Eliminar
    2. hola MetalPower soy estudiante de la carrera de ingenieria en Sistemas Computacionales. estoy aprendiendo todo este rollo de los tipos de planificacion. como puedo descargar el paquete completo de este programa? lo que pasa esque lo estoy pasando pero me marca errores. podrias enviarme el paquete el main y la clase ? mi correo es ivan_931229@hotmail.com me sacarias de un gran apuro te lo agradeceria de ante mano que bien que gente como tu nos comparta sus conocimientos gracias!

      Eliminar
  7. hola MetalPower soy estudiante de la carrera de ingenieria en Sistemas Computacionales. estoy aprendiendo todo este rollo de los tipos de planificacion. como puedo descargar el paquete completo de este programa? lo que pasa esque lo estoy pasando pero me marca errores. podrias enviarme el paquete el main y la clase ? mi correo es ivan_931229@hotmail.com me sacarias de un gran apuro te lo agradeceria de ante mano

    ResponderEliminar
  8. alguien me puede decir paso a paso como meter comandos para dar argumentos a programa? ayudenmeeeee :(

    ResponderEliminar
    Respuestas
    1. Hola. supongo que ya descargaste y compilaste ambas clases.
      Para meter argumentos a un programa en java hay que ejecutarlo desde la consola, abres tu consola (ms-dos windows) (terminal linux) y te posicionas en el directorio donde tienes las clases compiladas, por ejemplo c:/simula/ suponiendo que esta en un directorio llamado simula en la unidad c.

      Ahora ejecutas el comando java seguido del nombre de la clase principal, en este caso la principal es simulaPlanificacion asi que sera algo asi:

      c:/simula> java simulaPlanificacion

      Si le das entre se ejecuta (debes tener configurado el path con java)
      Si escribes mas cosas delante del nombre del programa separados por un espacio estos se consideran argumentos y son simplemente cadenas de texto, ejemplo:

      c:/simula> java simulaPlanificacion arg1 arg2

      donde arg1 es el argumento uno, arg2 es el dos, etc
      Si lees la explicacion de la entrada ya solo verifica que uses los aruemntos correctos y listo!

      Eliminar

Publicar un comentario

Entradas populares