#define MSG_MODE 1 #include #include #include #include #include #include #include #include #include #include VER_INFO_EXPORT (pingpong, "1.0", "", __FILE__, "severin") #define DEFAULT_TIMER 60 /* Durée par défaut du test (en secondes) */ #define DEFAULT_WINSIZE 100 /* Taille par défaut de la fenêtre de messages */ #define DEFAULT_MSGSIZE 100 /* Taille par défaut de chaque message */ #define FATHER_KEY "father_port" /* Clé du port de messages d'écoute du père */ #define CHILD_KEY "child_port" /* Clé du port de messages d'écoute du fils */ #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif /*----------------------------------------------------------------*/ MSGT_Port * My_Port, * Its_Port; unsigned int Child_Pid, Father_Pid, Its_Pid, My_Pid; int Verbose, Tree; unsigned int Win_Size, Msg_Size, Cpt_Msg, Timer; SMT_DSH * DSH; SMT_Heap * Heap; int End_Test, End_Sigum; char str [100]; void stop_test (int); void stop_father (void); void stop_child (void); void clean (int); void trace (char *); void print_result (void); void parse_arg (int, char **); extern char * strdup (const char *); extern kill (int, int); /*----------------------------------------------------------------*/ int main (int argc, char ** argv) { unsigned int i; MSGT_Message * Msg; /* Récupération des arguments de la ligne de commande */ parse_arg (argc, argv); /* Récupération du numéro de processus courant */ Father_Pid = getpid (); /* Création d'un process fils avec qui dialoguer */ if ((Child_Pid = fork ()) != 0) { Heap = NULL; /*--------- Code pour le process père -----------*/ /* Ouverture de la librairie libmsg */ if (MSG_Library_Open (0, NULL, MSGD_OPEN | MSGD_DEBUG_ALL) != MSGS_OK) return 0; Its_Pid = Child_Pid; My_Pid = Father_Pid; signal (SIGINT, stop_test); signal (SIGUSR1, stop_test); /* Création d'un port de messages privé pour le père */ if (MSG_Port_Open (FATHER_KEY, &My_Port, MSGD_CREATE) != MSGS_OK) { fprintf (stderr, "Unable to create a message port for the father process\n"); clean (TRUE); return 0; } else if (Verbose) { sprintf (str, "Message port \"%s\" created", My_Port->Name); trace (str); } if (Tree == TRUE) { if (MSG_Port_Config (My_Port, MSGD_CONFIG_MSGQUEUE, NDD_DS_TREE) != MSGS_OK) { fprintf (stderr, "Unable to create a message port for the father process\n"); clean (TRUE); return 0; } } /* On attend que le fils ait créé son port de messages */ sleep (1); /* Récupération du port de messages privé du fils */ if (MSG_Port_Open (CHILD_KEY, &Its_Port, MSGD_OPEN) != MSGS_OK) { fprintf (stderr, "Unable to retrieve the message port of the child process\n"); clean (TRUE); return 0; } else if (Verbose) { sprintf (str, "Message port \"%s\" retrieved", Its_Port->Name); trace (str); } /* Initialisation du Timer */ signal (SIGALRM, stop_test); alarm (Timer); /* Début du test : traitement des messages */ fprintf (stdout, "Testing LIBMSG for %d second(s) with %d message(s) of %d byte(s)...\n", Timer, Win_Size, Msg_Size); /* Création et envoi de tous les messages au fils */ for (i = 0; i < Win_Size; i++) { if (MSG_Message_Alloc (&Msg, Msg_Size) == MSGS_OK) { if (Verbose) { sprintf (str, "Message %d created", i); trace (str); } if (MSG_Message_Send (My_Port->Name, Its_Port, Msg) == MSGS_OK) { if (Verbose) { sprintf (str, "Message %d sent to port \"%s\"", i, Its_Port->Name); trace (str); } } } } Cpt_Msg = 0; while (End_Test == FALSE) { /* Réception de messages */ if (MSG_Message_Receive (My_Port, MSGD_NO_TYPE, &Msg, MSGD_WAIT) == MSGS_OK) { if (Verbose) { sprintf (str, "Message %d received from port \"%s\"", Msg->Type, My_Port->Name); trace (str); } Cpt_Msg++; /* Réenvoi du message au fils */ if (MSG_Message_Reply (Msg) == MSGS_OK) { if (Verbose) { sprintf (str, "Message %d replied", Msg->Type); trace (str); } } } } stop_father (); } else { /*---------- Code pour le process fils ----------*/ Heap = NULL; My_Pid = getpid (); Its_Pid = Father_Pid; /* Ouverture de la librairie libmsg */ if (MSG_Library_Open (0, NULL, SMD_OPEN | MSGD_DEBUG_ALL) != MSGS_OK) return 0; /* Trap du signal SIGUSR1 envoyé par le process père à la fin du test */ signal (SIGUSR1, stop_test); signal (SIGINT, stop_test); /* Création d'un port de messages privé pour le fils */ if (MSG_Port_Open (CHILD_KEY, &My_Port, MSGD_CREATE) != MSGS_OK) { fprintf (stderr, "Unable to create message port for the child process\n"); clean (TRUE); return 0; } else if (Verbose) { sprintf (str, "Message port \"%s\" created", My_Port->Name); trace (str); } /* On attend que le père ait créé son port de messages privé */ sleep (1); /* Récupération du port de messages privé du père */ if (MSG_Port_Open (FATHER_KEY, &Its_Port, MSGD_OPEN) != MSGS_OK) { fprintf (stderr, "Unable to retrieve the message port of the father process\n"); clean (TRUE); return 0; } else if (Verbose) { sprintf (str, "Message port \"%s\" retrieved", Its_Port->Name); trace (str); } /* Traitement des messages */ while (End_Test == FALSE) { /* Réception de messages */ if (MSG_Message_Receive (My_Port, MSGD_NO_TYPE, &Msg, MSGD_WAIT) == MSGS_OK) { if (Verbose) { sprintf (str, "Message %d received from port \"%s\"", Msg->Type, My_Port->Name); trace (str); } /* Renvoi du message */ if (MSG_Message_Reply (Msg) == MSGS_OK) { if (Verbose) { sprintf (str, "Message %d replied", Msg->Type); trace (str); } } } } stop_child (); } return 0; } /*----------------------------------------------------------------*/ void stop_test (int signum) { End_Sigum = signum; End_Test = TRUE; } /*----------------------------------------------------------------*/ void stop_father (void) { switch (End_Sigum) { case SIGINT: /* Fin initiée par l'utilisateur : ménage simple */ case SIGUSR1: /* Fin anormale en provenance du fils : ménage simple */ sprintf (str, "Signal USR1 received from child process"); trace (str); clean (FALSE); break; case SIGALRM: /* Fin normale : ménage + stop du fils + affichage du réultat */ clean (TRUE); print_result (); break; default: /* Fin anormale sur le process père : ménage + avertit le process fils */ clean (TRUE); break; } exit (1); } /*----------------------------------------------------------------*/ void print_result (void) { /* Affichage du résultat du test */ fprintf (stdout, "%d message(s) exchanged (%d msg/sec)\n", Cpt_Msg, (int)(Cpt_Msg / Timer)); } /*----------------------------------------------------------------*/ void stop_child (void) { switch (End_Sigum) { case SIGINT: /* Fin initiée par l'utilisateur : ménage simple */ case SIGUSR1: /* Fin initiée par le process père : ménage simple */ sprintf (str, "Signal USR1 received from father process"); trace (str); clean (FALSE); break; default: /* Fin anormale sur le process fils : ménage + avertit le process père */ clean (TRUE); break; } exit (0); } /*----------------------------------------------------------------*/ void clean (int warn) { /* On avertit l'autre process */ if (warn == TRUE) kill (Its_Pid, SIGUSR1); /* Fermeture du port de l'autre process */ if (Its_Port != NULL) { char Port_Name [256]; strcpy (Port_Name, Its_Port->Name); MSG_Port_Close (Its_Port, MSGD_CLOSE); if (Verbose) { sprintf (str, "Message port \"%s\" closed", Port_Name); trace (str); } } /* Destruction du port de messages privé */ if (My_Port != NULL) { char Port_Name [256]; strcpy (Port_Name, My_Port->Name); /* On attend un peu afin que l'autre process puisse fermer mon port de messages */ sleep (1); MSG_Port_Close (My_Port, MSGD_DESTROY); if (Verbose) { sprintf (str, "Message port \"%s\" removed", Port_Name); trace (str); } } MSG_Library_Close (MSGD_CLOSE); } /*----------------------------------------------------------------*/ void trace (char * s) { time_t dts; struct tm * dt; char Current_Date [25]; char strace [100]; /* Get current date */ time (&dts); dt = localtime (&dts); sprintf (Current_Date, "%04d/%02d/%02d %02d:%02d:%02d", dt->tm_year + 1900, dt->tm_mon + 1, dt->tm_mday, dt->tm_hour, dt->tm_min, dt->tm_sec); sprintf (strace, "Process %d - %s : %s\n", My_Pid, Current_Date, s); fprintf (stderr, strace); fflush (stderr); } /*----------------------------------------------------------------*/ void parse_arg (int argc, char **argv) { int i; Verbose = Tree = FALSE; for (i = 1; i < argc; i++) { if (!strcmp (argv[i], "--help") || !strcmp (argv[i], "-h")) { fprintf (stdout, "Usage : %s [options]\n", argv[0]); fprintf (stdout,"options :\n"); fprintf (stdout, "\t --help | -h\n"); fprintf (stdout, "\t --clean\n"); fprintf (stdout, "\t --verbose\n"); fprintf (stdout, "\t --duration