/* * File: shm.c * Author: Arthur Brandao * * Created on 21 décembre 2018 */ #include #include #include /* Constante option */ #include #include "error.h" #include "shm.h" /* --- Extern --- */ extern int errno; /* --- Fonctions prviées --- */ /** * Indique si il reste des processus utilsant le segment * @param shared_mem* La mémoire partagée * @return Peut ont supprimer ou non */ boolean can_delete_shm(shared_mem* shm){ struct shmid_ds buf; /* Recup les infos de la mémoire */ if (shmctl(shm->id, IPC_STAT, &buf) == ERR) { addperror("Impossible de récupérer les données du segment"); return false; } /* Verifie qu'il n'y a plus d'utilisateur actif */ return buf.shm_nattch == 0; } /* --- Fonctions publiques --- */ boolean create_shm(shared_mem* shm, int code, int size) { int id; void* adr; /* Création de la shm */ key_t key = ftok(IPCKEYPATH, code); if (key == ERR) { addperror("Impossible de générer la clef"); return false; } id = shmget(key, size, S_IRUSR | S_IWUSR | IPC_CREAT | IPC_EXCL); if (id == ERR) { /* Si erreur existe deja appel get_shm */ if (errno == EEXIST) { adderror("Le segment existe deja, tentative de récupération"); return get_shm(shm, code, size); } else { addperror("Impossible de créer la mémoire partagée"); return false; } } /* On attache */ adr = shmat(id, NULL, 0); if (adr == (void*) ERR) { addperror("Impossible d'attacher le segment"); return false; } /* Initialisation de la structure */ shm->id = id; shm->key = key; shm->size = size; shm->adr = adr; return true; } boolean get_shm(shared_mem* shm, int code, int size) { int id; void* adr; /* Création de la shm */ key_t key = ftok(IPCKEYPATH, code); if (key == ERR) { addperror("Impossible de générer la clef"); return false; } id = shmget(key, size, S_IRUSR | S_IWUSR); if (id == ERR) { addperror("Impossible de récupérer la mémoire partagée"); return false; } /* On attache */ adr = shmat(id, NULL, 0); if (adr == (void*) ERR) { addperror("Impossible d'attacher le segment"); return false; } /* Initialisation de la structure */ shm->id = id; shm->key = key; shm->size = size; shm->adr = adr; return true; } boolean unset_shm(shared_mem* shm){ /* On détache la shm */ if(shmdt(shm->adr) == ERR){ perror("Erreur lors du détachement de la mémoire "); return false; } shm->adr = NULL; shm->size = 0; /* Retour */ return true; } boolean delete_shm(shared_mem* shm) { /* Regarde si on peut supprimer */ if(!can_delete_shm(shm)){ adderror("Des processus utilisent encore le segment"); return false; } /* Supprime */ if (shmctl(shm->id, IPC_RMID, 0) == ERR) { addperror("Impossible de supprimer le segment"); return false; } /* Reset la structure */ shm->id = 0; shm->key = 0; return true; }