#include "generator.h" #include #include #include #include #include int main(int argc, char *argv[]) { /* * ANALYSE DES ARGUMENTS * Détermine le rôle du programme (Client, Serveur ou Local) * pour décider s'il faut activer les fonctions réseau (sockets). */ int is_server = (argc > 1 && strcmp(argv[1], "server") == 0); int is_client = (argc > 1 && strcmp(argv[1], "client") == 0); int use_socket = (is_server || is_client); int fd = -1; int *shared_mem = MAP_FAILED; struct timeval start, end; double t_rand, t_rand48; /* * MISE EN PLACE DE LA MÉMOIRE PARTAGÉE (SHM) * 1. shm_open : crée ou ouvre un objet de mémoire partagée POSIX. * 2. ftruncate : définit la taille physique du segment. * 3. mmap : projette ce segment dans l'espace d'adressage du processus. */ printf("Initialisation Mémoire Partagée (%zu octets)...\n", SIZE); fd = shm_open(SHM_NAME, O_CREAT | O_RDWR, 0600); if (fd == -1) { perror("shm_open"); exit(1); } ftruncate(fd, SIZE); shared_mem = mmap(NULL, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (shared_mem == MAP_FAILED) { perror("mmap"); close(fd); exit(1); } /* * PHASE 1 : GÉNÉRATION MULTI-PROCESSUS (RAND_R) * Utilisation de fork() pour paralléliser la génération. * Chaque fils travaille sur une portion spécifique de la mémoire partagée. */ printf("\n PHASE 1 : Génération avec rand_r() [%d processus]...\n", NB_PROCESSUS); gettimeofday(&start, NULL); for (int i = 0; i < NB_PROCESSUS; i++) { if (fork() == 0) { size_t s = (size_t)i * NB_ALEATOIRES_PAR_PROC; size_t c = (i == NB_PROCESSUS - 1) ? (NB_ALEATOIRES_TOTAL - s) : NB_ALEATOIRES_PAR_PROC; generate_numbers(shared_mem, s, c, 0); exit(0); } } /* Synchronisation : le père attend la fin de tous ses processus fils */ for (int i = 0; i < NB_PROCESSUS; i++) wait(NULL); gettimeofday(&end, NULL); t_rand = get_elapsed_time(start, end); /* Analyse statistique et export des données de la phase 1 */ Stats res_rand = analyze_data(shared_mem, NB_ALEATOIRES_TOTAL, "RAND_R", t_rand); printf("Sauvegarde CSV (Rand)... "); write_to_csv("rand.csv", shared_mem, NB_ALEATOIRES_TOTAL); printf("\nTerminé.\n"); /* * PHASE 2 : GÉNÉRATION MULTI-PROCESSUS (DRAND48_R) * Même logique de parallélisme, mais utilise l'algorithme 48-bit * pour comparer les performances et la qualité statistique. */ printf("\n PHASE 2 : Génération avec drand48_r() [%d processus]...\n", NB_PROCESSUS); gettimeofday(&start, NULL); for (int i = 0; i < NB_PROCESSUS; i++) { if (fork() == 0) { size_t s = (size_t)i * NB_ALEATOIRES_PAR_PROC; size_t c = (i == NB_PROCESSUS - 1) ? (NB_ALEATOIRES_TOTAL - s) : NB_ALEATOIRES_PAR_PROC; generate_numbers(shared_mem, s, c, 1); exit(0); } } for (int i = 0; i < NB_PROCESSUS; i++) wait(NULL); gettimeofday(&end, NULL); t_rand48 = get_elapsed_time(start, end); /* Analyse statistique et export des données de la phase 2 */ Stats res_rand48 = analyze_data(shared_mem, NB_ALEATOIRES_TOTAL, "DRAND48_R", t_rand48); printf("Sauvegarde CSV (Drand48)... "); write_to_csv("rand48.csv", shared_mem, NB_ALEATOIRES_TOTAL); printf("\nTerminé.\n"); /* * COMMUNICATION RÉSEAU * Si le mode socket est activé, transmet les résultats (Stats) * au partenaire distant (Serveur <-> Client). */ if (use_socket) { printf("\n Établissement de la connexion socket...\n"); communicate_with_socket(is_server, res_rand.time, res_rand48.time, res_rand.std_dev, res_rand48.std_dev, res_rand.throughput, res_rand48.throughput, res_rand.max_occ, res_rand.min_occ); } /* * NETTOYAGE DES RESSOURCES * Libère la projection mémoire et ferme le descripteur. */ if (shared_mem != MAP_FAILED) munmap(shared_mem, SIZE); if (fd != -1) close(fd); /* * Seul le serveur ou le mode local supprime définitivement * le segment shm de la RAM pour éviter les fuites de ressources. */ if (is_server || !use_socket) { shm_unlink(SHM_NAME); printf("\n Segment mémoire partagée supprimé du système.\n"); } printf(" Fin du programme. Fichiers CSV conservés.\n"); return 0; }