/* ---------------------------------- Semestrální práce č. 16 Autor: Martin Bruchanov Skupina: Úterý 11:00 ---------------------------------- Zadání: Průbězný sort Simulujte průbězný sort. Jsou dány procesy P, S a C. Proces P zasílá náhodná čísla procesu S max. rychlostí čísel za jednotku času. Proces S třídí tyto čísla. rychlostí u komparací za jednotku času a zasílá nejnižší dostupná čísla procesu C (pokud nejsou k dispozici, je proces C uspán). Odesláná data jsou v procesu S smazána. Na závěr chování pro různě velké hodnoty u a v. Implementace Po spuštění programu se vytvoří dva nové procesy: S - třídící proces C - odchytávací Ještě v rodičovkém procesu je vytvořena dvojice datových rour, které slouží pro posílání dat mezi P -> S a S -> C. O korektní ukončení programu se stará rutina pověšená na signálech SIGINT a SIGTERM, která nastaví globální proměnou QUIT, která procesu říká že má končit. Třídění v procesu S jsem značně zjednodušil pomocí knihovní funkce qsort. Tento zpusob je ovsem nevhodný, protože nové prvky se umísťují do setříděného pole, takže zatřiďování lze provést algoritmem se složitosí n (qsort má n*lg(n)). Uspání procesu C není řešeno v programu, díky sys. volání read, je proces v případě, že v rourě nejsou žádná data uspán v kernel módu. Při ukončení přicházím o data, která zustávají v bufferu procesu S, takže to možný duvod pro menší vylepšení. */ #include #include #include #include #include #include #include #include /* Rozsah hodnot generovanych nahodnych cisel */ #define ROZSAH_RND 1000 /* Doba cekani mezi poslanim dvou cisel v mikrosekundach */ #define CEKEJ_USEC 1000000 #define BUFFER 1000 #define SENDING_BUFFER 5 typedef struct { unsigned int pocet; int *mem; } s_pamet; /************************** * * * Globalni promenne * * * **************************/ sig_atomic_t QUIT = 0; /* if 1 KONEC */ /* Osetreni ukonceni programu pri CTRL+C a prijeti signalu SIGTERM */ void ukonceni(void){ QUIT++; } int porovnani(const void* A, const void* B){ if( *((int *) A) > *((int *) B) ) return 1; if( *((int *) A) < *((int *) B) ) return -1; return 0; } int main(){ int roura[2], vylevka[2]; unsigned int cislo, prijem; struct sigaction akce; pid_t S, C; /* Obsluha signalu SIGINT a SIGINT */ memset (&akce, 0, sizeof (akce)); akce.sa_handler = (void *)&ukonceni; sigaction(SIGINT, &akce, NULL); /* CTRL + C*/ sigaction(SIGTERM, &akce, NULL); /* kill */ /* Vytvoreni datove roury */ if(pipe(roura)==-1 || pipe(vylevka)==-1){ perror("pipe"); return -1; } /* ---------------- */ /* Tridici proces */ /* ---------------- */ S = fork(); if( !S ){ int TRIDIM, j; s_pamet prostor = {0, NULL}; close(roura[1]); close(vylevka[0]); for(;;){ // TRIDIM = 0; // if(QUIT && TRIDIM){ if(read(roura[0], &prijem, sizeof(prijem)) == sizeof(prijem)) printf("S prijal %u -> ", prijem); if(!(prostor.pocet % BUFFER)){ /* Pametovy prostor kde se to bude tridit */ prostor.mem = (int *) realloc(prostor.mem, (prostor.pocet + BUFFER) * sizeof(int)); } prostor.mem[prostor.pocet] = prijem; prostor.pocet++; /* Zatridovani */ // Vymyslet lepsi algoritmus, qsort sloz. n*log2(n) qsort(prostor.mem, prostor.pocet, sizeof(int), porovnani); /* Vypis bufferu */ for(j = 0; j <= SENDING_BUFFER; j++){ printf("%d ", prostor.mem[j]); } putchar('\n'); if(prostor.pocet > SENDING_BUFFER){ /* Posilani nejmensiho cisla procesu C */ write(vylevka[1], prostor.mem, sizeof(int)); /* zruseni prvniho prvku */ prostor.pocet--; memmove(prostor.mem, prostor.mem+1, (prostor.pocet)*sizeof(int)); } if(QUIT){ fprintf(stderr, "Tridici proces %d vypina!\n", getpid()); return 0; } } } /* ---------------- */ /* Odchytavac cisel */ /* ---------------- */ C = fork(); if( !C ){ int prijem; close(vylevka[1]); for(;;){ if(read(vylevka[0], &prijem, sizeof(prijem)) == sizeof(prijem)) printf("C prijal %d \n", prijem); if(QUIT){ fprintf(stderr, "Odchytavaci proces %d vypina!\n", getpid()); return 0; } } } /* -------------------------------------- */ /* Generovani cisel v rodicovskem procesu */ /* -------------------------------------- */ close(roura[0]); srandom(time(NULL)); for(;;){ cislo = random() % ROZSAH_RND; write(roura[1], &cislo, sizeof(cislo)); usleep(CEKEJ_USEC); if(QUIT){ /* Cekani na ukonceni potomku */ waitpid(S, NULL, 0); waitpid(C, NULL, 0); fprintf(stderr, "Hlavni proces %d vypina!\n", getpid()); return 0; } } }