Première version

This commit is contained in:
smas 2000-07-28 15:34:22 +00:00
commit 961ddc46da
14 changed files with 6065 additions and 0 deletions

618
lib/libmsg.3 Normal file
View File

@ -0,0 +1,618 @@
'\" t
.\" @(#)LIBMSG.3 1.0 00/07/04 SMA;
.TH LIBMSG 3 "07 Apr 2000"
.SH NOM
LIBMSG (librairie de communication inter-processus par messages)
.SH SYNOPSIS
.LP
.BI "cc [flag ...] file ... -lver -ldl -lnode -lshmem -ldatastr -lmsg [library ...]"
.LP
.BI "#include <msg.h>"
.LP
.BI "MSGT_Status MSG_Library_Open ( int " Instance ", const char * " Context ", MSGT_Flags " Open_Mode " );"
.LP
.BI "MSGT_Status MSG_Library_IsOpen ( void );"
.LP
.BI "MSGT_Status MSG_Library_Signal ( void );"
.LP
.BI "MSGT_Status MSG_Library_Close ( MSGT_Flags " Close_Mode " );"
.LP
.BI "MSGT_Status MSG_Library_Stderr_Set ( FILE * " Out " );"
.LP
.BI "MSGT_Status MSG_Library_Dump ( FILE * " Out " );"
.LP
.BI "MSGT_Status MSG_Port_Open ( int " Id ", MSGT_Port ** " Port ", MSGT_Flags " Open_Mode " );"
.LP
.BI "MSGT_Status MSG_Port_Lock ( MSGT_Port * " Port ", MSGT_Flags " Mode " );"
.LP
.BI "MSGT_Status MSG_Port_Unlock ( MSGT_Port * " Port ", MSGT_Flags " Mode " );"
.LP
.BI "MSGT_Status MSG_Port_Config ( MSGT_Port * " Port ", MSGT_Config " Tag ", " ... " );"
.LP
.BI "MSGT_Status MSG_Port_Close ( MSGT_Port * " Port ", MSGT_Flags " Close_Mode " );"
.LP
.BI "MSGT_Status MSG_PortList_Open ( MSGT_PortList ** " PortList " );"
.LP
.BI "MSGT_Status MSG_PortList_Port_Add ( MSGT_PortList * " PortList ", MSGT_Port * " Port " );"
.LP
.BI "MSGT_Status MSG_PortList_Port_Remove ( MSGT_PortList * " PortList ", MSGT_Port * " Port " );"
.LP
.BI "MSGT_Status MSG_PortList_Close ( MSGT_PortList * " PortList " );"
.LP
.BI "MSGT_Status MSG_PortList_Listen ( MSGT_PortList * " PortList ", unsigned int " Type ", MSGT_Message ** " Msg ", MSGT_Flags " Flags " );"
.LP
.BI "MSGT_Status MSG_Message_Alloc ( MSGT_Message ** " Msg ", size_t " Size " );"
.LP
.BI "MSGT_Status MSG_Message_Config ( MSGT_Message * " Msg ", MSGT_Config " Tag ", " ... " );"
.LP
.BI "MSGT_Status MSG_Message_Free ( MSGT_Message * " Msg " );"
.LP
.BI "MSGT_Status MSG_Message_Send ( MSGT_Port * " From ", , MSGT_Port * " To ", MSGT_Message * " Msg " );"
.LP
.BI "MSGT_Status MSG_Message_Receive ( MSGT_Port * " Port ", unsigned int " Type ", MSGT_Message ** " Msg ", MSGT_Flags " Flags " );"
.LP
.BI "MSGT_Status MSG_Message_Reply ( MSGT_Message * " Msg " );"
.LP
.BI "MSGT_Status MSG_Message_Return ( MSGT_Message * " Msg " );"
.LP
.SH "CODES RETOUR"
.LP
Toutes les fonctions constituant l'API de la librairie LIBMSG retournent un code de type
.B MSGT_Status
:
.LP
.RS 3
-
.B MSGS_OK
: la fonction s'est correctement executee et a produit un resultat
.LP
-
.B MSGS_KO
: la fonction s'est correctement executee mais n'a pas produit de resultat
.LP
-
.B MSGS_ERRAPI
: la fonction a ete appelee avec des arguments de valeur incorrecte
.LP
-
.B MSGS_ERRMEM
: la fonction ne s'est pas correctement executee pour un probleme d'allocation memoire
.LP
-
.B MSGS_ERRSHM
: la fonction ne s'est pas correctement executee pour un probleme relatif a la memoire partagee
.LP
-
.B MSGS_ERRSEM
: la fonction ne s'est pas correctement executee pour un probleme relatif a l'utilisation des semaphores
.LP
-
.B MSGS_ERRSIG
: une operation sur semaphore a ete interrompue par un signal
.LP
-
.B MSGS_ERRNOWAIT
: une operation sur semaphore n'a pas pu etre realisee et le mode d'operation est sans attente
.LP
-
.B DSS_ERRDLL
: la fonction ne s'est pas correctement executee pour un probleme de chargement dynamique d'objet
.LP
.RS -3
.I NB
: la macro
.B MSG_ERROR()
permet de tester si un code retour correspond a une erreur.
.LP
En cas d'erreur, la variable MSG_Error_Message contient un message du type :
.LP
.RS 3
Error <Nom fonction> : <message d'erreur>
.RS -3
.LP
Pour les fonctions de reception de messages, 3 codes retour supplementaires ont ete definis :
.LP
.RS 3
-
.B MSGS_NO_MSG
si aucun message n'a ete trouve dans le(s) port(s) de messages ecoute(s)
.LP
-
.B MSGS_BAD_TYPE
si des messages sont presents mais qu'aucun ne correspond au type de message demande.
.LP
-
.B MSGS_SIGNAL
si l'ecoute du port a ete interrompue par un signal systeme.
.RS -3
.LP
.SH "FONCTIONS"
.LP
.BI "MSGT_Status MSG_Library_Open ( int " Instance ", const char * " Context ", MSGT_Flags " Open_Mode " );"
.RS 3
.LP
La librairie LIBMSG implemente une base qui reference tous les ports de messages et tous les messages crees.
.LP
Cette fonction permet donc d'acceder a toutes ces ressources pour un contexte et une instance donnes designes par leur nom
.I Context
et
.I Instance
:
.LP
.RS 3
- en ouverture simple si
.I Open_Mode
vaut
.B MSGD_OPEN
.LP
- en creation si
.I Open_Mode
vaut
.B MSGD_CREATE
.RS -3
.LP
.I NB
: l'indicateur d'ouverture
.I Open_Mode
pourra etre combinee avec un mode de debugging (
.B MSGD_DEBUG_NONE
: aucun message d'erreur n'est affiche
.LP
.B MSGD_DEBUG
: les messages d'erreur generes par la librairie LIBMSG sont affiches sur la sortie standard d'erreur
.LP
.B MSGD_DEBUG_ALL
: les messages d'erreur generes par toutes les librairies sous-jacentes a la LIBMSG sont affiches sur la sortie standard d'erreur
.LP
.I NB
: l'ouverture de la librairie en creation est reservee aux administrateurs.
.LP
L'ouverture de la librairie est obligatoire avant d'utiliser toute autre fonction de la librairie LIBMSG.
.LP
.RS -3
.LP
.BI "MSGT_Status MSG_Library_Signal ( void );"
.RS 3
.LP
Cette fonction permet d'informer la librairie LIBMSG de la reception d'un signal systeme.
.LP
.I NB
: cette fonction sera utile a l'utilisateur pour eviter que le processus reste bloque sur une attente de message malgre la reception de signal.
.RS -3
.LP
.BI "MSGT_Status MSG_Library_IsOpen ( void );"
.RS 3
.LP
Cette fonction permet de tester si une instance de la librairie LIBMSG a deja ete ouverte.
.RS -3
.LP
.BI "MSGT_Status MSG_Library_Close ( MSGT_Flags " Close_Mode " );"
.RS 3
.LP
Cette fonction permet de fermer toutes les ressources de l'instance de la librairie ouverte :
.LP
.RS 3
- fermeture simple si
.I Close_Mode
vaut
.B MSGD_CLOSE
.LP
- destruction si
.I Close_Mode
vaut
.B MSGD_DESTROY
.RS -3
.LP
.I NB
: l'utilisation du parametre
.B MSGD_DESTROY
est reservee aux administrateurs.
.LP
.RS -3
.BI "MSGT_Status MSG_Library_Dump ( FILE * " Out " );"
.RS 3
.LP
Cette fonction permet d'afficher toutes les ressources de l'instance de la librairie ouverte.
.LP
L'argument
.I Out
designe le flux de sortie de l'affichage.
.LP
.RS -3
.BI "MSGT_Status MSG_Port_Open ( int " Id ", MSGT_Port ** " Port ", MSGT_Flags " Open_Mode " );"
.LP
.RS 3
Cette fonction permet d'ouvrir un port de messages.
.LP
Elle requiert les arguments suivants :
.RS 3
.LP
* (In)
.I Id
: l'identifiant numerique du port de messages
.LP
* (Out)
.I Port
: l'adresse d'un pointeur sur le port de messages
.LP
* (In)
.I Open_Mode
: le mode d'ouverture du port de messages
.LP
.RS 3
- en ouverture simple si
.I Open_Mode
vaut
.B MSGD_OPEN
.LP
- en creation si
.I Open_Mode
vaut
.B MSGD_CREATE
.RS -3
.RS -3
.LP
.RS -3
.BI "MSGT_Status MSG_Port_Lock ( MSGT_Port * " Port ", MSGT_Flags " Mode " );"
.RS 3
.LP
Cette fonction permet de verrouiller un port de messages.
.LP
Elle requiert les arguments suivants :
.LP
.RS 3
* (In)
.I Port
: un pointeur sur le port de messages a verrouiller
.LP
* (In)
.I Mode
: le mode de verrouillage (
.B MSGD_READ
ou
.B MSGD_WRITE
)
.LP
.RS -3
.LP
.RS -3
.BI "MSGT_Status MSG_Port_Unlock ( MSGT_Port * " Port ", MSGT_Flags " Mode " );"
.RS 3
.LP
Cette fonction permet d'oter le verrou pose sur un port de messages.
.LP
Elle requiert les arguments suivants :
.LP
.RS 3
* (In)
.I Port
: un pointeur sur le port de messages a deverrouiller
.LP
* (In)
.I Mode
: le mode dans lequel le port est verrouille (
.B MSGD_READ
ou
.B MSGD_WRITE
)
.LP
.RS -3
.LP
.RS -3
.BI "MSGT_Status MSG_Port_Config ( MSGT_Port * " Port ", MSGT_Config " Tag ", " ... " );"
.RS 3
.LP
Cette fonction permet de configurer un port de messages.
.LP
Elle requiert les arguments suivants :
.LP
.RS 3
* (In)
.I Port
: un pointeur sur le port de messages a configurer
.LP
* (In)
.I Tag
: le type de configuration (
.B MSGD_CONFIG_SIZE
)
.LP
* (In)
.I ...
: la ou les valeurs utiles (fonction du type de configuration)
.LP
.RS -3
.LP
.RS -3
.BI "MSGT_Status MSG_Port_Close ( MSGT_Port * " Port ", MSGT_Flags " Close_Mode " );"
.RS 3
.LP
Cette fonction permet de fermer un port de messages.
.LP
Elle requiert les arguments suivants :
.RS 3
.LP
* (In)
.I Port
: un pointeur sur le port de messages a fermer
.LP
* (In)
.I Close_Mode
: le mode de fermeture du port de messages
.LP
.RS 3
- fermeture simple si
.I Close_Mode
vaut
.B MSGD_CLOSE
.LP
- destruction si
.I Close_Mode
vaut
.B MSGD_DESTROY
.RS -3
.RS -3
.LP
.RS -3
.BI "MSGT_Status MSG_PortList_Open ( MSGT_PortList ** " PortList " );"
.RS 3
.LP
Cette fonction permet d'ouvrir une liste de ports de messages.
.LP
L'argument
.I PortList
est l'adresse d'un pointeur sur la liste de port a creer.
.LP
.I NB
: une liste de ports permet a un processus d'ecouter plusieurs ports de messages simultanement.
Une liste de ports n'est pas partageable entre les processus.
.LP
.RS -3
.BI "MSGT_Status MSG_PortList_Port_Add ( MSGT_PortList * " PortList ", MSGT_Port * " Port " );"
.RS 3
.LP
Cette fonction permet d'ajouter un port de messages a une liste de ports.
.LP
Elle requiert les arguments suivants :
.LP
.RS 3
* (In)
.I PortList
: un pointeur sur une liste de ports
.LP
* (In)
.I Port
: un pointeur sur le port de messages a ajouter
.LP
.RS -3
.LP
.RS -3
.BI "MSGT_Status MSG_PortList_Port_Remove ( MSGT_PortList * " PortList ", MSGT_Port * " Port " );"
.RS 3
.LP
Cette fonction permet de retirer un port de messages d'une liste de ports.
.LP
Elle requiert les arguments suivants :
.LP
.RS 3
* (In)
.I PortList
: un pointeur sur une liste de ports
.LP
* (In)
.I Port
: un pointeur sur le port de messages a retirer
.LP
.RS -3
.LP
.RS -3
.BI "MSGT_Status MSG_PortList_Close ( MSGT_PortList * " PortList " );"
.RS 3
.LP
Cette fonction permet de detruire une liste de ports de messages.
.LP
L'argument
.I PortList
est un pointeur sur la liste de port a supprimer.
.LP
.I NB
: lorsqu'un processus ajoute un port de messages a sa liste de ports, le port de messages memorise le fait que le processus doit etre averti si un message y est ajoute ou retire.
Il est donc important que chaque processus detruise explicitement toutes les listes de ports qu'il a creees lorsque celles-ci ne sont plus utilisees.
.LP
.RS -3
.BI "MSGT_Status MSG_PortList_Listen ( MSGT_PortList * " PortList ", unsigned int " Type ", MSGT_Message ** " Msg ", MSGT_Flags " Flags " );"
.RS 3
.LP
Cette fonction permet de receptionner un message a partir d'une liste de ports.
La notion d'ecoute correspond au fait qu'un processus pourra se mettre en attente jusqu'a ce qu'un message soit envoye sur l'un des ports.
.LP
Elle requiert les arguments suivants :
.LP
.RS 3
* (In)
.I Port
: un pointeur sur la liste de ports
.LP
* (In)
.I Type
: le type du message a receptionner (la valeur
.B MSGD_NO_TYPE
permet de ne specifier aucun type en particulier)
.LP
* (Out)
.I Msg
: l'adresse d'un pointeur sur le message a receptionner.
.LP
* (In)
.I Flags
: le type d'ecoute (avec attente :
.B MSGD_WAIT
, sans attente :
.B MSGD_NOWAIT
)
.LP
.RS -3
.I NB
: pour une ecoute avec attente, un processus sera reveille a chaque fois qu'un message arrive dans l'un des ports de la liste. Il pourra toutefois se remettre en attente si le message a ete receptionne par un autre processus ou bien si son type n'est pas celui demande.
.LP
.I NB
: la recherche des messages dans les differents ports de la liste s'effectue dans l'ordre dans lequel ils ont ete ajoute a la liste.
.LP
.RS -3
.BI "MSGT_Status MSG_Message_Alloc ( MSGT_Message ** " Msg ", size_t " Size " );"
.RS 3
.LP
Cette fonction permet de creer un message et d'allouer de la memoire pour les donnees associees au message.
.LP
Elle requiert les arguments suivants :
.LP
.RS 3
* (Out)
.I Msg
: l'adresse d'un pointeur sur le message a creer
.LP
* (In)
.I Size
: la taille des donnees du message
.RS -3
.LP
.I NB
: l'utilisateur pourra modifier a sa guise la zone de donnees du message pointee par le champ
.B Data
du message.
Il veillera toutefois a ne pas deborder en dehors de cette zone auquel cas le fonctionnement de la librairie pourrait etre corrompue.
.LP
.RS -3
.BI "MSGT_Status MSG_Message_Config ( MSGT_Message * " Msg ", MSGT_Config " Tag ", " ... " );"
.RS 3
.LP
Cette fonction permet de configurer un message.
.LP
Elle requiert les arguments suivants :
.LP
.RS 3
* (In)
.I Msg
: un pointeur sur le message a configurer
.LP
* (In)
.I Tag
: le type de configuration (
.B MSGD_CONFIG_TYPE
,
.B MSGD_CONFIG_PRIORITY
)
.LP
* (In)
.I ...
: la ou les valeurs utiles (fonction du type de configuration)
.RS -3
.LP
.RS -3
.BI "MSGT_Status MSG_Message_Free ( MSGT_Message * " Msg " );"
.RS 3
.LP
Cette fonction permet de supprimer un message de la base de la librairie LIBMSG.
.LP
L'argument
.I Msg
est un pointeur sur le message a supprimer.
.LP
.I NB
: l'utilisateur veillera a ne pas supprimer les messages de maniere inconsideree, ceux-ci pouvant etre en cours d'envoi dans un port de messages.
.LP
Les regles d'usage veulent que ce soit le processus initiateur d'un message qui le supprime.
Dans le cas ou les messages ne sont pas renvoyes au processus initiateur, c'est le processus qui receptionne le message qui le supprimera.
.LP
.RS -3
.BI "MSGT_Status MSG_Message_Send ( MSGT_Port * " From ", , MSGT_Port * " To ", MSGT_Message * " Msg " );"
.RS 3
.LP
Cette fonction permet d'envoyer un message dans un port de messages.
.LP
Elle requiert les arguments suivants :
.LP
.RS 3
* (In)
.I From
: un pointeur sur le port de l'emetteur du message
.LP
* (In)
.I To
: un pointeur sur le port destinataire du message
.LP
* (In)
.I Msg
: un pointeur sur le message a envoyer
.LP
.RS -3
.I NB
: un message ne pourra pas etre envoye simultanement dans plusieurs ports de messages.
.LP
.RS -3
.BI "MSGT_Status MSG_Message_Receive ( MSGT_Port * " Port ", unsigned int " Type ", MSGT_Message ** " Msg ", MSGT_Flags " Flags " );"
.RS 3
.LP
Cette fonction permet de receptionner un message dans un port de messages.
.LP
Elle requiert les arguments suivants :
.LP
.RS 3
* (In)
.I Port
: un pointeur sur le port de messages a ecouter
.LP
* (In)
.I Type
: le type du message a receptionner (la valeur
.B MSGD_NO_TYPE
permet de ne specifier aucun type en particulier)
.LP
* (Out)
.I Msg
: l'adresse d'un pointeur sur le message a receptionner.
.LP
* (In)
.I Flags
: le type d'ecoute (avec attente :
.B MSGD_WAIT
, sans attente :
.B MSGD_NOWAIT
)
.LP
.RS -3
.I NB
: la reception d'un message ne fait que retirer celui-ci du port de messages.
Le message n'est donc pas supprime et pourra en consequence etre envoye a nouveau dans une autre port de messages.
.LP
Pour une reception avec attente, un processus sera reveille a chaque fois qu'un message arrive dans le port de la liste.
.LP
Independamment du type demande, les messages sont receptionnes selon leur priorite puis selon leur ordre d'envoi.
.LP
.RS -3
.BI "MSGT_Status MSG_Message_Reply ( MSGT_Message * " Msg " );"
.RS 3
.LP
Cette fonction permet de renvoyer un message a son envoyeur.
.LP
.I NB
: l'envoyeur devra alors avoir precise l'identifiant de son port d'ecoute dans le champ
.B From
du message
.I Msg
.
.LP
.RS -3
.BI "MSGT_Status MSG_Message_Return ( MSGT_Message * " Msg " );"
.RS 3
.LP
Cette fonction permet de renvoyer un message au processus initiateur du message (different de l'envoyeur si le message passe entre plusieurs mains.
.LP
.I NB
: l'initiateur du message devra alors avoir precise l'identifiant de son port d'ecoute dans le champ
.B Init
du message
.I Msg
.
.LP
.RS -3

3181
lib/libmsg.c Normal file

File diff suppressed because it is too large Load Diff

BIN
lib/libmsg.doc Normal file

Binary file not shown.

118
lib/libmsg.h Normal file
View File

@ -0,0 +1,118 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <ver.h>
#include <node.h>
#include <datastr.h>
#include <msg.h>
extern char * strdup (const char *);
int MSG_Signal_Received;
/* Tous les heaps créés via la librairie LIBMSG seront préfixés par le nom suivant */
#define MSG_PREFIX "MSG"
/* Nom du fichier à charger pour accéder aux fonctions manager d'une data structure créée par la LIBMSG */
#define MSG_FILE_MANAGER "libmsg.so"
/*
Heap dans lequel sera stockée la base de la librairie LIBMSG :
Ce heap ne contient que la structure MSGT_Base qui permet de référencer
la liste des ports de messages.
Ce heap ne sera constitué que d'une unique segment très petit.
*/
#define MSG_BASE_HEAP_NAME "BASE"
#define MSG_BASE_HEAP_SEGMENT_SIZE 100
/*
Heap dans lequel sera stockée la liste des ports de messages :
Ce heap ne contient que la structure MSGT_Base qui permet de référencer
la liste des ports de messages.
Ce heap n'a pas besoin besoin d'être très grand.
*/
#define MSG_PORT_LIST_NAME "PORT_REF"
#define MSG_PORT_LIST_SEGMENT_SIZE 10240
/*
Heap sous-jacent à un port de messages :
Un port de messages est une data structure qui ne contient que sa racine, les
noeuds étant stockés par ailleurs. On peut donc se contenter d'un petit segment.
*/
#define MSG_PORT_SEGMENT_SIZE 1024
/*
Heap dans lequel seront alloués les messages :
Ce heap étant amené à grandir rapidemment, il vaut mieux choisir
une taille importante par segment afin de limiter le nombre de segments.
*/
#define MSG_MESSAGE_HEAP_NAME "MSG_REF"
#define MSG_MESSAGE_HEAP_SEGMENT_SIZE 1024000
/* Utilisation des sémaphores pour l'écoute des ports de messages ou des liste de ports */
struct sembuf MSG_SemOp_Listen [2] = { {0, -1, 0}, {0, 1, 0} }; /* Opération d'écoute */
struct sembuf MSG_SemOp_Receive [1] = { {0, -1, IPC_NOWAIT} }; /* Opération de retrait de message */
struct sembuf MSG_SemOp_Add [1] = { {0, 1, IPC_NOWAIT} }; /* Opération d'ajout de message */
/* Utilisation des sémaphores pour verrouiller les ports de messages */
struct sembuf MSG_SemOp_SSL [2] = { {0, -1, SEM_UNDO}, {0, 2, SEM_UNDO} };
struct sembuf MSG_SemOp_RSL [2] = { {0, -2, SEM_UNDO|IPC_NOWAIT}, {0, 1, SEM_UNDO|IPC_NOWAIT} };
struct sembuf MSG_SemOp_SEL [2] = { {0, -1, SEM_UNDO}, {0, 0, SEM_UNDO} };
struct sembuf MSG_SemOp_REL [2] = { {0, 0, SEM_UNDO|IPC_NOWAIT}, {0, 1, SEM_UNDO|IPC_NOWAIT} };
/* Compteur d'ouverture de la librairie */
unsigned int MSG_Open_Counter = 0;
/* Flux de sortie des messages d'erreur générés par la librairie */
FILE * MSG_stderr;
typedef union semun {
int val;
struct semid_ds * buf;
unsigned short int * array;
} semun;
NDT_Status MSG_Base_Port_List_Manager (va_list);
NDT_Status MSG_Semaphore_List_Manager (va_list args_ptr);
NDT_Status MSG_PortList_Manager (va_list args_ptr);
NDT_Status MSG_MessageQueue_Manager (va_list);
MSGT_Status MSG_ShareLock_Set (int);
MSGT_Status MSG_ShareLock_Release (int);
MSGT_Status MSG_ExclusiveLock_Set (int);
MSGT_Status MSG_ExclusiveLock_Release (int);
MSGT_Status MSG_Semaphore_Operate (int, struct sembuf *, unsigned int);
void MSG_Error_Print ( void );
static char * MSG_Name_Prefix (const char * Name);
char * MSG_LockStatus_Get (int SemID);

516
lib/msg.h Normal file
View File

@ -0,0 +1,516 @@
#ifndef _LIBMSG
#define _LIBMSG
#ifdef __cplusplus
extern "C" {
#endif
#include <sys/time.h>
#include <ver.h>
#include <node.h>
#include <shmem.h>
#include <datastr.h>
/* Code retour des fonctions constituant l'API */
typedef long MSGT_Status;
#define MSGS_OK DSS_OK /* La fonction s'est correctement exécutée et a produit un résultat */
#define MSGS_KO DSS_KO /* La fonction s'est correctement exécutée mais n'a pas produit de résultat */
#define MSGS_YES MSGS_OK /* Résultat booléen positif */
#define MSGS_NO MSGS_KO /* Résultat booléen négatif */
#define MSGS_ERRMEM DSS_ERRMEM /* Problème d'allocation mémoire */
#define MSGS_ERRAPI DSS_ERRAPI /* Utilisation incorrecte des API */
#define MSGS_ERRSHM DSS_ERRSHM /* Problème relatif aux segments de mémoire partagée */
#define MSGS_ERRSEM DSS_ERRSEM /* Problème relatif à l'utilisation des sémaphores */
#define MSGS_ERRSIG DSS_ERRSIG /* Opération sur sémaphore interrompue par un signal */
#define MSGS_ERRDLL DSS_ERRDLL /* Problème de chargement dynamique de librairie */
#define MSGS_ERRNOWAIT -7 /* Opération sur sémaphore impossible et le mode d'opération est sans attente */
#define MSG_ERROR(s) ((s) < 0) /* Tous les codes retour négatifs correspondent à des erreurs */
/* Codes retour spécifiques pour la réception de messages */
#define MSGS_NO_MSG 5
#define MSGS_BAD_TYPE 6
/* Indicateurs */
typedef int MSGT_Flags;
/* Flags de debug sur l'ouverture de la librairie */
#define MSGD_DEBUG_NONE SMD_DEBUG_NONE /* pour n'afficher aucun message généré par les diverses librairies */
#define MSGD_DEBUG SMD_DEBUG /* pour afficher les messages générés par la librairie */
#define MSGD_DEBUG_ALL SMD_DEBUG_ALL /* pour afficher les messages générés par toutes les librairies sous-jacentes */
#define MSGD_DEBUG_MSK (MSGD_DEBUG & MSGD_DEBUG_ALL)
/* Flags d'ouverture et de fermeture des différentes ressources de la librairie */
#define MSGD_OPEN SMD_OPEN
#define MSGD_CREATE SMD_CREATE
#define MSGD_MSK_OPEN(a) (MSGD_OPEN & (a))
#define MSGD_MSK_CREATE(a) (MSGD_CREATE & (a))
#define MSGD_CLOSE SMD_CLOSE
#define MSGD_DESTROY SMD_DESTROY
/* Flags de réception de message */
#define MSGD_NO_WAIT 1 /* Réception sans attente si aucun message */
#define MSGD_WAIT 2 /* Réception avec attente */
/* Flags de verrouillage d'un port de messages */
#define MSGD_READ 1 /* verrou partagé */
#define MSGD_WRITE 2 /* verrou exclusif */
#define MSGD_MSK_READ(a) (MSGD_READ & (a))
#define MSGD_MSK_WRITE(a) (MSGD_WRITE & (a))
#define MSGD_UNLIMITED 0
/* Notion de port de messages */
typedef struct {
char Name [50]; /* Nom du port de messages */
size_t Size; /* Taille limite du port en nombre de messages */
int ListenSemID; /* sémaphore permettant l'écoute du port */
int LockSemID; /* sémaphore permettant le verrouillage du port */
NDT_Root * SemList; /* Liste des sémaphores des listes de ports qui sont à l'écoute du port */
NDT_Root * MsgQueue; /* File d'attente des messages */
} MSGT_Port;
/* Quelques ports de message prédéfinis */
#define MSGD_DEFAULT_PORT_NAME "DEFAULT_PORT"
#define MSGD_SYSTEM_PORT_NAME "SYSTEM_PORT"
#define MSGD_SUPERVISOR_PORT_NAME "SUPERVISOR_PORT"
/* Notion de liste de ports de messages */
typedef struct {
NDT_Root * Root; /* Liste de ports de messages */
int ListenSemID; /* Identifiant du sémaphore pour l'écoute de la liste de ports */
} MSGT_PortList;
/* Notion de messages */
typedef struct {
char From [50]; /* Nom du port d'écoute de l'initiateur du message */
char Via [50]; /* Nom du port d'écoute du dernier envoyeur du message */
char To [50]; /* Nom du port du dernier envoi du message */
unsigned int Type; /* Type du message */
int Priority; /* Priorité du message */
size_t Size; /* Taille des données du message */
void * Data; /* Données du message */
char * Swap; /* Nom du fichier de swap dans lequel est stocké le message */
} MSGT_Message;
#define MSGD_NO_TYPE 0
/*
Types de message :
Les types de message vont de 1 à 255 et sont partagés en 2 plages :
- messages systèmes prédéfinis de 1 à 32
- messages utilisateur de 33 à 255
*/
#define MSGD_NO_TYPE 0
#define MSGD_NB_SYSTEM_MESSAGE 32
#define MSGD_IS_SYSTEM(t) ((t) != MSGD_NO_TYPE && (t) < MSGD_NB_SYSTEM_MESSAGE)
#define MSGD_IS_SYSTEM_REQUEST(t) ((t) != MSGD_NO_TYPE && (t) < MSGD_NB_SYSTEM_MESSAGE && (t) % 2 == 1)
#define MSGD_IS_SYSTEM_REPLY(t) ((t) != MSGD_NO_TYPE && (t) < MSGD_NB_SYSTEM_MESSAGE && (t) % 2 == 0)
#define MSGD_SYSTEM_PING_REQUEST 1
#define MSGD_SYSTEM_PING_REPLY 2
#define MSGD_SYSTEM_STOP_REQUEST 3
#define MSGD_SYSTEM_STOP_REPLY 4
#define MSGD_SYSTEM_CONTINUE_REQUEST 5
#define MSGD_SYSTEM_CONT_REPLY 6
#define MSGD_SYSTEM_RESTART_REQUEST 7
#define MSGD_SYSTEM_RESTART_REPLY 8
#define MSGD_SYSTEM_SHUTDOWN_REQUEST 9
#define MSGD_SYSTEM_SHUTDOWN_REPLY 10
#define MSGD_SYSTEM_STATUS_REQUEST 11
#define MSGD_SYSTEM_STATUS_REPLY 12
#define MSGD_SYSTEM_INFO_REQUEST 13
#define MSGD_SYSTEM_INFO_REPLY 14
#define MSGD_SYSTEM_TRACEON_REQUEST 15
#define MSGD_SYSTEM_TRACEON_REPLY 16
#define MSGD_SYSTEM_TRACEOFF_REQUEST 17
#define MSGD_SYSTEM_TRACEOFF_REPLY 18
/* Type de message système générique (utile pour ne réceptionner que les messages système) */
#define MSGD_SYSTEM_GENERIC MSGD_NB_SYSTEM_MESSAGE
/* Quelques types de messages utilisateur prédéfinis */
#define MSGD_USER_TYPE1 MSGD_NB_SYSTEM_MESSAGE + 1
#define MSGD_USER_TYPE2 MSGD_NB_SYSTEM_MESSAGE + 2
#define MSGD_DEFAULT_TYPE MSGD_USER_TYPE1
/*
Priorités des messages :
Les priorités vont de -128 (la plus elevée) à 127 (plus basse) divisées en 2 plages :
- Priorités des messages système : [-128, -65] U [+65, +127]
- Priorités des messages utilisateur : [-64, +64]
*/
#define MSGD_SYSTEM_HIGH_PRIORITY -128
#define MSGD_SYSTEM_LOW_PRIORITY 127
#define MSGD_USER_HIGH_PRIORITY -64
#define MSGD_USER_NORMAL_PRIORITY 0
#define MSGD_USER_LOW_PRIORITY 64
#define MSGD_DEFAULT_PRIORITY MSGD_USER_NORMAL_PRIORITY
/* Types de configuration */
typedef int MSGT_Config;
#define MSGD_CONFIG_SIZE 1 /* Configuration de la taille d'un port de messages */
#define MSGD_CONFIG_MSGQUEUE 2 /* Choix du type de structure pour la queue de message d'un port de messages */
#define MSGD_CONFIG_TYPE 3 /* Configuration du type d'un message */
#define MSGD_CONFIG_PRIORITY 4 /* Configuration de la priorité d'un message */
char MSG_Error_Msg [512];
/* Base de la librairie LIBMSG */
SMT_Heap * MSG_Base_Heap;
SMT_Heap * MSG_Message_Heap;
typedef struct {
NDT_Root * Port_List; /* Liste de tous les ports de messages */
} MSGT_Base;
MSGT_Base * MSG_Base;
/* Contenu d'un message de type PING_REPLY */
typedef struct {
struct timeval Snd1;
struct timeval Rcv1;
struct timeval Snd2;
struct timeval Rcv2;
} MSGT_PingData;
/* Définition des alias de l'API */
#ifndef MSG_MODE
#define MSG_MODE 0
#endif
#if MSG_MODE == 1
/* Utilisation des API sans vérification des arguments */
# define MSG_Library_Open MSG_Library_Open_I
# define MSG_Library_Signal MSG_Library_Signal_I
# define MSG_Library_IsOpen MSG_Library_IsOpen_I
# define MSG_Library_Context_Set MSG_Library_Context_Set_I
# define MSG_Library_Context_Get MSG_Library_Context_Get_I
# define MSG_Library_Close MSG_Library_Close_I
# define MSG_Library_Stderr_Set MSG_Library_Stderr_Set_I
# define MSG_Library_Dump MSG_Library_Dump_I
# define MSG_Port_Exist MSG_Port_Exist_I
# define MSG_Port_Open MSG_Port_Open_I
# define MSG_Port_Config MSG_Port_Config_I
# define MSG_Port_Lock MSG_Port_Lock_I
# define MSG_Port_Unlock MSG_Port_Unlock_I
# define MSG_Port_Close MSG_Port_Close_I
# define MSG_PortList_Open MSG_PortList_Open_I
# define MSG_PortList_Port_Add MSG_PortList_Port_Add_I
# define MSG_PortList_Port_Remove MSG_PortList_Port_Remove_I
# define MSG_PortList_Close MSG_PortList_Close_I
# define MSG_PortList_Listen MSG_PortList_Listen_I
# define MSG_Message_Alloc MSG_Message_Alloc_I
# define MSG_Message_Config MSG_Message_Config_I
# define MSG_Message_Free MSG_Message_Free_I
# define MSG_Message_Send MSG_Message_Send_I
# define MSG_Message_Receive MSG_Message_Receive_I
# define MSG_Message_Reply MSG_Message_Reply_I
# define MSG_Message_Return MSG_Message_Return_I
#else
/* Utilisation avec vérification des arguments */
# define MSG_Library_Open MSG_Library_Open_C
# define MSG_Library_IsOpen MSG_Library_IsOpen_C
# define MSG_Library_Signal MSG_Library_Signal_C
# define MSG_Library_Context_Set MSG_Library_Context_Set_C
# define MSG_Library_Context_Get MSG_Library_Context_Get_C
# define MSG_Library_Close MSG_Library_Close_C
# define MSG_Library_Stderr_Set MSG_Library_Stderr_Set_C
# define MSG_Library_Dump MSG_Library_Dump_C
# define MSG_Port_Exist MSG_Port_Exist_C
# define MSG_Port_Open MSG_Port_Open_C
# define MSG_Port_Config MSG_Port_Config_C
# define MSG_Port_Lock MSG_Port_Lock_C
# define MSG_Port_Unlock MSG_Port_Unlock_C
# define MSG_Port_Close MSG_Port_Close_C
# define MSG_PortList_Open MSG_PortList_Open_C
# define MSG_PortList_Port_Add MSG_PortList_Port_Add_C
# define MSG_PortList_Port_Remove MSG_PortList_Port_Remove_C
# define MSG_PortList_Close MSG_PortList_Close_C
# define MSG_PortList_Listen MSG_PortList_Listen_C
# define MSG_Message_Alloc MSG_Message_Alloc_C
# define MSG_Message_Config MSG_Message_Config_C
# define MSG_Message_Free MSG_Message_Free_C
# define MSG_Message_Send MSG_Message_Send_C
# define MSG_Message_Receive MSG_Message_Receive_C
# define MSG_Message_Reply MSG_Message_Reply_C
# define MSG_Message_Return MSG_Message_Return_C
#endif
/*------------------------------------------------------------------------------*/
/* Permet d'indiquer à la librairie qu'un signal a été reçu. */
/* */
/* NB : cette fonction sera appelée par l'utilisateur pour éviter que le */
/* processus se bloque sur une attente de message malgré la réception de signal */
/*------------------------------------------------------------------------------*/
MSGT_Status MSG_Library_Signal_I ( void );
MSGT_Status MSG_Library_Signal_C ( void );
/*------------------------------------------------------------------------------*/
/* Ouverture de la librairie */
/*------------------------------------------------------------------------------*/
/* (I) Instance : numéro de l'instance de la librairie */
/* (I) Context : contexte d'utilisation de la librairie */
/* (I) Open_Mode : mode d'ouverture de la librairie */
/*------------------------------------------------------------------------------*/
MSGT_Status MSG_Library_Open_I ( int Instance, const char * Context, MSGT_Flags Open_Mode );
MSGT_Status MSG_Library_Open_C ( int Instance, const char * Context, MSGT_Flags Open_Mode );
/*------------------------------------------------------------------------------*/
/* Teste si la librairie a été ouverte */
/*------------------------------------------------------------------------------*/
MSGT_Status MSG_Library_IsOpen_I ( void );
MSGT_Status MSG_Library_IsOpen_C ( void );
/*------------------------------------------------------------------------------*/
/* Changement de contexte d'utilisation de la librairie */
/*------------------------------------------------------------------------------*/
/* (I) Context : nom du nouveau contexte */
/*------------------------------------------------------------------------------*/
MSGT_Status MSG_Library_Context_Set_I (const char * Context);
MSGT_Status MSG_Library_Context_Set_C (const char * Context);
/*------------------------------------------------------------------------------*/
/* Récupération du nom du contexte utilisée */
/*------------------------------------------------------------------------------*/
/* (O) Context : adresse du nom du contexte utilisé */
/*------------------------------------------------------------------------------*/
MSGT_Status MSG_Library_Context_Get_I (char ** Context);
MSGT_Status MSG_Library_Context_Get_C (char ** Context);
/*------------------------------------------------------------------------------*/
/* Fermeture de la librairie */
/*------------------------------------------------------------------------------*/
/* (I) Close_Mode : mode de fermeture de la librairie */
/*------------------------------------------------------------------------------*/
MSGT_Status MSG_Library_Close_I ( MSGT_Flags Close_Mode );
MSGT_Status MSG_Library_Close_C ( MSGT_Flags Close_Mode );
/*------------------------------------------------------------------------------*/
/* Définition de la sortie standard des messages d'erreur de la librairie */
/*------------------------------------------------------------------------------*/
/* (I) Out : flux de sortie des messages d'erreur */
/*------------------------------------------------------------------------------*/
MSGT_Status MSG_Library_Stderr_Set_I ( FILE * Out );
MSGT_Status MSG_Library_Stderr_Set_C ( FILE * Out );
/*------------------------------------------------------------------------------*/
/* Affichage des ressources de la librairie */
/*------------------------------------------------------------------------------*/
/* (I) Out : Flux de sortie de l'affichage */
/*------------------------------------------------------------------------------*/
MSGT_Status MSG_Library_Dump_I ( FILE * Out );
MSGT_Status MSG_Library_Dump_C ( FILE * Out );
/*------------------------------------------------------------------------------*/
/* Teste l'existence d'un port de messages */
/*------------------------------------------------------------------------------*/
/* (I) Name : nom du port de messages */
/* (O) Port : adresse d'un pointeur sur le port de messages */
/*------------------------------------------------------------------------------*/
MSGT_Status MSG_Port_Exist_I ( const char *, MSGT_Port ** );
MSGT_Status MSG_Port_Exist_C ( const char *, MSGT_Port ** );
/*------------------------------------------------------------------------------*/
/* Création/ouverture d'un port de messages */
/*------------------------------------------------------------------------------*/
/* (I) Name : nom du port de messages */
/* (O) Port : adresse d'un pointeur sur le port de messages */
/* (I) Open_Mode : mode d'ouverture du port de messages */
/*------------------------------------------------------------------------------*/
MSGT_Status MSG_Port_Open_I ( const char * Name, MSGT_Port ** Port, MSGT_Flags Open_Mode );
MSGT_Status MSG_Port_Open_C ( const char * Name, MSGT_Port ** Port, MSGT_Flags Open_Mode );
/*------------------------------------------------------------------------------*/
/* Configuration d'un port de messages */
/*------------------------------------------------------------------------------*/
/* (I) Port : pointeur sur le port de messages */
/* (I) Tag : type de configuration */
/* (I) ... : données de configuration */
/*------------------------------------------------------------------------------*/
MSGT_Status MSG_Port_Config_I ( MSGT_Port * Port, MSGT_Config Tag, ... );
MSGT_Status MSG_Port_Config_C ( MSGT_Port * Port, MSGT_Config Tag, ... );
/*------------------------------------------------------------------------------*/
/* Verrouillage d'un port de messages */
/*------------------------------------------------------------------------------*/
/* (I) Port : pointeur sur le port de messages */
/* (I) Mode : type de verrouillage */
/*------------------------------------------------------------------------------*/
MSGT_Status MSG_Port_Lock_I ( MSGT_Port * Port, MSGT_Flags Mode );
MSGT_Status MSG_Port_Lock_C ( MSGT_Port * Port, MSGT_Flags Mode );
/*------------------------------------------------------------------------------*/
/* Déverrouillage d'un port de messages */
/*------------------------------------------------------------------------------*/
/* (I) Port : pointeur sur le port de messages */
/* (I) Mode : type de verrou à enlever */
/*------------------------------------------------------------------------------*/
MSGT_Status MSG_Port_Unlock_I ( MSGT_Port * Port, MSGT_Flags Mode );
MSGT_Status MSG_Port_Unlock_C ( MSGT_Port * Port, MSGT_Flags Mode );
/*------------------------------------------------------------------------------*/
/* Fermeture d'un port de messages */
/*------------------------------------------------------------------------------*/
/* (I) Port : pointeur sur le port de messages */
/* (I) Close_Mode : mode de fermeture du port de messages */
/*------------------------------------------------------------------------------*/
MSGT_Status MSG_Port_Close_I ( MSGT_Port * Port, MSGT_Flags Close_Mode );
MSGT_Status MSG_Port_Close_C ( MSGT_Port * Port, MSGT_Flags Close_Mode );
/*------------------------------------------------------------------------------*/
/* Création/ouverture d'une liste de ports de messages */
/*------------------------------------------------------------------------------*/
/* (O) PortList : adresse d'un pointeur sur la liste de ports de messages */
/*------------------------------------------------------------------------------*/
MSGT_Status MSG_PortList_Open_I ( MSGT_PortList ** PortList );
MSGT_Status MSG_PortList_Open_C ( MSGT_PortList ** PortList );
/*------------------------------------------------------------------------------*/
/* Ajout d'un port de messages à une liste de ports */
/*------------------------------------------------------------------------------*/
/* (I) PortList : pointeur sur la liste de ports de messages */
/* (I) Port : pointeur sur un port de messages */
/*------------------------------------------------------------------------------*/
MSGT_Status MSG_PortList_Port_Add_I ( MSGT_PortList * PortList, MSGT_Port * Port );
MSGT_Status MSG_PortList_Port_Add_C ( MSGT_PortList * PortList, MSGT_Port * Port );
/*------------------------------------------------------------------------------*/
/* Retrait d'un port de messages d'une liste de ports */
/*------------------------------------------------------------------------------*/
/* (I) PortList : pointeur sur la liste de ports de messages */
/* (I) Port : pointeur sur un port de messages */
/*------------------------------------------------------------------------------*/
MSGT_Status MSG_PortList_Port_Remove_I ( MSGT_PortList * PortList, MSGT_Port * Port );
MSGT_Status MSG_PortList_Port_Remove_C ( MSGT_PortList * PortList, MSGT_Port * Port );
/*------------------------------------------------------------------------------*/
/* Suppressin d'une liste de ports de messages */
/*------------------------------------------------------------------------------*/
/* (I) PortList : pointeur sur la liste de ports de messages */
/*------------------------------------------------------------------------------*/
MSGT_Status MSG_PortList_Close_I ( MSGT_PortList * PortList );
MSGT_Status MSG_PortList_Close_C ( MSGT_PortList * PortList );
/*------------------------------------------------------------------------------*/
/* Ecoute d'une liste de ports de messages */
/*------------------------------------------------------------------------------*/
/* (I) PortList : pointeur sur une liste de ports de messages */
/* (I) Type : type du message à récupérer */
/* (O) Msg : adresse d'un pointeur sur le message à recevoir */
/* (I) Flags : paramètres de réception */
/*------------------------------------------------------------------------------*/
MSGT_Status MSG_PortList_Listen_I ( MSGT_PortList * PortList, unsigned int Type, MSGT_Message ** Msg, MSGT_Flags Flags);
MSGT_Status MSG_PortList_Listen_C ( MSGT_PortList * PortList, unsigned int Type, MSGT_Message ** Msg, MSGT_Flags Flags);
/*------------------------------------------------------------------------------*/
/* Création d'un message */
/*------------------------------------------------------------------------------*/
/* (O) Msg : adresse d'un pointeur sur le message */
/* (I) Size : taille en octets des données du message */
/*------------------------------------------------------------------------------*/
MSGT_Status MSG_Message_Alloc_I ( MSGT_Message ** Msg, size_t Size );
MSGT_Status MSG_Message_Alloc_C ( MSGT_Message ** Msg, size_t Size );
/*------------------------------------------------------------------------------*/
/* Configuration d'un message */
/*------------------------------------------------------------------------------*/
/* (I) Msg : pointeur sur un message */
/* (I) Tag : type de configuration */
/* (I) ... : données de configuration */
/*------------------------------------------------------------------------------*/
MSGT_Status MSG_Message_Config_I ( MSGT_Message * Msg, MSGT_Config Tag, ... );
MSGT_Status MSG_Message_Config_C ( MSGT_Message * Msg, MSGT_Config Tag, ... );
/*------------------------------------------------------------------------------*/
/* Destruction d'un message */
/*------------------------------------------------------------------------------*/
/* (I) Msg : pointeur sur le message */
/*------------------------------------------------------------------------------*/
MSGT_Status MSG_Message_Free_I ( MSGT_Message * Msg );
MSGT_Status MSG_Message_Free_C ( MSGT_Message * Msg );
/*------------------------------------------------------------------------------*/
/* Envoi d'un message dans un port de messages */
/*------------------------------------------------------------------------------*/
/* (I) From : nom du port de messages de l'envoyeur */
/* (I) To : pointeur sur le port de messages destinataire */
/* (I) Msg : pointeur sur le message */
/*------------------------------------------------------------------------------*/
MSGT_Status MSG_Message_Send_I ( const char * From, MSGT_Port * To, MSGT_Message * Msg );
MSGT_Status MSG_Message_Send_C ( const char * From, MSGT_Port * To, MSGT_Message * Msg );
/*------------------------------------------------------------------------------*/
/* Réception d'un message dans un port de messages */
/*------------------------------------------------------------------------------*/
/* (I) Port : pointeur sur le port de messages */
/* (I) Type : type du message à récupérer */
/* (O) Msg : adresse d'un pointeur sur le message à recevoir */
/* (I) Flags : paramètres de réception */
/*------------------------------------------------------------------------------*/
MSGT_Status MSG_Message_Receive_I ( MSGT_Port * Port, unsigned int Type, MSGT_Message ** Msg, MSGT_Flags Flags );
MSGT_Status MSG_Message_Receive_C ( MSGT_Port * Port, unsigned int Type, MSGT_Message ** Msg, MSGT_Flags Flags );
/*------------------------------------------------------------------------------*/
/* Retour à l'envoyeur d'un message */
/*------------------------------------------------------------------------------*/
/* (I) Msg : pointeur sur le message */
/*------------------------------------------------------------------------------*/
MSGT_Status MSG_Message_Reply_I ( MSGT_Message * Msg );
MSGT_Status MSG_Message_Reply_C ( MSGT_Message * Msg );
/*------------------------------------------------------------------------------*/
/* Retour à l'initiateur d'un message */
/*------------------------------------------------------------------------------*/
/* (I) Msg : pointeur sur le message */
/*------------------------------------------------------------------------------*/
MSGT_Status MSG_Message_Return_I ( MSGT_Message * Msg );
MSGT_Status MSG_Message_Return_C ( MSGT_Message * Msg );
#ifdef __cplusplus
}
#endif
#endif

235
util/msgadmin.c Normal file
View File

@ -0,0 +1,235 @@
#define DATASTR_MODE 1 /* Pas de vérif des arguments + verrou sytématique */
#define MSG_MODE 1 /* Pas de vérif des arguments */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <sys/time.h>
#include <ver.h>
#include <datastr.h>
#include <msg.h>
VER_INFO_EXPORT (msgadmin, "$Revision: 1.1 $", "$Name: $", __FILE__, "$Author: smas $")
#define USAGE "Usage : %s [ --help | --version [-v] | --create | --destroy ]\n"
#define QUIT 0
#define BASE_INIT 1
#define BASE_OPEN 2
#define BASE_INFO 3
#define BASE_CLOSE 4
#define BASE_END 5
#define SHOW_PORT_LIST 6
#define PORT_CREATE 7
#define PORT_DUMP 8
#define PORT_FLUSH 9
#define PORT_DELETE 10
char menu [1000];
char tmp [100];
void init_menu (void);
int print_menu (void);
int main (int argc, char ** argv)
{
int choice;
MSGT_Port * Port;
MSGT_Message * Msg;
char Answer[10];
/* Lancement de commande d'administration */
if (argc >= 2)
{
if (!strcmp (argv[1], "--help"))
{
fprintf (stderr, USAGE, argv[0]);
return -1;
}
else if (!strcmp (argv[1], "--version"))
{
if (argc >= 3 && !strcmp (argv[2], "-v")) return VER_Object_Print (stdout, VERD_VERBOSE);
else return VER_Object_Print (stdout, VERD_MINIMAL);
}
else if (!strcmp (argv[1], "--create"))
{
if (MSG_Library_Open (0, NULL, MSGD_CREATE | MSGD_DEBUG_ALL) != MSGS_OK)
{
fprintf (stderr, "=> Impossible de créer l'instance de la librairie LIBMSG\n");
return -1;
}
return 1;
}
else if (!strcmp (argv[1], "--destroy"))
{
if (MSG_Library_Open (0, NULL, MSGD_OPEN | MSGD_DEBUG_ALL) != MSGS_OK || MSG_Library_Close (MSGD_DESTROY) != MSGS_OK)
{
fprintf (stderr, "=> Impossible de détruire l'instance de la librairie LIBMSG\n");
return -1;
}
return 0;
}
else
{
fprintf (stderr, USAGE, argv[0]);
return -1;
}
}
/* Lancement du menu intercatif */
init_menu ();
choice = print_menu ();
while (choice != QUIT)
{
strcpy (Answer, "yes");
switch (choice)
{
case BASE_INIT:
fprintf (stdout, "\nReturn code = %s\n", \
MSG_Library_Open (0, NULL, MSGD_CREATE | MSGD_DEBUG_ALL) == MSGS_OK ? "OK" : "NOK" );
break;
case BASE_OPEN:
fprintf (stdout, "\nReturn code = %s\n", \
MSG_Library_Open (0, NULL, MSGD_OPEN | MSGD_DEBUG_ALL) == MSGS_OK ? "OK" : "NOK" );
break;
case BASE_END:
fprintf (stdout, "\nReturn code = %s\n", \
MSG_Library_Close (MSGD_DESTROY) == MSGS_OK ? "OK" : "NOK" );
break;
case BASE_CLOSE:
fprintf (stdout, "\nReturn code = %s\n", \
MSG_Library_Close (MSGD_CLOSE) == MSGS_OK ? "OK" : "NOK" );
break;
case BASE_INFO:
if (!MSG_Base)
fprintf (stdout, "\nLIBMSG base must be opened first\n");
else
DS_DataStruct_Info_Print (MSG_Base->Port_List, stdout);
break;
case SHOW_PORT_LIST:
if (!MSG_Base) fprintf (stdout, "\nLIBMSG base must be opened first\n");
else DS_DataStruct_Print (MSG_Base->Port_List, stdout);
break;
case PORT_CREATE:
if (!MSG_Base) fprintf (stdout, "\nLIBMSG base must be opened first\n");
else
{
fprintf (stdout, "\nPort name ? ");
gets (tmp);
if (MSG_Port_Open (tmp, &Port, MSGD_CREATE) != MSGS_OK)
fprintf (stdout, "Unable to create port \"%s\"\n", tmp);
}
break;
case PORT_DUMP:
if (!MSG_Base) fprintf (stdout, "\nLIBMSG base must be opened first\n");
else
{
fprintf (stdout, "\nPort name ? ");
gets (tmp);
if (MSG_Port_Open (tmp, &Port, MSGD_OPEN) != MSGS_OK)
fprintf (stdout, "Unable to open port \"%s\"\n", tmp);
else
{
ND_Manager_Exec (MSG_Base->Port_List->Manager, NDD_CMD_PRINT_VALUE, Port, stdout);
if (fprintf (stdout, "\n\nShow message queue ? (y/n) ") && gets (tmp) && *tmp == 'y')
DS_DataStruct_Print (Port->MsgQueue, stdout);
if (fprintf (stdout, "\nShow semaphore list ? (y/n) ") && gets (tmp) && *tmp == 'y')
DS_DataStruct_Print (Port->SemList, stdout);
}
}
break;
case PORT_FLUSH:
if (!MSG_Base) fprintf (stdout, "\nLIBMSG base must be opened first\n");
else
{
fprintf (stdout, "\nPort name ? ");
gets (tmp);
if (MSG_Port_Open (tmp, &Port, MSGD_OPEN) != MSGS_OK)
fprintf (stdout, "Unable to open port \"%s\"\n", tmp);
/* Retrait de tous les messages du port */
while (MSG_Message_Receive (Port, MSGD_NO_TYPE, &Msg, MSGD_NO_WAIT) == MSGS_OK)
MSG_Message_Free (Msg);
}
break;
case PORT_DELETE:
if (!MSG_Base) fprintf (stdout, "\nLIBMSG base must be opened first\n");
else
{
fprintf (stdout, "\nPort name ? ");
gets (tmp);
if (MSG_Port_Exist (tmp, &Port) != MSGS_OK)
{
fprintf (stdout, "Port \"%s\" does not exist\n", tmp);
break;
}
if (MSG_Port_Close (Port, MSGD_DESTROY) != MSGS_OK)
fprintf (stdout, "Unable to delete port \"%s\"\n", tmp);
}
break;
case QUIT:
fprintf (stdout, "\nExiting program ...\n");
break;
default:
fprintf (stdout, "\nUndefined choice %d\n", choice);
}
choice = print_menu ();
}
return 0;
}
void init_menu (void)
{
sprintf (menu, "Menu :\n");
sprintf (tmp, " - %2d) %-25s", QUIT, "Quit"); strcat (menu, tmp);
sprintf (tmp, " - %2d) %-25s\n", BASE_INIT, "Init library"); strcat (menu, tmp);
sprintf (tmp, " - %2d) %-25s", BASE_OPEN, "Open library"); strcat (menu, tmp);
sprintf (tmp, " - %2d) %-25s\n", BASE_INFO, "Info library"); strcat (menu, tmp);
sprintf (tmp, " - %2d) %-25s", BASE_CLOSE, "Close library"); strcat (menu, tmp);
sprintf (tmp, " - %2d) %-25s\n", BASE_END, "End library"); strcat (menu, tmp);
sprintf (tmp, " - %2d) %-25s", SHOW_PORT_LIST, "Show message ports"); strcat (menu, tmp);
sprintf (tmp, " - %2d) %-25s\n", PORT_CREATE, "Create a message port"); strcat (menu, tmp);
sprintf (tmp, " - %2d) %-25s", PORT_DUMP, "Dump a message port"); strcat (menu, tmp);
sprintf (tmp, " - %2d) %-25s\n", PORT_FLUSH, "Flush all message from a port"); strcat (menu, tmp);
sprintf (tmp, " - %2d) %-25s\n", PORT_DELETE, "Delete a message port"); strcat (menu, tmp);
}
int print_menu (void)
{
fprintf (stdout, "---------------------------------------------------------------------------\n%s", menu);
tmp[0] = '\0';
while (tmp[0] == '\0')
{
printf ("\nChoice ? ");
gets (tmp);
}
return atoi (tmp);
}

BIN
util/msgbench.xls Normal file

Binary file not shown.

40
util/pingpong.result.cc Normal file
View File

@ -0,0 +1,40 @@
-------------- TEST LIBMSG -----------------
Testing LIBMSG for 10 second(s) with 1 message(s) of 10 byte(s)...
20450 message(s) exchanged (2045 msg/sec)
Testing LIBMSG for 10 second(s) with 1 message(s) of 1000 byte(s)...
20244 message(s) exchanged (2024 msg/sec)
Testing LIBMSG for 10 second(s) with 1 message(s) of 2048 byte(s)...
19520 message(s) exchanged (1952 msg/sec)
---------
Testing LIBMSG for 10 second(s) with 10 message(s) of 10 byte(s)...
30752 message(s) exchanged (3075 msg/sec)
Testing LIBMSG for 10 second(s) with 10 message(s) of 1000 byte(s)...
30220 message(s) exchanged (3022 msg/sec)
Testing LIBMSG for 10 second(s) with 10 message(s) of 2048 byte(s)...
28590 message(s) exchanged (2859 msg/sec)
---------
Testing LIBMSG for 10 second(s) with 100 message(s) of 10 byte(s)...
27008 message(s) exchanged (2700 msg/sec)
Testing LIBMSG for 10 second(s) with 100 message(s) of 1000 byte(s)...
24970 message(s) exchanged (2497 msg/sec)
Testing LIBMSG for 10 second(s) with 100 message(s) of 2048 byte(s)...
21838 message(s) exchanged (2183 msg/sec)
-------------- TEST IPC -----------------
Testing IPC message queue for 10 second (s) with 1 message (s) of 10 byte (s)...
169485 message (s) exchanged (16948 Msg/sec)
Testing IPC message queue for 10 second (s) with 1 message (s) of 1000 byte (s)...
102630 message (s) exchanged (10263 Msg/sec)
Testing IPC message queue for 10 second (s) with 1 message (s) of 2048 byte (s)...
102040 message (s) exchanged (10204 Msg/sec)
---------
Testing IPC message queue for 10 second (s) with 10 message (s) of 10 byte (s)...
300810 message (s) exchanged (30081 Msg/sec)
Testing IPC message queue for 10 second (s) with 10 message (s) of 1000 byte (s)...
159352 message (s) exchanged (15935 Msg/sec)
Testing IPC message queue for 10 second (s) with 10 message (s) of 2048 byte (s)...
127773 message (s) exchanged (12777 Msg/sec)
---------
Testing IPC message queue for 10 second (s) with 100 message (s) of 1000 byte (s)...
175376 message (s) exchanged (17537 Msg/sec)
Testing IPC message queue for 10 second (s) with 100 message (s) of 2048 byte (s)...
121655 message (s) exchanged (12165 Msg/sec)

40
util/pingpong.result.gcc Normal file
View File

@ -0,0 +1,40 @@
-------------- TEST LIBMSG -----------------
Testing LIBMSG for 10 second(s) with 1 message(s) of 10 byte(s)...
30364 message(s) exchanged (3036 msg/sec)
Testing LIBMSG for 10 second(s) with 1 message(s) of 1000 byte(s)...
29490 message(s) exchanged (2949 msg/sec)
Testing LIBMSG for 10 second(s) with 1 message(s) of 2048 byte(s)...
32788 message(s) exchanged (3278 msg/sec)
---------
Testing LIBMSG for 10 second(s) with 10 message(s) of 10 byte(s)...
32203 message(s) exchanged (3220 msg/sec)
Testing LIBMSG for 10 second(s) with 10 message(s) of 1000 byte(s)...
36712 message(s) exchanged (3671 msg/sec)
Testing LIBMSG for 10 second(s) with 10 message(s) of 2048 byte(s)...
34887 message(s) exchanged (3488 msg/sec)
---------
Testing LIBMSG for 10 second(s) with 100 message(s) of 10 byte(s)...
24382 message(s) exchanged (2438 msg/sec)
Testing LIBMSG for 10 second(s) with 100 message(s) of 1000 byte(s)...
24552 message(s) exchanged (2455 msg/sec)
Testing LIBMSG for 10 second(s) with 100 message(s) of 2048 byte(s)...
25862 message(s) exchanged (2586 msg/sec)
-------------- TEST IPC -----------------
Testing IPC message queue for 10 second (s) with 1 message (s) of 10 byte (s)...
162587 message (s) exchanged (16258 Msg/sec)
Testing IPC message queue for 10 second (s) with 1 message (s) of 1000 byte (s)...
106886 message (s) exchanged (10688 Msg/sec)
Testing IPC message queue for 10 second (s) with 1 message (s) of 2048 byte (s)...
88864 message (s) exchanged (8886 Msg/sec)
---------
Testing IPC message queue for 10 second (s) with 10 message (s) of 10 byte (s)...
267204 message (s) exchanged (26720 Msg/sec)
Testing IPC message queue for 10 second (s) with 10 message (s) of 1000 byte (s)...
167169 message (s) exchanged (16716 Msg/sec)
Testing IPC message queue for 10 second (s) with 10 message (s) of 2048 byte (s)...
121365 message (s) exchanged (12136 Msg/sec)
---------
Testing IPC message queue for 10 second (s) with 100 message (s) of 1000 byte (s)...
165790 message (s) exchanged (16579 Msg/sec)
Testing IPC message queue for 10 second (s) with 100 message (s) of 2048 byte (s)...
122897 message (s) exchanged (12289 Msg/sec)

579
util/pingpong_ipc.c Normal file
View File

@ -0,0 +1,579 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <errno.h>
#include <time.h>
#include <signal.h>
#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 64 /* Clé du port de messages du père */
#define CHILD_KEY 65 /* Clé du port de messages du fils */
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
/*----------------------------------------------------------------*/
typedef struct {
long mtype;
char * mtext;
} T_Msg;
int My_Port, Its_Port;
int Child_Pid, Father_Pid, Its_Pid, My_Pid;
int Verbose;
unsigned int Timer;
unsigned int Win_Size;
unsigned int Msg_Size;
int Cpt_Msg;
T_Msg ** Msg_Window;
int End_Test, End_Sigum;
char * error_code (void);
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 *);
/*----------------------------------------------------------------*/
int main (int argc, char ** argv)
{
unsigned int i, size;
char str [256];
T_Msg * Msg;
/* Récupération des arguments de la ligne de commande */
parse_arg (argc, argv);
/* Récupération du no de process courant */
Father_Pid = getpid ();
/* Création d'un process fils avec qui dialoguer */
if ((Child_Pid = fork ()) != 0)
{
/*--------- Code pour le process père -----------*/
Its_Pid = Child_Pid;
My_Pid = Father_Pid;
My_Port = 0;
signal (SIGINT, stop_test);
signal (SIGUSR1, stop_test);
/* Création d'un port de messages */
if ((My_Port = msgget (FATHER_KEY, 0777|IPC_CREAT|IPC_EXCL)) == -1)
{
fprintf (stderr, "Unable to create message queue for the father process : error %d (%s)\n", errno, error_code ());
clean (TRUE);
return 0;
}
else
{
sprintf (str, "Message port %d created", My_Port);
trace (str);
}
/* On attend que le fils ait créé son port de messages */
sleep (2);
/* Initialisation de la fenêtre de messages */
Msg_Window = (T_Msg **)malloc (Win_Size);
for (i = 0; i < Win_Size; i++)
{
Msg_Window[i] = (T_Msg *)malloc (sizeof (T_Msg));
Msg_Window[i]->mtype = 1;
Msg_Window[i]->mtext = (char *)malloc (Msg_Size);
Msg_Window[i]->mtext[0] = (char)i;
}
/* Récupération de la port de messages du fils */
if ((Its_Port = msgget (CHILD_KEY, 0)) == -1)
{
fprintf (stderr, "Unable to retrieve the message queue of the child process : error %d (%s)\n", errno, error_code ());
clean (TRUE);
return 0;
}
Msg = malloc (sizeof (T_Msg));
Msg->mtext = (char *)malloc (Msg_Size);
/* Initialisation du Timer */
signal (SIGALRM, stop_test);
alarm (Timer);
/* Début du test : traitement des messages */
fprintf (stdout, "Testing IPC message queue for %d second (s) with %d message (s) of %d byte (s)...\n", Timer, Win_Size, Msg_Size);
/* Envoi de tous les messages de la fenêtre au fils */
for (i = 0; i < Win_Size; i++)
{
errno = 0;
if (msgsnd (Its_Port, Msg_Window[i], Msg_Size, IPC_NOWAIT) == 0)
{
if (Verbose)
{
sprintf (str, "Message %d sent to port %d", i, Its_Port);
trace (str);
}
}
if (errno != 0 && errno != EAGAIN)
fprintf (stderr, "Unable to send message %d to port %d : error %d (%s)\n", i, Its_Port, errno, error_code ());
}
Cpt_Msg = 0;
while (End_Test == FALSE)
{
/* Réception de messages */
errno = 0;
if ((size = msgrcv (My_Port, Msg, Msg_Size, 0, MSG_NOERROR)) > 0)
{
i = (int)(Msg->mtext[0]);
if (Verbose)
{
sprintf (str, "Message %d received from port %d", i, My_Port);
trace (str);
}
Cpt_Msg++;
/* Réenvoi du message au fils */
errno = 0;
if (msgsnd (Its_Port, Msg_Window[i], Msg_Size, IPC_NOWAIT) == 0)
{
if (Verbose)
{
sprintf (str, "Message %d replied", i);
trace (str);
}
}
if (errno != 0 && errno != EAGAIN)
fprintf (stderr, "Unable to reply message %d to port %d (%s)\n", i, Its_Port, error_code ());
}
if (errno != 0)
fprintf (stderr, "Unable to receive a message from port %d (%s)\n", My_Port, error_code ());
}
stop_father ();
}
else
{
/*---------- Code pour le process fils ----------*/
My_Pid = getpid ();
Its_Pid = Father_Pid;
My_Port = 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 */
if ((My_Port = msgget (CHILD_KEY, 0777|IPC_CREAT|IPC_EXCL)) == -1)
{
fprintf (stderr, "Unable to create message queue for the child process (%s)\n", error_code ());
clean (TRUE);
return 0;
}
else
{
sprintf (str, "Message port %d created", My_Port);
trace (str);
}
/* On attend que le père ait créé son port de messages */
sleep (2);
Msg_Window = (T_Msg **)malloc (Win_Size);
for (i = 0; i < Win_Size; i++)
{
Msg_Window[i] = (T_Msg *)malloc (sizeof (T_Msg));
Msg_Window[i]->mtype = 1;
Msg_Window[i]->mtext = (char *)malloc (Msg_Size * sizeof (char));
Msg_Window[i]->mtext[0] = (char)i;
}
/* Récupération du port de messages du père */
if ((Its_Port = msgget (FATHER_KEY, 0)) == -1)
{
fprintf (stderr, "Unable to retrieve the message queue of the father process (%s)\n", error_code ());
clean (TRUE);
return 0;
}
/* Traitement des messages */
Msg = malloc (sizeof (T_Msg));
Msg->mtext = (char *)malloc (Msg_Size * sizeof (char));
while (End_Test == FALSE)
{
/* Réception de messages */
errno = 0;
if ((size = msgrcv (My_Port, Msg, Msg_Size, 0, MSG_NOERROR)) > 0)
{
i = (int)(Msg->mtext[0]);
if (Verbose)
{
sprintf (str, "Message %d received from port %d", i, My_Port);
trace (str);
}
Cpt_Msg++;
/* Réenvoi du message au fils */
errno = 0;
if (msgsnd (Its_Port, Msg_Window[i], Msg_Size, IPC_NOWAIT) == 0)
{
if (Verbose)
{
sprintf (str, "Message %d replied", i);
trace (str);
}
}
if (errno != 0 && errno != EAGAIN)
fprintf (stderr, "Unable to reply message %d to port %d (%s)\n", i, Its_Port, error_code ());
}
if (errno != 0)
fprintf (stderr, "Unable to receive a message from port %d (%s)\n", My_Port, error_code ());
}
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 */
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 */
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)
{
unsigned int i;
char str [256];
/* On avertit l'autre process */
if (warn == TRUE) kill (Its_Pid, SIGUSR1);
if (Msg_Window != NULL)
{
for (i = 0; i < Win_Size; i++)
{
if (Msg_Window[i] != NULL)
{
if (Msg_Window[i]->mtext != NULL) free (Msg_Window[i]->mtext);
free (Msg_Window[i]);
}
}
free (Msg_Window);
}
/* Destruction de la port de messages */
if (My_Port > 0)
{
if (Verbose)
{
sprintf (str, "Removing message queue %d...\n", My_Port);
trace (str);
}
msgctl (My_Port, IPC_RMID, NULL);
}
}
/*----------------------------------------------------------------*/
char * error_code (void)
{
static char * str;
if (str) free (str);
switch (errno)
{
case EACCES:
str = strdup ("EACCES");
break;
case EEXIST:
str = strdup ("EEXIST");
break;
case EIDRM:
str = strdup ("EIDRM");
break;
case ENOENT:
str = strdup ("ENOENT");
break;
case ENOMEM:
str = strdup ("ENOMEM");
break;
case ENOSPC:
str = strdup ("ENOSPC");
break;
case EFAULT:
str = strdup ("EFAULT");
break;
case EINTR:
str = strdup ("EINTR");
break;
case EINVAL:
str = strdup ("EINVAL");
break;
case E2BIG:
str = strdup ("E2BIG");
break;
case ENOMSG:
str = strdup ("ENOMSG");
break;
case EAGAIN:
str = strdup ("EAGAIN");
break;
default:
str = strdup ("unknown");
break;
}
return str;
}
/*----------------------------------------------------------------*/
void trace (char *str)
{
time_t dts;
struct tm *dt;
char current_date [30];
char str_trace [256];
/* 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 (str_trace, "Process %d - %s : %s\n", My_Pid, current_date, str);
fprintf (stderr, str_trace);
fflush (stderr);
}
/*----------------------------------------------------------------*/
void parse_arg (int argc, char ** argv)
{
int i;
Verbose = 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 <time in seconds> (default is %d)\n", DEFAULT_TIMER);
fprintf (stdout, "\t --window <message number> (default is %d)\n", DEFAULT_WINSIZE);
fprintf (stdout, "\t --message <message size> (default is %d bytes)\n", DEFAULT_MSGSIZE);
exit (1);
}
if (!strcmp (argv[i], "--clean"))
{
if ((My_Port = msgget (FATHER_KEY, 0)) != -1) msgctl (My_Port, IPC_RMID, NULL);
if ((Its_Port = msgget (CHILD_KEY, 0)) != -1) msgctl (Its_Port, IPC_RMID, NULL);
exit (1);
}
if (!strcmp (argv[i], "--verbose"))
{
Verbose = TRUE;
continue;
}
if (!strcmp (argv[i], "--duration"))
{
i++;
if (i == argc)
{
fprintf (stderr, "Missing argument after %s\n", argv[i - 1]);
exit (0);
}
Timer = atoi (argv[i]);
continue;
}
if (!strcmp (argv[i], "--window"))
{
i++;
if (i == argc)
{
fprintf (stderr, "Missing argument after %s\n", argv[i - 1]);
exit (0);
}
Win_Size = atoi (argv[i]);
continue;
}
if (!strcmp (argv[i], "--message"))
{
i++;
if (i == argc)
{
fprintf (stderr, "Missing argument after %s\n", argv[i - 1]);
exit (0);
}
Msg_Size = atoi (argv[i]);
continue;
}
fprintf (stdout, "Unknown option '%s'\n", argv[i]);
exit (0);
}
if (Timer <= 0) Timer = DEFAULT_TIMER;
if (Win_Size <= 0) Win_Size = DEFAULT_WINSIZE;
if (Msg_Size <= 0) Msg_Size = DEFAULT_MSGSIZE;
}

