/** * Funkcia syncProcess vytvara procesy a synchronizuje ich. * @param param Struktura s vlastnostami pre procesy. * @return Chybovy navrat funkcie. */ int syncProcess(TParams *param) { int error = EOK; // Premmena pre chybu pri zdielanej pamati. param->mainpid = getpid(); // Proces id hlavneho programu. setSignals(getpid()); // Zachytenie signalov. signal(SIGCHLD, SIG_IGN); // Ignorovanie sigchld a uvolnovanie procesov. // Inicializacia semaforov TMutx semaphores = {.mut0 = NULL, .mut1 = NULL, .mut2 = NULL ,.mut3 = NULL, .mut4 = NULL, .mut5 = NULL, .mut6 = NULL, .mut7 = NULL,}; if(initSemaphores(&semaphores) != EOK) { destroySemaphores(&semaphores); return ESEMAP; } g_mutxs = &semaphores; // Vytvorenie zdielanej pamate. TSmem *memory = createSharedMem(&error,param,"/tmp"); if(error) return ESHARED; g_mems = memory; g_shmid = param->sharedid; // Vytvorenie procesa holica. if((param->barberid = fork()) == -1) { destroySemaphores(&semaphores); unlinkSharedMem(memory,param->sharedid); return EFORK; } // Volanie holica. else if(param->barberid == 0) { syncBarber(memory, &semaphores, param); destroySemaphores(&semaphores); unlinkSharedMem(memory,param->sharedid); fclose(param->fw); exit(EXIT_SUCCESS); } // Vytvorenie procesov zakaznikov. else if(param->barberid > 0) { if(createCustomers(memory,param,&semaphores) == EFORK) { printECode(EFORK); kill(param->barberid, SIGUSR1); for(int i = 0; i < memory->created; i++) kill(memory->pids[0],SIGTERM); errorCleanAll(&semaphores,memory,param); } // Pockanie na proces barbra a uvolnenie zdielanej pamati. waitpid(param->barberid, NULL, 0); unlinkSharedMem(memory,param->sharedid); destroySemaphores(&semaphores); } return EOK; }
/** * Funkcia createCustomers vytvara zakaznikov. * @param shm Struktura zdielanej pamati. * @param param Struktura s parametrami programu. * @param smphrs Struktura so semaformi. */ int createCustomers(TSmem *shm, TParams *param, TMutx *smphrs) { pid_t pid; // PID pre zakaznika. int customerid = 0; // Poradove cislo zakaznika. signal(SIGCHLD, SIG_IGN); // Ignorovanie sigchld a uvolnovanie procesov. // Vytvorenie zakaznikov. for(unsigned long int i = 0; i < param->customers; i++) { usleep(rand()%(param->t_interval+1)*TOMSECOND); if((pid = fork()) == -1) return EFORK; // Volanie zakaznika. else if(pid == 0) { shm->pids[i] = getpid(); sem_wait(smphrs->mut7); setbuf(param->fw, NULL); fprintf(param->fw,"%d: customer %d: created\n",++(shm->action), ++(shm->created)); customerid = shm->created; sem_post(smphrs->mut7); syncCustomer(shm,smphrs,customerid,param); unlinkSharedMem(shm,param->sharedid); destroySemaphores(smphrs); fclose(param->fw); exit(EXIT_SUCCESS); } } return EOK; }
void Thread::cancel(bool wait) { waiting = wait; cancelled = true; pthread_join(threadDescriptor, NULL); pthread_detach(threadDescriptor); destroySemaphores(); }
/** * Funkcia errorCleanAll odstrani vytvorene procesy, semafory a pamat. * @param error Premenna urcujuca typ chyby. * @param smphrs Struktura pre semafory. * @param mem Zdielana struktura. * @param param Struktura s doplnkovymi parametrami. */ void errorCleanAll(TMutx *smphrs, TSmem *mem, TParams *param) { destroySemaphores(smphrs); unlinkSharedMem(mem,param->sharedid); fclose(param->fw); kill(param->mainpid, SIGTERM); exit(EXIT_FAILURE); }
/** * Funkcia killMain zasle signal sigterm hlavnemu procesu pri chybe. * @param signal Typ signalu. */ void killMain(int sig) { destroySemaphores(g_mutxs); unlinkSharedMem(g_mems,g_shmid); if(g_fr != NULL) fclose(g_fr); signal(SIGTERM,SIG_DFL); kill(sig,getpid()); exit(EXIT_FAILURE); return; }
int main(int argc, char const *argv[]) { if (argc != 2) { printf("usage: %s <data file>\n", argv[0]); exit(4); } int semaphores = getSemaphores(); semaphoreWait(semaphores, WRITER); FILE* outputFile; outputFile = fopen(argv[1], "w"); if (outputFile == 0) { printf("error: couldn't open output file"); exit(5); } StudentInfo* basePointer = getSharedMemoryPointer(); StudentInfo* currentPointer = basePointer; for (int i = 0; i < MAX_STUDENTS; ++i) { fprintf(outputFile, "%s\n", currentPointer->studentName); fprintf(outputFile, "%s\n", currentPointer->studentID); fprintf(outputFile, "%s\n", currentPointer->address); fprintf(outputFile, "%s\n", currentPointer->telephoneNumber); currentPointer++; } fclose(outputFile); detachSharedMemoryPointer(basePointer); destroySharedMemory(); destroyReadCount(); semaphoreSignal(semaphores, WRITER); destroySemaphores(semaphores); return 0; }
/** * Funkcia getParams spracuje argumenty z terminalu. * @param argc Pocet argumentov. * @param argv Argumenty. * @return Strukturu so spracovanymy vysledkami. */ TParams getParams(int argc, char *argv[]) { char *echar; // Pomocna premmenna pre chybu v strtol(). TParams param = { .error = 0, .state = 0, .filew = 0 , .chairs = 0, .t_interval = 0, .t_service = 0, .customers = 0, .fw = NULL, }; // Zistenie ci je v programu napoveda. if(argc == 2) { if(argv[1][0] == '-' && argv[1][1] == 'h') { param.state = CHELP; return param; } else param.error = ECLWRONG; } else if(argc != PRMSCOUNT) param.error = ECLWRONG; // Spracovanie parametrov, prevod retazca na cislo pomocou strtol(). if(param.error == EOK) { param.chairs = strtol(argv[1], &echar, DECIMAL); if(errno == ERANGE || *echar != '\0' || argv[1][0] == '-') param.error = ECLWRONG; param.t_interval = strtol(argv[2], &echar, DECIMAL); if(errno == ERANGE || *echar != '\0' || argv[2][0] == '-') param.error = ECLWRONG; param.t_service = strtol(argv[3], &echar, DECIMAL); if(errno == ERANGE || *echar != '\0' || argv[3][0] == '-') param.error = ECLWRONG; param.customers = strtol(argv[4], &echar, DECIMAL); if(errno == ERANGE || *echar != '\0' || argv[4][0] == '-') param.error = ECLWRONG; param.state = CFILE; // Zistenie ci je vystup do suboru. if(argv[5][0] == '-' && argv[5][1] == '\0') param.filew = CSTDOUT; else param.filew = CFILE; } return param; } /** * Funkcia killbarber ukonci barbra pri chybe. * @param sig Typ signalu. */ void killbarber(int sig) { destroySemaphores(g_mutxs); unlinkSharedMem(g_mems,g_shmid); if(g_fr != NULL) fclose(g_fr); signal(sig, SIG_DFL); exit(EXIT_FAILURE); return; }