-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.c
1706 lines (1509 loc) · 44.2 KB
/
main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
© 2013
Autores:
* F. Daguerre, Federico M. <fetudaguerre@gmail.com>
* Buscaglia, Alan <alanbuscaglia@gmail.com>
* Pennisi, Giuliana <guipennisi92@gmail.com>
* Aristoy, Gonzalo <gonzaloaristoy@hotmail.com>
Este código se escribió en el marco del Trabajo Práctico N 2
de la cátedra de Sistemas Operativos I de la Universidad CAECE
Mar del Plata. Este programa permite realizar la simulación
de la ejecución de procesos concurrentes en un entorno monoprocesador,
con IPC (sincronización entre los procesos).
Para más información dirijase a la documentación técnica
en el directorio docs.
Docentes:
* Valania, Paula
* Ojeda, German
Este programa es software libre: podés distribuirlo y/o modificarlo
bajo los términos de la Licencia Pública General de GNU como está
publicada por la Free Software Foundation, en su versión 3 o, si lo
preferís cualquiera posterior.
Este programa se distribuye con la esperanza que sea útil,
pero SIN NINGUNA GARANTÍA; ni siquiera la garantía implícita de
COMERCIALIZACIÓN o IDONEIDAD PARA UN PROPÓSITO PARTICULAR.
Véa la Licencia General Púbica de GNU para mas detalles.
Junto con este programa fuente se distribuye una copia de la
Licencia Púbica General de GNU. Si no es así puede encontrar una
copia en <http://www.gnu.org/licenses/>
Si decides mejorar nuestro código te agradeceremos que nos envíes una copia.
*/
/*! \file main.c*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/*! \typedef SEMAFORO
* Estructura para almacenar un semaforo
*/
typedef struct semaforo
{
char tipo; /**< Indica el tipo de semáforo, puede ser V o P */
char nombre; /**< Indica el nombre del semaforo: a,b,c,.. */
int valor; /**< Valor de la variable semáforo */
struct semaforo * sig; /**< Puntero a otro semáforo */
}SEMAFORO;
/*! \typedef SEMAFOROS
* Lista dinámica de semáforos
* Cada proceso tendrá asoiciado una lista de semáforos
*/
typedef SEMAFORO * SEMAFOROS;
/*! \typedef PROCESO
* Estructura para alamcenar un proceso que este activo en el sistema
*/
typedef struct proceso
{
int pid; /**< Identificador único del proceso */
int tcpu; /**< Contiene la necesidad incial de ciclos de procesador que necesita el proceso */
int necesidad; /**< Contiene la cantidad de ciclos de procesador que necesita el proceso para finalizar */
int arribo; /**< Instante de arribo del proceso */
int contIos; /**< Cuenta la cantidad de IOs del proceso (para el Tiempo de Respuesta) */
int turnAround; /**< TurnAround del proceso */
int tResp; /**< Tiempo de Respuesta del proceso */
int tEListos; /**< Tiempo de Espera en cola de Listos del proceso */
int tESync; /**< Tiempo de Espera en cola de bloqueados por sincronización del proceso */
int tETotal; /**< Tiempo de Espera Total del proceso */
int tEDisp; /**< Tiempo de Uso de Dispositivos */
SEMAFOROS semaforos; /**< Lista dinámica de semáforos asociados al proceso*/
struct proceso *sig; /**< Puntero al próximo proceso */
}PROCESO;
/*! \typedef PROCESOS
* Lista dinámica de procesos
*
*/
typedef PROCESO * PROCESOS;
/*! \typedef EVENTO
* Estructura para alamacenar un evento de ocurrencia en la simulación
*/
typedef struct evento
{
int instante; /**< Instante de ocurrencia del evento */
int pid; /**< PID que genero el evento */
char codigo[4]; /**< Código del evento : ANP,SIO,FIO,V,P,FPR */
char semaforo; /**< Nombre del semáforo, en el caso de que el código se V o P */
struct evento * sig; /**< Puntero al próximo evento */
}EVENTO;
/*! \typedef EVENTOS
* Lista dinámica de eventos
*/
typedef EVENTO * EVENTOS;
/*! \typedef SCALL
* Estructura para almacenar un System Call
*/
typedef struct scall
{
int pid; /**< PID del proceso que solicita servicio */
int instante; /**< Instante de ocurrencia de la solicitud relativo al tiempo de ejecución del proceso */
int resolucion; /**< Tiempo que toma resolver la solicitud de servicio */
char tipo[4]; /**< Tipo de solicitud: SIO, V, P */
char semaforo; /**< char que almacena el semaforo asociado si el tipo es V o P */
struct scall * sig; /**< Puntero al próximo System Call */
}SCALL;
/*! \typedef SCALLS
* Lista dinámica de System Calls
*/
typedef SCALL * SCALLS;
/*! \typedef PROCESOIN
* Estructura para leer una línea del archivo de entrada de procesos (input)
*/
typedef struct procesoIN
{
int pid; /**< PID */
int arribo; /**< Instante de arribo al sistema */
int Tcpu; /**< Tiempo que requiere de CPU */
struct procesoIN *sig; /**< Puntero al próximo proceso */
}PROCESOIN;
/*! \typedef PROCESOSIN
* Lista dinámica de procesos de entrada
*/
typedef PROCESOIN * PROCESOSIN;
/*! \typedef IOIN
* Estructura para leer una línea del archivo de entrada de I/O (input)
*/
typedef struct ioIN
{
int pid; /**< PID */
int instante; /**< Instante de ocurrencia de la solicitud de IO relativo al tiempo de ejecución del proceso */
int tiempo; /**< Tiempo de resolución */
struct ioIN *sig; /**< Puntero al próximo SIO */
}IOIN;
/*! \typedef IOSIN
* Lista dinámica de I/Os de entrada
*/
typedef IOIN * IOSIN;
/*! \typedef PRECIN
* Estructura para leer una línea del archivo de entrada de Precedencia (input)
*/
typedef struct precIN
{
int precedente; /**< PID del proceso que precede */
int precedido; /**< PID del proceso que es pecedido */
struct precIN * sig; /**< Puntero al siguiente */
}PRECIN;
/*! \typedef PRECSIN
* Lista dinámica de reglas de precedencia de entrada
*/
typedef PRECIN * PRECSIN;
/*! \typedef SYSIND
* Estructura para almacenar información de indicadores del sistema
*/
typedef struct sysind
{
float tAroundP; /**< Turn Around Promedio */
float tRespP; /**< Tiempo de Respuesta Promedio */
float tEListosP; /**< Tiempo de Espera en cola de Listos Promedio */
float tESyncP; /**< Tiempo de Espera en cola de sincronización Promedio */
}SYSIND;
/**
* Inserta un evento en la lista de eventos a procesar por el simulador.
* @param eventos Lista de eventos del simulador
* @param e Evento nuevo a ingresar
*/
void insertarEvento(EVENTOS * eventos, EVENTOS * e)
{
EVENTOS act=*eventos,ant=NULL;
while (act!=NULL && act->instante <= (*e)->instante)
{
ant=act;
act = act->sig;
}
//El primero nunca va a ser porque ya estan cargados los arribos.
ant->sig=*e;
(*e)->sig = act;
}
/**
* Mueve un proceso de una cola de origen hacia una cola de destino.
* Dentro de las colas de procesos tanto de origen como de destino
* tambien se tiene en cuenta al cpu como una cola de un único
* proceso.
* @param destino Cola destino a la que hay que agregar el proceso
* @param origen Cola origen de la que hay que quitar el proceso
* @param pid En el caso que el pid sea 0 (cero) moverá de origen el primer elemento, de lo contrario buscara el pid y ese es el que moverá
*/
void moverProceso(PROCESOS * destino,PROCESOS *origen, int pid)
{
PROCESOS actD = *destino,ultD=NULL;
PROCESOS actO = *origen,antO=NULL;
// Siempre tengo que insertar al final del destino por eso lo recorro hasta el ultimo elemento
while (actD != NULL)
{
ultD = actD;
actD = actD->sig;
}
//Si no hay elementos en la cola de destino
if (ultD == NULL)
{
// Si hay que mover el primer elemento de la cola origen:
if (pid == 0)
{
*destino = *origen;
*origen = (*origen)->sig;
(*destino)->sig = NULL;
}
// Si hay que buscar el elemento de la cola origen:
else
{
// Avanzo con antO y actO en la cola de origen hasta encontrar el proceso
while(actO != NULL && actO->pid != pid)
{
antO = actO;
actO = actO->sig;
}
//el primer elemento de la cola destino va a ser el actual de la cola origen
*destino = actO;
//Si el elemento de la cola origen no era el único
if (antO!=NULL)
{
//Desvinculo al actual de la cola de origen
antO->sig = actO->sig;
}
// Si el elemento de la cola origen era el único
else
{
*origen = NULL;
}
// Como es el unico elemento que quedo en la cola de destino, el sig es NULL
(*destino)->sig = NULL;
}
}
// Si hay elementos en la cola de destino tengo en ultD el ultimo elemento de destino
else
{
// Si hay que mover el primer elemento de la cola origen:
if (pid == 0)
{
ultD->sig = *origen;
*origen = (*origen)->sig;
}
//Si hay que buscar el elemento de la cola origen:
else
{
// Avanzo con antO y actO en la cola de origen hasta encontrar el proceso
while(actO != NULL && actO->pid != pid)
{
antO = actO;
actO = actO->sig;
}
//el ultimo elemento de la cola destino va a ser el actual de la cola origen
ultD->sig = actO;
//Desvinculo al actual de la cola de origen
if (antO != NULL)
{
antO->sig = actO->sig;
}
else
{
*origen = (*origen)->sig;
}
ultD = ultD->sig;
ultD->sig = NULL;
}
}
}
/**
* Muestra los PID de los procesos de una lista de procesos.
* @param procesos Lista de procesos a mostrar
*/
void mostrarProcesos(PROCESOS procesos)
{
while (procesos != NULL)
{
printf("%d ",procesos->pid);
procesos = procesos->sig;
}
printf("\n");
}
/**
* Devuelve una lista de semáforos asociados a un proceso determinado por su PID.
* @param procesos Lista de procesos activos donde buscar
* @param pid PID del proceso del que se quieren obtener los semáforos asociados
* @return Devuelve una lista de semáforos
*/
SEMAFOROS obtenerSemaforos(PROCESOS procesos,int pid)
{
while(procesos!=NULL && procesos->pid!=pid)
{
procesos=procesos->sig;
}
return procesos->semaforos;
}
/**
* LLeva adelante la simulación de la ejecución de los procesos de forma concurrente.
*
* @param procesos Lista dinámica de los procesos que se van a simular
* @param scs Lista dinámica de los System Call que se van a simular
* @param eventos Lista incial de eventos que se van a simular
* @param pasoapaso Contiene 1 si se debe mostrar paso a paso la simulación, de lo contrario 0 (cero)
* @param *rp Puntero a una lista de procesos (de salida)
* @param *re Puntero a una lista de eventos (de salida)
* @param *rs Puntero a una lista de SYSIND (de salida)
*/
void simular(PROCESOS procesos,SCALLS scs, EVENTOS eventos, int pasoapaso, PROCESOS *rp, EVENTOS *re, SYSIND *rs)
{
int reloj=0,relojAnt=0;
int pid;
int actInstante;
int pidb;
int antPid=0;
char evento[4];
int semT;
char continua;
PROCESOS cpu;
PROCESOS p,pAct;
EVENTOS e,ef;
SEMAFOROS semAct;
PROCESOS listos = NULL,auxListos;
PROCESOS finalizados = NULL,auxFin;
PROCESOS bloqueadosIO = NULL,auxbloqIO;
PROCESOS bloqueadosSYNC = NULL,auxbloqSYNC;
SCALLS antSC,actSC,aux;
cpu = NULL; //el procesador esta idle
while (eventos!=NULL)
{
reloj = eventos->instante;
// PARECIERA QUE LA CONSIGNA OLVIDA DE SOLICITAR MOSTRAR QUIEN ESTA EN EL CPU. Y EN CAMBIO PIDE PID GENERADOR DEL EVENTO
pid = eventos->pid;
strcpy(evento,eventos->codigo);
// Antes de procesar el evento, le sumamos a los tiempos de espera
// Los que están en listos suman en Tiempo de Espera en cola de Listos
auxListos = listos;
while (auxListos != NULL)
{
auxListos->tEListos += reloj - relojAnt;
auxListos = auxListos->sig;
}
// Los que están en bloqueados SYNC suman en Tiempo de Espera por sincronización
auxbloqSYNC = bloqueadosSYNC;
while (auxbloqSYNC != NULL)
{
auxbloqSYNC->tESync += reloj- relojAnt;
auxbloqSYNC = auxbloqSYNC->sig;
}
// Los que están en bloqueados SYNC suman en Tiempo de Espera por sincronización
auxbloqIO = bloqueadosIO;
while (auxbloqIO != NULL)
{
auxbloqIO->tEDisp += reloj- relojAnt;
auxbloqIO = auxbloqIO->sig;
}
//Procesar el evento
if (!strcmp(evento,"ANP")) // ARRIBO DE NUEVO PROCESO
{
//Busco el proceso en la lista de procesos que se van a simular
pAct = procesos;
while (pAct!= NULL && pAct->pid != eventos->pid)
{
pAct = pAct->sig;
}
//Copio el proceso simulando activarlo en el sistema
p = (PROCESOS)malloc(sizeof(PROCESO));
p->pid = pAct->pid;
p->tcpu = pAct->tcpu;
p->necesidad = pAct->necesidad;
p->arribo = pAct->arribo;
p->contIos = 0;
p->turnAround = 0; // Se calcula cuando se finaiza el proceso
p->tResp = 0; // Se calcula cuando se termina la 1er IO
p->tEListos = 0; // Se calcula en cada iteracion si el proceso esta en listos
p->tESync = 0; // Se calcula en cada iteración si el proceso esta en bloq SYNC
p->tETotal = 0; // Se calcula al final sumando los tiempos de espera
p->tEDisp = 0; // Se calcula en cada iteración si el proceso esta en bloq IO
p->semaforos = pAct->semaforos; // esto esta bien copiado?
p->sig = NULL;
// Si la cola de listos esta vacía y no hay nadie en el procesador:
// asigno al procesador el proceso, de lo contrario lo agrego a listos.
if (listos == NULL && cpu == NULL)
{
moverProceso(&cpu,&p,0);
}
else
{
moverProceso(&listos,&p,0);
}
}
else if (!strcmp(evento,"SIO")) // SOLICITUD DE ENTRADA SALIDA
{
// Envío el proceso que esta en el cpu a la lista de bloqueados por IO
moverProceso(&bloqueadosIO,&cpu,0);
// Verifico si hay alguien listo para ir al procesador.
// Si no hay nadie listo: el cpu queda idle
if (listos == NULL)
cpu = NULL;
else
moverProceso(&cpu,&listos,0);
}
else if (!strcmp(evento,"FIO")) // FIN DE ENTRADA SALIDA
{
if (cpu != NULL)
{
moverProceso(&listos,&bloqueadosIO,pid);
// BUsco el proceso que acaba de terminar su IO en la cola de listos
auxListos = listos;
while (auxListos !=NULL && auxListos->pid != pid)
{
auxListos = auxListos->sig;
}
// Si es el primer FIO entonces calculo el tiempo de respuesta del proceso
if (++auxListos->contIos == 1)
{
auxListos->tResp = reloj - auxListos->arribo;
}
}
else
{
moverProceso(&cpu,&bloqueadosIO,pid);
if (++cpu->contIos == 1)
{
cpu->tResp = reloj - cpu->arribo;
}
}
}
else if (!strcmp(evento,"FPR"))// FIN DE PROCESO
{
// Calculo el Turn Around del proceso que finaliza
cpu->turnAround = reloj - cpu->arribo;
moverProceso(&finalizados,&cpu,0);
// Si no hay nadie listo el cpu queda idle.
if (listos == NULL)
cpu = NULL;
else
moverProceso(&cpu,&listos,0);
}
else if (!strcmp(evento,"P")) // OPERACION P SOBRE UN SEMAFORO
{
semAct = cpu->semaforos;//obtenerSemaforos(procesos,eventos->pid);
while(semAct != NULL && semAct->nombre != eventos->semaforo)
{
semAct = semAct->sig;
}
if (--semAct->valor < 0)
{
moverProceso(&bloqueadosSYNC,&cpu,0);
}
if (cpu == NULL && listos != NULL)
{
moverProceso(&cpu,&listos,0);
}
}
else if (!strcmp(evento,"V")) // OPERACION V SOBRE UN SEMAFORO
{
pAct = bloqueadosSYNC;
while (pAct != NULL)
{
semAct = pAct->semaforos;
while(semAct !=NULL && semAct->nombre != eventos->semaforo)
{
semAct = semAct->sig;
}
if(semAct != NULL && ++semAct->valor >= 0)
{
semAct = pAct->semaforos;
semT=1;
while (semAct !=NULL)
{
if (semAct->tipo == 'P' && semAct->valor < 0)
{
semT = 0;
semAct = NULL;
}
semAct = semAct->sig;
}
if (semT)
{
pidb = pAct->pid;
moverProceso(&listos,&bloqueadosSYNC,pidb);
}
pAct = pAct->sig;
}
else
{
pAct = pAct->sig;
}
}
}
//Mostrar por pantalla el paso si corresponde
if (pasoapaso)
{
system("clear");
printf("******************************************************************\n");
printf(" SIMULACIÓN PASO A PASO\n");
printf("******************************************************************\n");
printf("\n");
printf("RELOJ: %d\n",reloj);
if (cpu!=NULL) printf("CPU: %d\n",cpu->pid); else printf("CPU: idle\n");
printf("------------------------------------\n");
printf("---- DATOS DEL EVENTO PROCESADO ----\n");
printf("TIPO DE EVENTO: %s\n",evento);
printf("PID: %d\n",pid);
printf("------------------------------------\n");
printf("--------- COLAS DE PROCESOS --------\n");
if (listos != NULL) {printf("Listos: ");mostrarProcesos(listos);}
if (finalizados != NULL) {printf("Finalizados: ");mostrarProcesos(finalizados);}
if (bloqueadosIO != NULL) {printf("Bloqueados por I/O: ");mostrarProcesos(bloqueadosIO);}
if (bloqueadosSYNC != NULL) {printf("Bloqueados por sincronización: ");mostrarProcesos(bloqueadosSYNC);}
printf("\n");
printf("------------------------------------");
printf("¿Desea continuar? s/n : ");
fflush(stdin);
continua=getchar();getchar();
printf("\n");
if (continua == 'n') pasoapaso = 0;
}
//Buscar el próximo system call del proceso que esta en ejecución.
//** SOLO SI HAY UN PROCESO EN EJECUCIÓN!! **>
if (cpu != NULL)
{
if (cpu->pid != antPid || eventos->sig == NULL)
{
actSC = scs;
antSC = NULL;
while (actSC != NULL && actSC->pid != cpu->pid)
{
antSC = actSC;
actSC = actSC->sig;
}
// Si hay un system call para el proceso que esta en ejecución
// lo agrego a los eventos
// y lo elimino del los system calls
if (actSC!=NULL)
{
do
{
e = (EVENTOS) malloc(sizeof(EVENTO));
strcpy(e->codigo,actSC->tipo);
e->instante = reloj + actSC->instante - (cpu->tcpu - cpu->necesidad);
e->pid = actSC->pid;
if(!strcmp(e->codigo,"SIO"))
{
ef = (EVENTOS) malloc(sizeof(EVENTO));
strcpy(ef->codigo,"FIO");
ef->instante = reloj + actSC->instante - (cpu->tcpu - cpu->necesidad) + actSC->resolucion;
ef->pid = actSC->pid;
insertarEvento(&eventos,&ef);
}
else if(!strcmp(e->codigo,"P"))
{
e->semaforo = actSC->semaforo;
}
else if(!strcmp(e->codigo,"V"))
{
e->semaforo = actSC->semaforo;
}
insertarEvento(&eventos,&e);
actInstante = actSC->instante;
if (antSC == NULL) // el SC fue el primero de la lista
{
scs = scs->sig;
actSC = actSC->sig;
}
else
{
aux = actSC;
actSC = actSC->sig;
antSC->sig = actSC;
free(aux);
}
}
while ((actSC != NULL && actInstante == actSC->instante && !strcmp(actSC->tipo,"V"))); //|| (eventos->sig == NULL && actSC->sig != NULL));
}
if (eventos->sig != NULL)
{
cpu->necesidad -= eventos->sig->instante - reloj;
if (cpu->necesidad <= 0)
{
e = (EVENTOS) malloc(sizeof(EVENTO));
strcpy(e->codigo,"FPR");
// la necesidad es cero o negaitva por lo que esta suma en realidad resta ¡¡@K¡¡
e->instante = eventos->sig->instante + cpu->necesidad;
e->pid = cpu->pid;
insertarEvento(&eventos,&e);
}
}
else
{
e = (EVENTOS) malloc(sizeof(EVENTO));
strcpy(e->codigo,"FPR");
// la necesidad es cero o negaitva por lo que esta suma en realidad resta ¡¡@K¡¡
e->instante = reloj + cpu->necesidad;
e->pid = cpu->pid;
insertarEvento(&eventos,&e);
}
}
antPid = cpu->pid;
}
//Antes de avanzar al siguiente evento, lo guardo para el trace.txt
EVENTOS ultE;
if (*re == NULL)
{
*re = eventos;
eventos = eventos->sig;
(*re)->sig = NULL;
}
else
{
ultE = *re;
while (ultE->sig != NULL)
{
ultE = ultE->sig;
}
ultE->sig = eventos;
eventos = eventos->sig;
ultE = ultE->sig;
ultE->sig = NULL;
}
relojAnt = reloj;
}
//Antes de terminar la simulación copio los procesos finalizados a procesos de salida
auxFin = finalizados;
while (auxFin != NULL)
{
auxFin->tETotal = auxFin->tEListos + auxFin->tESync + auxFin->tEDisp;
auxFin = auxFin->sig;
}
*rp = finalizados;
}
/**
* Escribe los resultados de la simulación a archivos de texto.
* @param p Lista de procesos
* @param e Lista de eventos
* @param s Estructura de Indicadores del Sistema
*
*/
int escribirResultados(char * archp, char * archs, char * arche,PROCESOS p,SYSIND s, EVENTOS e)
{
int cont;
FILE *fe;
fe = fopen(arche,"w");
printf("Generando archivo de eventos procesados...\n");
fprintf(fe,"Archivo generado automaticamente por el simulador...\n");
fprintf(fe,"\n");
fprintf(fe,"INSTANTE\t\tPID\t\tEVENTO\t\tSEMAFORO\n");
while (e != NULL)
{
fprintf(fe,"%d\t\t%d\t\t%s\t\t%c\n",e->instante,e->pid,e->codigo,e->semaforo);
e = e->sig;
}
fclose(fe);
FILE *fp;
fp = fopen(archp,"w");
printf("Generando archivo de indicadores de procesos...\n");
fprintf(fp,"Archivo generado automaticamente por el simulador...\n");
fprintf(fp,"\n");
fprintf(fp,"PID\t\tTURNAROUND\tT° RESP\t\tT° E LISTOS\tT° E SYNC\tT° E DISP\tT° E TOTAL\n");
while (p != NULL)
{
fprintf(fp,"%d\t\t%d\t\t%d\t\t%d\t\t%d\t\t%d\t\t%d\n",p->pid,p->turnAround,p->tResp,p->tEListos,p->tESync,p->tEDisp,p->tETotal);
cont ++;
s.tAroundP += p->turnAround;
s.tRespP += p->tResp;
s.tEListosP += p->tEListos;
s.tESyncP += p->tESync;
p = p->sig;
}
fclose(fp);
if (s.tAroundP != 0) s.tAroundP = (float) s.tAroundP / cont;
if (s.tRespP != 0) s.tRespP = (float) s.tRespP / cont;
if (s.tEListosP != 0) s.tEListosP = (float) s.tEListosP / cont;
if (s.tESyncP != 0) s.tESyncP = (float) s.tESyncP / cont;
FILE *fs;
fs = fopen(archs,"w");
printf("Generando archivo de indicadores a nivel sistema...\n");
fprintf(fs,"Archivo generado automaticamente por el simulador...\n");
fprintf(fs,"\n");
fprintf(fs,"TurnAround Promedio = %2.2f\n",s.tAroundP);
fprintf(fs,"Tiempo de Respuesta Promedio = %2.2f\n",s.tRespP);
fprintf(fs,"Tiempo de Espera en Listos Promedio = %2.2f\n",s.tEListosP);
fprintf(fs,"Timepo de Espera por Sync Promedio = %2.2f\n",s.tESyncP);
return 1;
}
/**
* Imprime la ayuda del sistema.
* La ayuda se ejecuta con el parámetro -h o --help pasado como argumento del programa en su ejecución
*/
void imprimirAyuda()
{
printf("Modo de uso:\n");
printf("simulador [-p arhivo de entrada de procesos] [-io archivo de entrada de solicitudes de I/O] [-prec archivo de entrada de precedencia de procesos] [-rs archivo de resultados a nivel sistema] [-rp archivo de resultados de procesos] [-ev archivo de salida de eventos tratados]\n");
printf("\n");
printf("* Los parámetros son todos opcionales. No importa el orden.\n");
printf("* En el caso de que no se indique algun parámetro estos se tomarán por defecto de acuerdo a:\n");
printf(" -p : procesos.txt\n");
printf(" -io : io.txt\n");
printf(" -prec : precedencia.txt\n");
printf(" -rs : sys-ind.txt\n");
printf(" -rp : proc-ind.txt\n");
printf(" -ev : trace.txt\n");
printf("\n");
printf("\n");
printf("* El programa simulador cuenta con un menú de opciones entre las que se puede elejir:\n");
printf(" 1) Simulación paso a paso -> Le permite visualizar en cada instante:\n");
printf(" - Reloj (Instante de tiempo)\n");
printf(" - CPU (Proceso que se esta ejecutando)\n");
printf(" - Datos del evento procesado (Tipo de evento y PID que lo generó)\n");
printf(" - Colas de procesos, si tienen elementos (Listos, Bloqueados por IO, Bloqueados por SYNC, Finalizados)\n");
printf(" ** Además le permite en cualquier instante no continuar y generar directamente los resultados.\n");
printf("\n");
printf(" 2) Generar directamente resultados de la simulación -> Genera los resultados y finaliza el programa\n");
printf("\n");
printf(" 3) Salir inmediatamente! -> Finaliza el programa :) \n");
printf("\n");
printf("\n");
printf("* Este programa tiene fines educativos y esta licenciado por sus autores con la licencia GNU GPL v3 o posterior\n");
printf("* Para ver una copia de la licencia puede entrar en http://www.gnu.org/licenses/gpl-3.0.txt\n");
printf("* Para reportar bugs o invitarnos una cerveza ;):\n\t** Federico M. F. Daguerre - <fetudaguerre@gmail.com>\n\t** Alan Buscaglia - <alanbuscaglia@gmail.com>\n\t** Giuliana Pennisi - <giupennisi92@gmail.com>\n\t** Gonzalo Aristoy - <gonzaloaristoy@hotmail.com>\n");
printf("\n");
printf("*************************************************************\n");
}
/**
* Comprueba los parámetros de entrada del sistema.
* Entre las comprobaciones que realiza controla la cantidad, la validez y si algun parámetro esta repetido.
* @param argc Cantidad de argumentos recibidos en la ejecución
* @param argv Arreglo con los argumentos recibidos en la ejecución
* @return Devuelve 1 si se comprueban los parámetros correctamente o 0 (cero) en otro caso
*/
int comprobarParametros(int argc, char *argv[])
{
/*
* Datos de entrada
-p nombre archivo Para especificar archivo de procesos
-io nombre archivo Para especificar archivo de solicitudes de I/O de cada proceso
-prec nombre archivo Para especificar archivo precedencia de los procesos
Datos de salida
-rs nombre archivo Para especificar archivo de resultados a nivel sistema
-rp nombre archivo Para especificar archivo de resultados a nivel proceso
-ev nombre archivo Para especificar archivo de eventos tratados
*/
// Si solo envío un parámetro y ademas el parámetro es --help o -h
if (argc == 2 && (!strcmp(argv[1],"--help") || !strcmp(argv[1],"-h")))
{
imprimirAyuda();
return 0;
}
// Si se envío algun parámetro, estos tienen que venir "paramtero" "valor"
// Por lo que si, restando el argv[0] la cantidad de parámetros es impar: error
// O si la cantidad de parametros es mayor a 10: error
if ((argc > 1 && (argc -1) % 2 != 0) || argc > 10)
{
printf("Error: Cantidad de parámetros incorrectos.\n");
imprimirAyuda();
return 0;
}
int i;
// Verifico que las opciones de parámetros sean válidas
for (i=1; i<argc; i+=2)
{
if (strcmp(argv[i],"-p") && strcmp(argv[i],"-io") && strcmp(argv[i],"-prec") && strcmp(argv[i],"-rs") && strcmp(argv[i],"-rp") && strcmp(argv[i],"-ev"))
{
printf("Error: El parámetro %s es inválido!.\n",argv[i]);
imprimirAyuda();
return 0;
}
}
// Verifico que no hay parámetros repetidos
int j=1,k;
while (j<argc)
{
k=j+2;
while (k<argc && strcmp(argv[j],argv[k])) k+=2;
if (k<argc)
{
printf("Error: Parámetro %s repetido.\n",argv[j]);
imprimirAyuda();
return 0;
}
j+=2;
}
return 1;
}
/**
* Carga los archivos de texto a lista dinámicas para ser utilizados por el sistema.
* @param p Ruta del archivo de entrada de Procesos
* @param io Ruta del archivo de entrada de I/O
* @param prec Ruta del archivo de entrada de Precedencia
* @param procesos Lista dinámica donde se cargan los Procesos
* @param ios Lista dinámica donde se cargan las I/O
* @param precs Lista dinámica donde se carga la Precedencia
* @return Devuelve 1 si se cargaron los 3 archivos de forma correcta o 0 (cero) en otro caso
*/
int cargarArchivos(char *p, char *io, char *prec,PROCESOSIN *procesos, IOSIN *ios, PRECSIN *precs)
{
FILE * fp,* fio,* fprec;
PROCESOSIN ultimoProceso,antP;
IOSIN ultimoIo,antIo;
PRECSIN ultimoPrec,antPr;
// Cargo la lista de los procesos de entrada desde el archivo de procesos de entrada.
fp = fopen(p,"r");
if (fp!=NULL || !feof(fp))
{
*procesos = (PROCESOSIN)malloc(sizeof(PROCESOIN));
if(fscanf(fp,"%d %d %d",&((*procesos)->pid),&((*procesos)->arribo),&((*procesos)->Tcpu))==3)
{
(*procesos)->sig = NULL;
ultimoProceso = *procesos;
}
else
{
free(*procesos);
}
while(!feof(fp))
{
ultimoProceso->sig = (PROCESOSIN)malloc(sizeof(PROCESOIN));
antP = ultimoProceso;
ultimoProceso = ultimoProceso->sig;
if (fscanf(fp,"%d %d %d",&(ultimoProceso->pid),&(ultimoProceso->arribo),&(ultimoProceso->Tcpu))!=3)
{
free(ultimoProceso);
ultimoProceso = antP;
}
ultimoProceso->sig=NULL;
}
}
else
{
return 0;
}
fclose(fp);
// Cargo la lista de los io de entrada desde el archivo de io de entrada.
fio = fopen(io,"r");
if (fio!=NULL && !feof(fio))
{
*ios = (IOSIN)malloc(sizeof(IOIN));
if(fscanf(fio,"%d %d %d",&((*ios)->pid),&((*ios)->instante),&((*ios)->tiempo))==3)
{
(*ios)->sig = NULL;
ultimoIo = *ios;
}
else
{
free(*ios);
}
while(!feof(fio))
{
ultimoIo->sig = (IOSIN) malloc(sizeof(IOIN));
antIo = ultimoIo;
ultimoIo = ultimoIo->sig;
if(fscanf(fio,"%d %d %d",&(ultimoIo->pid),&(ultimoIo->instante),&(ultimoIo->tiempo))!=3)
{
free(ultimoIo);
ultimoIo = antIo;
}
ultimoIo->sig = NULL;
}
}
else
{
return 0;
}
fclose(fio);
// Cargo la lista de los precs de entrada desde el archivo de precs de entrada
fprec = fopen(prec,"r");
if (fprec!=NULL && !feof(fprec))
{
*precs = (PRECSIN) malloc(sizeof(PRECIN));
if(fscanf(fprec,"%d %d",&((*precs)->precedente),&((*precs)->precedido))==2)
{
(*precs)->sig = NULL;
ultimoPrec = *precs;
}
else
{
free(*precs);
}
while(!feof(fprec))
{
ultimoPrec->sig = (PRECSIN) malloc(sizeof(PRECIN));
antPr = ultimoPrec;