main.c 4,55 ko
Newer Older
#include "generator.h"
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <string.h>

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;
}