543
util/pingpong_msg.c Normal file
View File

@ -0,0 +1,543 @@
#define MSG_MODE 1
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <time.h>
#include <signal.h>
#include <shmem.h>
#include <msg.h>
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 <time in seconds> (default is %d)\n", DEFAULT_TIMER);
fprintf (stdout, "\t --window <message number> (default is %d)\n", DEFAULT_WINSIZE);
fprintf (stdout, "\t --message <message size> (default is %d bytes)\n", DEFAULT_MSGSIZE);
fprintf (stdout, "\t --tree\n");
fprintf (stdout, "\t --version [-v]\n");
exit (1);
}
if (!strcmp (argv[i], "--clean"))
{
if (MSG_Library_Open (NULL, NULL, MSGD_OPEN) == MSGS_OK)
{
if (MSG_Port_Open (FATHER_KEY, &My_Port, MSGD_OPEN) == MSGS_OK)
MSG_Port_Close (My_Port, MSGD_DESTROY);
if (MSG_Port_Open (CHILD_KEY, &Its_Port, MSGD_OPEN) == MSGS_OK)
MSG_Port_Close (Its_Port, MSGD_DESTROY);
MSG_Library_Close (MSGD_CLOSE);
}
exit (1);
}
if (!strcmp (argv[i], "--verbose"))
{
Verbose = TRUE;
continue;
}
if (!strcmp (argv[i], "--tree"))
{
Tree = TRUE;
continue;
}
if (!strcmp (argv[i], "--duration"))
{
i++;
if (i == argc)
{
fprintf (stderr, "Missing argument after %s\n", argv[i - 1]);
exit (0);
}
Timer = atoi (argv[i]);
continue;
}
if (!strcmp (argv[i], "--window"))
{
i++;
if (i == argc)
{
fprintf (stderr, "Missing argument after %s\n", argv[i - 1]);
exit (0);
}
Win_Size = atoi (argv[i]);
continue;
}
if (!strcmp (argv[i], "--message"))
{
i++;
if (i == argc)
{
fprintf (stderr, "Missing argument after %s\n", argv[i - 1]);
exit (0);
}
Msg_Size = atoi (argv[i]);
continue;
}
if (!strcmp (argv[i], "--version"))
{
if (i+1 < argc && !strcmp (argv[i+1], "-v"))
{
VER_Object_Print (stdout, VERD_VERBOSE);
exit (0);
}
else
{
VER_Object_Print (stdout, VERD_MINIMAL);
exit (0);
}
}
fprintf (stdout, "Unknown option '%s'\n", argv[i]);
exit (0);
}
if (Timer <= 0) Timer = DEFAULT_TIMER;
if (Win_Size <= 0) Win_Size = DEFAULT_WINSIZE;
if (Msg_Size <= 0) Msg_Size = DEFAULT_MSGSIZE;
}

20
util/result.linux Normal file
View File

@ -0,0 +1,20 @@
Testing LIBMSG for 10 second(s) with 1 message(s) of 10 byte(s)...
25791 message(s) exchanged (2579 msg/sec)
Testing LIBMSG for 10 second(s) with 1 message(s) of 1000 byte(s)...
24904 message(s) exchanged (2490 msg/sec)
Testing LIBMSG for 10 second(s) with 1 message(s) of 2048 byte(s)...
25248 message(s) exchanged (2524 msg/sec)
---------
Testing LIBMSG for 10 second(s) with 10 message(s) of 10 byte(s)...
27548 message(s) exchanged (2754 msg/sec)
Testing LIBMSG for 10 second(s) with 10 message(s) of 1000 byte(s)...
28720 message(s) exchanged (2872 msg/sec)
Testing LIBMSG for 10 second(s) with 10 message(s) of 2048 byte(s)...
26860 message(s) exchanged (2686 msg/sec)
---------
Testing LIBMSG for 10 second(s) with 100 message(s) of 10 byte(s)...
31243 message(s) exchanged (3124 msg/sec)
Testing LIBMSG for 10 second(s) with 100 message(s) of 1000 byte(s)...
29841 message(s) exchanged (2984 msg/sec)
Testing LIBMSG for 10 second(s) with 100 message(s) of 2048 byte(s)...
31047 message(s) exchanged (3104 msg/sec)

20
util/result.linux.old Normal file
View File

@ -0,0 +1,20 @@
Testing LIBMSG for 10 second(s) with 1 message(s) of 10 byte(s)...
23639 message(s) exchanged (2363 msg/sec)
Testing LIBMSG for 10 second(s) with 1 message(s) of 1000 byte(s)...
22974 message(s) exchanged (2297 msg/sec)
Testing LIBMSG for 10 second(s) with 1 message(s) of 2048 byte(s)...
23340 message(s) exchanged (2334 msg/sec)
---------
Testing LIBMSG for 10 second(s) with 10 message(s) of 10 byte(s)...
26497 message(s) exchanged (2649 msg/sec)
Testing LIBMSG for 10 second(s) with 10 message(s) of 1000 byte(s)...
26441 message(s) exchanged (2644 msg/sec)
Testing LIBMSG for 10 second(s) with 10 message(s) of 2048 byte(s)...
26680 message(s) exchanged (2668 msg/sec)
---------
Testing LIBMSG for 10 second(s) with 100 message(s) of 10 byte(s)...
29914 message(s) exchanged (2991 msg/sec)
Testing LIBMSG for 10 second(s) with 100 message(s) of 1000 byte(s)...
29854 message(s) exchanged (2985 msg/sec)
Testing LIBMSG for 10 second(s) with 100 message(s) of 2048 byte(s)...
29891 message(s) exchanged (2989 msg/sec)

155
util/skeleton.c Normal file
View File

@ -0,0 +1,155 @@
#include <stdlib.h>
#include <string.h>
#include <msg.h>
/*------------------------------------------------------------------------------------------*/
/* Fonction principale du programme */
/*------------------------------------------------------------------------------------------*/
void main ( void )
{
MSGT_Port * My_Port;
MSGT_Message * Msg;
int End_Process;
/* Ouverture de la librairie LIBMSG */
if (MSG_Library_Open (NULL, NULL, MSGD_OPEN) != MSGS_OK)
{
return;
}
/* Ouverture / création du port de messages privé */
if (MSG_Port_Open (<PORT_NAME>, &My_Port, <OPEN_MODE>) != MSGS_OK)
/*
<PORT_NAME> = nom du port privé (sans espace)
<OPEN_MODE> = MSGD_OPEN ou MSGD_CREATE
*/
{
MSG_Library_Close (MSGD_CLOSE);
return;
}
/* Boucle principale du programme */
End_Process = FALSE;
while (End_Proces == FALSE)
{
/* Ecoute du port de messages privé */
int rc = MSG_Message_Receive (My_Port, <RECEIVE_TYPE>, &Msg, <RECEIVE_MODE>);
/*
<RECEIVE_MODE> = MSGD_WAIT ou MSGD_NO_WAIT
<RECEIVE_TYPE> = MSGD_NO_TYPE ou type prédéfini ou type utilisateur
*/
switch (rc)
{
case MSGS_OK:
/* Message reçu */
Message_Process (Msg);
break;
case MSGS_NO_MSG:
/* Aucun message présent (en mode MSGD_NO_WAIT seulement) */
...
break;
case MSGS_BAD_TYPE:
/* Aucun message du type demandé (en mode MSGD_NO_WAIT seulement) */
...
break;
case MSGS_SIGNAL:
/* Ecoute interrompue par l'interception d'un signal */
...
break;
default:
break;
}
/* Traitement propre au programme */
...
} /* Fin de la boucle principale */
/* Fermeture du port de messages privé */
if (MSG_Port_Close (My_Port, <CLOSE_MODE>) != MSGS_OK) /* <CLOSE_MODE> = MSGD_CLOSE ou MSGD_DESTROY */
{
MSG_Library_Close (MSGD_CLOSE);
return;
}
/* Fermeture de la librairie LIBMSG */
MSG_Library_Close (MSGD_CLOSE);
}
/*------------------------------------------------------------------------------------------*/
/* Fonction de traitement d'un message reçu sur le port privé */
/*------------------------------------------------------------------------------------------*/
void Message_Process ( MSGT_Message * Msg )
{
/* Quel est le type du message ? */
switch ( (int)(Msg->Type) )
{
case <TYPE1>:
...
case <TYPE2>:
/* Traitement selon le message */
...
/* Réponse au message */
if (Msg->Size > strlen ("Message bien reçu"))
{
/* Réponse au message reçu */
strcpy ((char *)(Msg->Data), "Message bien reçu");
/* Retour à l'envoyeur */
if (MSG_Message_Reply (Msg) == MSGS_OK) return;
}
break;
default:
break;
}
/* Si on n'a pas répondu au message, on le supprime */
MSG_Message_Free (Msg);
}