Skip to content
Snippets Groups Projects
Commit 7c7a84a7 authored by carmuno's avatar carmuno :tennis:
Browse files

changes 
parent c43a810d
No related branches found
No related tags found
No related merge requests found
Showing
with 519 additions and 0 deletions
File added
//Carlos Noe Muñoz Bastardo 71205516t
//Martín Tornero Vazquez 71180133d
//LIBRERIAS UTILIZADAS.
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h> //Libreria de funciones para el trabajo con strings
#include <pthread.h> //Libreria con funciones de hilos
#include <semaphore.h> //Libreria con funciones de semaforos
#include <unistd.h>
#include <stdbool.h>
#include <ctype.h>
//PARAMETROS POR DEFECTO.
#define NPARAM 4 //Número de parámetros a utilizar
#define MAX_NUM 3000000 //Valor máximo que encontraremos en el archivo
#define LINE_SIZE 255 //Tamaño máximo de linea en el archivo
//CREACION DE LAS ESTRUCTURAS (INTERVALO Y CONSUMIDO).
typedef struct {//Utilizada para pasar los datos obtenidos al consumidor final.
int max;
int min;
int totalAmount;//Suma total
double average;//Media
int consumed;//Datos consumidos
int id;//Id local
int lowRange;
int highRange;
double mediana;
}consumido;
consumido *finalBuffer;
struct nodo {
int info;
struct nodo *sig;
};
typedef struct { //Estructura creada para cada hilo consumidor, declara su rango mayor y menor y un identificador de hilo.
int lowRange;
int highRange;
int id;
} tipointervalo;
//VARIABLES GLOBALES
int bufferSize; //Parametro introducido por el usuario
int numConsumers; //Parametro introducido por el usuario
int i,j;
int *buffer; //Variable global utilizada para el buffer para productores y consumidores.
int bufferPointer=0; //Variable utilizada para continuarrer el buffer.
int globalId; //Identificador global de hilo consumidor.
//DECLARACION DE SEMAFOROS.
sem_t hay_dato;
sem_t hayespacio;
sem_t mutex_critic;
sem_t mutex_final;
sem_t mutex_globalId;
sem_t mutex_finished;
//Funcion para la liberacion de nodos.
void liberar(struct nodo * raiz){
struct nodo *reco = raiz;
struct nodo *bor;
while (reco != NULL)
{
bor = reco;
reco = reco->sig;
free(bor);
}
}
//Funcion utilizada para introducir los elementos que quieren ser colocados y colocarlos de menor a mayor.
struct nodo* insertar(int x, struct nodo *nuevo, struct nodo *raiz){
nuevo=malloc(sizeof(struct nodo));
nuevo->info = x;
nuevo->sig=NULL;
if (raiz == NULL){
raiz = nuevo;
}
else{
if (x<raiz->info){
nuevo->sig = raiz;
raiz = nuevo;
}
else{
struct nodo *reco = raiz;
struct nodo *atras = raiz;
while (x >= reco->info && reco->sig != NULL){
atras = reco;
reco = reco->sig;
}
if (x >= reco->info){
reco->sig = nuevo;
}
else{
nuevo->sig = reco;
atras->sig = nuevo;
}
}
}
return raiz;
}
//Funcion que lista los nodos colocados.
/*void imprimir(){
struct nodo *reco=raiz;
printf("Lista completa.\n");
while (reco!=NULL){
printf("%i ",reco->info);
reco=reco->sig;
}
printf("\n");
}*/
//Funcion que calcula la mediana
double calcularMediana(int numnodos, struct nodo *cabesa){
struct nodo *rr = cabesa;
double mediana;
int valor = 0;
int anterior = 0;
int counter=0;
while(counter!=numnodos/2 && rr->sig!= NULL){
valor = rr->info;
if(counter!=(numnodos/2)-1){
anterior = rr->info;
}
rr=rr->sig;
counter++;
} //cuando se salga de aqui vamos a posicionarnos en la mitad del array.
if(numnodos % 2 == 0){
int sumaMedios = valor + anterior;
mediana = (double)sumaMedios / 2;
}
if(numnodos % 2 != 0){
mediana = rr->info;
}
return mediana;
}
//FUNCION DE COMPROBACION DE ENTEROS.
int checkInt (char punt []){
int flag =1;
for(int y = 0; y<strlen(punt); y++){
if(!isdigit(punt[y]) && punt[y]!='\n'){//Mientras no sea digito & no sea un salto de linea.
flag = 0;
break;
}
}
return flag;
}
//HILO PRODUCTOR
void *productor(void *fileName){ //Hilo productor cuya funcion es leer del fichero e introducirlo en un buffer con solo enteros.
FILE *fich;
int number = 0;
int bufferPointerP=0;
char lineSize[LINE_SIZE];
fich=fopen((char *) fileName,"r");//Validacion de apertura del fichero
if(fich==NULL){
printf("No se ha podido abrir el fichero (Comprobacion 2)");
exit(1);
}
while(fgets(lineSize,LINE_SIZE,fich)){ //Mientras haya algo que leer en el fichero sigue leyendo.
if(checkInt(lineSize)){ //Comprueba que el contenido sea un entero es number.
number=atoi(lineSize); //Convierte los string en enteros.
sem_wait(&hayespacio); //hay espacio?
buffer[bufferPointerP]= number;//Se rellena el buffer con los enteros del fichero
sem_post(&hay_dato); //el dato ya ha sido introducido
bufferPointerP = (bufferPointerP+1)%bufferSize;//Se aumenta el puntero del buffer circular
}
}
fclose(fich); //cierra el fichero al final del todo.
//Cuando haya espacio introduce un -1 en la ultima posicion del buffer para que los consumidores sepan que han llegado al final.
sem_wait(&hayespacio);
buffer[bufferPointerP]= -1;
sem_post(&hay_dato); //Cuando introducimos un -1 no se consume ningun dato por lo que sigue habiendo dato.
pthread_exit(NULL);
}
//HILOS CONSUMIDORES
void* consumidores (void* consumeIntervalo){ //Consumidor cuya labor es consumir los datos del buffer creados por el productor en su rango determinado.
tipointervalo *p = (tipointervalo*) consumeIntervalo; //Puntero de tipo tipointervalo utilizado para pasar al consumidor la estructura con los rangos que debe introducir.
int lowRange = p->lowRange;
int highRange = p->highRange;
int id = p->id;
int max = 0;
int min = MAX_NUM+1; //Valor max.
int totalAmount = 0;
double average;
double mediana;
struct nodo *pruebas;
struct nodo *raiz=NULL;
struct nodo *rrr;
int cont=0;//Contador local para saber cuantos datos se han consumido
int datoBuffer;
bool enter = true;//Boleano para la entrada en el bucle de consumicion.
bool seconsume = false;//Boleano para la entrada en el el segundo if para consumir.
while(enter){
sem_wait(&hay_dato);//Hay dato??
sem_wait(&mutex_critic);//Entrada en seccion critica
datoBuffer=buffer[bufferPointer];// Crea datoBuffer.
if((lowRange<=datoBuffer)&&(datoBuffer<=highRange)){//Si se encuentra dentro del rango de valores que debe consumir aumenta el iterador.
bufferPointer=(bufferPointer+1)%bufferSize;//Itera el buffer ciruclar.
seconsume= true;
sem_post(&hayespacio);//Hay espacio porque ha aumentado el iterador.
}
sem_post(&mutex_critic);//Salida de seccion critica.
if(datoBuffer==-1){//En caso de que el consumidor encuentre un -1 termina de consumir ya que ha leido todos los datos.
enter=false;
seconsume=false;
sem_post(&hay_dato);//Hay dato ya que no lo ha consumido.
}else if(seconsume){//Si se encuentra entre el rango de valores que debe consumir lo consume
raiz = insertar(datoBuffer, pruebas,raiz);
seconsume= false;
cont++;//Variable local utilizada para saber el number de datos consumidos.
totalAmount=totalAmount+datoBuffer; //Suma a la suma total cada vez que consume un dato.
if(datoBuffer>max){//Calculo del maximo.
max=datoBuffer;
}
if(datoBuffer<min){//Calculo del minimo.
min=datoBuffer;
}
}else sem_post(&hay_dato);//En caso de que no consuma-->Hay dato
}
if(min==MnAX_NUM+1){
min=0;
}
if(cont!=0){//Calculo de la media, en caso de que el numerto de datos consumidos sea 0 no se realiza para evitar coma flotante.
average=(double)totalAmount/cont;
}
rrr = raiz;
mediana = calcularMediana(cont, rrr);
liberar(raiz);
//Paso de resultados a la estrura final.
finalBuffer[id].id=id;
finalBuffer[id].max = max;
finalBuffer[id].min = min;
finalBuffer[id].average = average;
finalBuffer[id].totalAmount = totalAmount;
finalBuffer[id].consumed=cont;
finalBuffer[id].highRange=highRange;
finalBuffer[id].lowRange=lowRange;
finalBuffer[id].mediana= mediana;
sem_wait(&mutex_globalId);//Proteccion del identificador global del hilo consumidor.
globalId = id;
sem_post(&mutex_finished);//Se ha terminado de consumir.
pthread_exit(NULL);
}
//HILO CONSUMIDOR FINAL
void *consumidorFinal(void* finalFileName){
FILE* finalFile;
finalFile=fopen((char*) finalFileName, "w");//Creacion del fichero final para escritura.
if(finalFile==NULL){//Comprobacion de si se ha creado correctamente.
printf("No se ha podido crear el fichero");
}
for(int i=0;i<numConsumers;i++){
sem_wait(&mutex_finished);//Ha terminado de consumir??
//Introduccion de los datos al fichero final
fprintf(finalFile,"\n======RANGO DEL HILO %d [%d]-[%d]======\n",finalBuffer[globalId].id,finalBuffer[globalId].lowRange,finalBuffer[globalId].highRange);
fprintf(finalFile,"En número total de datos del hilo %d es: %d\n", finalBuffer[globalId].id, finalBuffer[globalId].consumed);
fprintf(finalFile,"La suma total de los datos consumidos del hilo %d es: %d\n",finalBuffer[globalId].id, finalBuffer[globalId].totalAmount);
fprintf(finalFile,"El mínimo del hilo %d es: %d\n", finalBuffer[globalId].id, finalBuffer[globalId].min);
fprintf(finalFile,"El máximo del hilo %d es: %d\n", finalBuffer[globalId].id, finalBuffer[globalId].max);
fprintf(finalFile,"La media del hilo %d es: %.6f\n", finalBuffer[globalId].id, finalBuffer[globalId].average);
fprintf(finalFile,"La mediana del hilo %d es: %3.f\n",finalBuffer[globalId].id,finalBuffer[globalId].mediana);
sem_post(&mutex_globalId);//Proteccion del identificador global de consumidor.
}
fclose(finalFile);//Cerrado del fichero final.
pthread_exit(NULL);
}
//MAIN DEL PROGRAMA
int main(int arg, char *argv[] ){ //Lanzadera del programa, se le pasaran argumentos por linea de comandos: Fichero inicial, fichero final, numero de consumidores y tamaño del buffer.
FILE *punt;
FILE *result;
int lowRange;
int highRange;
int quantum;
tipointervalo *rangeVector;
pthread_t *tids;
pthread_t hproductor;
//VALIDACION DE DATOS INTRODUCIDOS
if(arg !=NPARAM+1){ //El numero de parametros introducido debe de ser correcto.
printf("El number de argumentos introducido es incorrecto, debes introducir un fichero de entrada, uno de salida, el tamaño del buffer y el number de consumidores.\n");
exit(1);
}
punt=fopen(argv[1],"r");
if(punt==NULL){ //En caso de que no se pueda abrir el fichero manda mensaje y termina el programa.
printf("No se ha podido abrir el fichero.\n");
exit(1);
}
fclose(punt);
result=fopen(argv[2],"w");
if(result==NULL){//En caso de que no se pueda crear el fichero final manda mensaje y termina el programa.
printf("No se ha podido crear el fichero");
exit(1);
}
if(!checkInt(argv[3])){//Comprueba que el tercer argumento (tamaño del buffer) es un entero.
printf("Error al introducir el tamaño del buffer, debe de ser un entero. \n");
exit(1);
}
if(!checkInt(argv[4])){//Comprueba que el cuarto argumento (number de consumidores) es un entero.
printf("Error al introducir el number de consumidores, debe de ser un entero. \n");
exit(1);
}
//Se convierten los argumentos validados a enteros y se hacen variables globales.
bufferSize = atoi(argv[3]);
numConsumers = atoi (argv[4]);
//Creacion del buffer de tamaño dinamico.
buffer=(int*)malloc(bufferSize*sizeof(int));
if (buffer==NULL){//Comprobacion de que la reserva de memoria del buffer sea correcta.
printf("Reserva de memoria del buffer fallida");
}
//Creacion del vector de rangos de tamaño dinamico.
rangeVector=(tipointervalo *)malloc(numConsumers*sizeof(tipointervalo));
if (rangeVector==NULL){//Comprobacion que la reserva de memoria del vector de rangos sea correcta.
printf("Reserva de memoria del buffer fallida");
}
//INICIALIZACION DE SEMAFOROS.
sem_init(&hayespacio,0,bufferSize);//Semaforo utilizado para comprobar si hay espacio en el buffer, se inicializa al tamaño del buffer
sem_init(&mutex_critic,0,1);//Semaforo utilizado para la sección critica de llenado del buffer.
sem_init(&hay_dato,0,0);//Comprobacion si hay dato introducido en el buffer.
sem_init(&mutex_finished,0,0);//Protege la introducción de datos en la estructura consumidor final.
sem_init(&mutex_globalId,0,1);//Utilizado para la proteccion del identificador global ha la hora de darle valor y utilizarlo.
finalBuffer= (consumido*)malloc(numConsumers*sizeof(consumido)); //Utilizado para la estructura del hilo consumidor final
if(finalBuffer==NULL){
printf("Reserva de memoria del structura fallida");
}
//CREACION DE LOS HILOS
tids = (pthread_t *)malloc(numConsumers*sizeof(pthread_t)); //Asignacion de memoria para los hilos consumidores.
if (tids==NULL){
printf("Reserva de memoria del buffer fallida");
}
pthread_t hconsumidorFinal; //Hilo consumidor final.
quantum= MAX_NUM/numConsumers;//Calculo del quantum.
for (int u=1;u<numConsumers+1;u++) { //Se lanzan todos los hilos consumidores y cada hilo consumidor recibe.
//Calculo del rango a consumir de cada consumidor.
if(u==numConsumers){
highRange=MAX_NUM;
lowRange = (u-1)*quantum;
}
else{
lowRange = (u-1)*quantum; //Calculo del rango que debe consumir cada consumidor
highRange = u*(quantum-1)+(u-1);
}
//Se pasan los rangos obtenidos a una estructura para que cada hilo consumidor disponga de ellos.
rangeVector[u-1].lowRange=lowRange;
rangeVector[u-1].highRange=highRange;
rangeVector[u-1].id= u-1;
//Lanzamiento de los hilos consumidores
pthread_create(&tids[u-1],NULL,consumidores,(void*) &rangeVector[u-1]);//Una vez calculados los rangos se crean los hilos consumidores.
}
//Lanzamiento del hilo productor.
pthread_create(&hproductor,NULL,productor,(void*) argv[1]); //Se le pasa como parametro el argumento 1 (nombre del fichero de entrada).
//Lanzamiento del hilo consumidor final.
pthread_create(&hconsumidorFinal,NULL,consumidorFinal,(void *)argv[2]);//Se le pasa como parametro el argumento 2 (nombre del fichero de salida).
//Cierre del hilo productor.
pthread_join(hproductor,NULL);
//Cierre de los hilos consumidores.
for(int u = 0; u<numConsumers;u++){
pthread_join(tids[u],NULL);
}
//Cierre del hilo consumidor final.
pthread_join(hconsumidorFinal,NULL);
//Liberacion de memoria dinamica
free(buffer);
free(rangeVector);
free(tids);
free(finalBuffer);
//Destruccion de semaforos
sem_destroy(&hay_dato);
sem_destroy(&hayespacio);
sem_destroy(&mutex_final);
sem_destroy(&mutex_critic);
sem_destroy(&mutex_finished);
return(0);
}
\ No newline at end of file
File added
File added
File added
File added
File added
File added
File added
File added
File added
File added
File added
File added
teoría/PHOTO-2019-11-21-19-03-29 2.jpg

174 KiB

teoría/PHOTO-2019-11-21-19-03-42 2.jpg

168 KiB

teoría/PHOTO-2019-11-26-18-03-10.jpg

121 KiB

teoría/PHOTO-2019-11-26-18-03-18.jpg

124 KiB

0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment