IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

POSIX : MSG QUEUE / Lecture sans extraction


Sujet :

C

  1. #1
    Membre régulier
    Inscrit en
    Décembre 2003
    Messages
    99
    Détails du profil
    Informations forums :
    Inscription : Décembre 2003
    Messages : 99
    Points : 82
    Points
    82
    Par défaut POSIX : MSG QUEUE / Lecture sans extraction
    Bonjour,

    J'aimerais savoir si il est possible de lire un élément dans une "message queue" (POSIX) pour faire un traitement puis de le supprimer si le traitement est OK.

    Actuellement j'implémente moi même la file au travers d'un fichier. Mais j'aimerais quelque chose de standard et de plus simple.

    Merci .
    "Il n'existe que deux choses infinies, l'univers et la bêtise humaine... mais pour l'univers, je n'ai pas de certitude absolue." A. Einstein

  2. #2
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par chicorico Voir le message
    Bonjour,

    J'aimerais savoir si il est possible de lire un élément dans une "message queue" (POSIX) pour faire un traitement puis de le supprimer si le traitement est OK.

    Actuellement j'implémente moi même la file au travers d'un fichier. Mais j'aimerais quelque chose de standard et de plus simple.

    Merci .
    Salut

    Tu parles des msq avec msgsnd() et msgrcv() ? Pas possible. Dès que tu récupères un message, il est supprimé de la file d'attente.

    Je m'étais amusé une fois à créer un "spymsg". Le principe était de lire chaque message puis de le remettre dans la file.

    Voici le code
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
     
    //                                                                            
    // SOURCE : msg_espion.c                                                      
    //                                                                            
    // OBJET : msg_espion                                                         
    //                               
    // BUT : Espionner les messages d'une boite aux lettres                       
    //                                                                            
    // PRINCIPE : Le premier argument est la clef de la boite (hexadecimal)       
    //            Le second (facultatif) est le type du message (decimal)         
    //            Si argument pas clef valide, il devient identifiant (décimal)   
    //            Le programme boucle sur le nombre initial de messages           
    //            Le message lu est affiché octet par octet dans le type demandé  
    //            puis il est remis dans la boite (pas d'effacement)              
    //                                                                            
    // USAGE : prog clef/id [type]                                                
    //	- Pas d'option                                                            
    //                                                                            
     
    #include <sys/types.h>						// Types prédéfinis "c"           
    #include <sys/ipc.h>						// Internal Process Comm.         
    #include <sys/msg.h>						// Boite aux lettres I.P.C.       
    #include <stdio.h>							// I/O fichiers classiques        
    #include <errno.h>							// Erreurs système                
     
    extern const char* const sys_errlist[];		// Liste messages erreurs         
     
    #define SZ_MESSAGE			(65535)			// Taille max. message            
     
    typedef struct {
    	mtyp_t mtype;							// Type de message                
    	char mcorps[SZ_MESSAGE];				// Corps du message               
    }t_msgbuf;		 							// Type "message" au format "ipc" 
     
    // Fonction principale 
    main(
    	int argc, 								// Nbre arguments                 
    	char *argv[])							// Ptr arguments                  
    {
    	// Déclaration des variables 
    	ushort nb_msg;							// Nombre de messages présents    
     
    	int msg_id;								// Identifiant de la boite        
    	int status;								// Status de retour fonction      
    	int i;									// Indice de boucle               
     
    	char *pt;								// Ptr sur chaine                 
     
    	key_t msg_key;							// Clef de la boite               
     
    	t_msgbuf msg_buf;						// Message à envoyer              
     
    	struct msqid_ds info; 					// Information boite              
     
    	// Vérification au moins un argument 
    	if (argc <= 1)
    	{
    		fprintf(stderr, "Usage: %s clef/id [type]\n", argv[0]);
    		exit(errno);
    	}
     
    	// Conversion argument 1 (hexa) en nombre 
    	msg_key=strtoul(argv[1], NULL, 16);
     
    	// Ouverture de la boite si clef valide 
    	if ((msg_id=msgget(msg_key, IPC_ALLOC)) == (-1))
    	{
    		fprintf(stderr, "ligne %u - msgget(0x%08x) - %s\n", __LINE__, msg_key, sys_errlist[errno]);
    		msg_id=strtoul(argv[1], NULL, 10);
    		printf("Clef 0x%08x invalide => Utilisation identifiant %d\n", msg_key, msg_id);
    	}
    	printf("Boite aux lettres 0x%x ouverte - valeur %d\n", msg_key, msg_id);
     
    	// Récuperation info boite 
    	if (msgctl(msg_id, IPC_STAT, &info) == (-1))
    	{
    		fprintf(stderr, "ligne %u - msgctl(%d) - %s\n", __LINE__, msg_id, sys_errlist[errno]);
    		exit(errno);
    	}
    	printf("Boite contient %hu messages (id=%d)\n", info.msg_qnum); 
     
    	// Boucle sur le nombre de messages 
    	for (nb_msg=info.msg_qnum; nb_msg > 0; nb_msg--)
    	{
    		// Récupération du message 
    		status=msgrcv(msg_id, &msg_buf, SZ_MESSAGE , 0, IPC_NOWAIT|MSG_NOERROR);
     
    		// Si récupération impossible mais pas par manque de place 
    		if (status == -1)
    		{
    			// Si erreur n'est pas "plus de message" 
    			if (errno != ENOMSG)
    			{
    				fprintf(stderr, "ligne %u - msgrcv() - %s\n", __LINE__, sys_errlist[errno]);
    				exit(errno);
    			}
    			else
    				break;
    		}
     
    		// Affichage message 
    		printf("\tmessage(type=%d): '", msg_buf.mtype);
    		for (i=0, pt=msg_buf.mcorps; i < status; i++, pt++)
    		{
    			// Si le caractère est imprimable ou est un 'saut de ligne' 
    			if (isprint(*pt) || *pt == '\n')
    				printf("%c", *pt);
    			else
    				// Si le caractère n'est pas nul 
    				if (*pt != 0)
    					printf("(0x%02x) ", *pt);
    		}
     
    		printf("' - status %d\n", status);
     
    		// Renvoi message 
    		status=msgsnd(msg_id, &msg_buf, status, IPC_NOWAIT);
    		if (status == -1)
    			fprintf(stderr, "ligne %u - msgsnd(%d) - %s\n", __LINE__, msg_id, sys_errlist[errno]);
    	}
     
    	// Fin du programme 
    	printf("Fin des messages (0x%x)\n", msg_key);
    }
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  3. #3
    Membre régulier
    Inscrit en
    Décembre 2003
    Messages
    99
    Détails du profil
    Informations forums :
    Inscription : Décembre 2003
    Messages : 99
    Points : 82
    Points
    82
    Par défaut
    Bonjour,

    Effectivement j'avais eu une idée du même style. Comme les priorités sont gérées par les files POSIX, je pensais mettre tous les messages lors de la soumission en priorité 0, extraire le message, puis si il y a un pb, remettre le message dans la file avec une priorité 1. Du coup, il aurait été artificiellement mis en tête de file.

    Mais bon, je trouve pas ça terrible.Par ailleurs, j'ai cru comprendre que le nombre de messages dans une file POSIX était limité à 10 et que la dépose était bloquée tant que la file était à 10.

    Donc,je vais rester sur mon fichier et mes pread,pwrite et semaphore :-).

    A moins qu'il existe une lib de gestion de files persistantes ?

    Merci.
    "Il n'existe que deux choses infinies, l'univers et la bêtise humaine... mais pour l'univers, je n'ai pas de certitude absolue." A. Einstein

  4. #4
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par chicorico Voir le message
    Effectivement j'avais eu une idée du même style. Comme les priorités sont gérées par les files POSIX, je pensais mettre tous les messages lors de la soumission en priorité 0, extraire le message, puis si il y a un pb, remettre le message dans la file avec une priorité 1. Du coup, il aurait été artificiellement mis en tête de file.
    La valeur "mtype" ne sert pas à gérer la priorité mais le type du message (bon bien entendu on peut utiliser ce type pour créer un semblant de priorité mais c'est pas son but initial). Le premier message inséré se met en tête de file et le second se met juste derrière quelle que soit la valeur de ce champ.
    Toutefois, si le premier a une valeur "1" et le second a une valeur "2" alors demander un message de type "2" te donnera alors le second bien qu'il y en ait un devant.
    Et on ne peut pas le mettre à 0 car la valeur 0 sert justement à demander à msgrcv() le premier message quel que soit son type.

    Citation Envoyé par chicorico Voir le message
    Par ailleurs, j'ai cru comprendre que le nombre de messages dans une file POSIX était limité à 10 et que la dépose était bloquée tant que la file était à 10.
    Ca je sais pas mais ce serait étonnant...

    Citation Envoyé par chicorico Voir le message
    A moins qu'il existe une lib de gestion de files persistantes ?
    Ben oui, les msq !!!

    Merci.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  5. #5
    Membre régulier
    Inscrit en
    Décembre 2003
    Messages
    99
    Détails du profil
    Informations forums :
    Inscription : Décembre 2003
    Messages : 99
    Points : 82
    Points
    82
    Par défaut
    Bonjour,

    Je parles de file de messages POSIX(mq_overview), pas de file de messages Système V.
    Les files POSIX (mqueue.h) ont une fonction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    mqd_t mq_receive(mqd_t mqdes, char *msg_ptr,
                          size_t msg_len, unsigned *msg_prio);
    Cette fonction gère les priorités, elle prend d'abord les message en priorité haute.
    Extrait du man :
    mq_receive() removes the oldest message with the highest priority from the message queue.
    D'où mon idée de jouer sur les priorités pour mettre en tête de file les messages traités en erreurs.

    Concernant la fonction de dépose, elle gère aussi les priorités. Mais le man dit :

    If the message queue is already full (i.e., the number of messages on the queue equals the queue’s mq_maxmsg attribute), then, by
    default, mq_send() blocks until sufficient space becomes available to allow the message to be queued, or until the call is inter-
    rupted by a signal handler
    Et le man de mq_overview :

    /proc/sys/fs/mqueue/msg_max
    This file can be used to view and change the ceiling value for the maximum number of messages in a queue. This value acts
    as a ceiling on the attr->mq_maxmsg argument given to mq_open(3). The default and minimum value for msg_max is 10; the
    upper limit is HARD_MAX: (131072 / sizeof(void *)) (32768 on Linux/86). This limit is ignored for privileged processes
    (CAP_SYS_RESOURCE), but the HARD_MAX ceiling is nevertheless imposed.
    Donc en fait on peut allez jusqu'à 32768, c'est pas ouf.Il me faudrait au moins 200000 messages car le consommateur de la file peut se retrouver bloquer si le traitement prend plus de temps. Le producteur lui par contre enpile très vite. Devant garantir l'ordre de traitement des messages, je ne peux avoir plus d'1 consommateur.

    Je viens aussi de voir, que la file n'est pas persistante en cas de ré-demarrage(plantage) de la machine :-(.

    Je crois que je vais rester sur mes lock et mes sémaphores

    Je ré-itère donc ma question existe-t-il à votre connaissance une librairie de file de messages réellement persistante et dont la taille peut-être plus grande que 32768 ?

    Merci.
    "Il n'existe que deux choses infinies, l'univers et la bêtise humaine... mais pour l'univers, je n'ai pas de certitude absolue." A. Einstein

  6. #6
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par chicorico Voir le message
    Je viens aussi de voir, que la file n'est pas persistante en cas de ré-demarrage(plantage) de la machine :-(.
    Normal, c'est géré par un processus daemon...

    Citation Envoyé par chicorico Voir le message
    Je crois que je vais rester sur mes lock et mes sémaphores
    Eux-aussi sont perdus au redémarrage...

    Citation Envoyé par chicorico Voir le message
    Je ré-itère donc ma question existe-t-il à votre connaissance une librairie de file de messages réellement persistante et dont la taille peut-être plus grande que 32768 ?
    Non pas à ma connaissance. Peut-être en passant par un fichier disque mais faudra passer par les fonctions bas niveau (open/read/write/close) et non fopen/fclose pour être sûr que l'écriture se fasse au moment où l'ordre est donné. Et peut-être passer par les locks pour garantir l'ordonnancement et donc ça va être lourd...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  7. #7
    Membre régulier
    Inscrit en
    Décembre 2003
    Messages
    99
    Détails du profil
    Informations forums :
    Inscription : Décembre 2003
    Messages : 99
    Points : 82
    Points
    82
    Par défaut
    Bonjour,

    Non pas à ma connaissance. Peut-être en passant par un fichier disque mais faudra passer par les fonctions bas niveau (open/read/write/close) et non fopen/fclose pour être sûr que l'écriture se fasse au moment où l'ordre est donné. Et peut-être passer par les locks pour garantir l'ordonnancement et donc ça va être lourd...
    Justement c'est ce que j'ai fait et c'est pourquoi je disais rester avec mes locks et sémaphores, c'est parce que je passe actuellement par un fichier sur le disque avec des pread , pwrite et des open. Donc la file reste persistante même après ré-demmarage et l'ordre d'écriture/lecture est garantie.
    Comme tu dis c'est lourd surtout les locks et les sémaphores d'où mon post d'avoir quelque chose de standard et de "safe".

    En gros, le producteur ouvre le fichier en "append" via open, le lock, fait des pwrite des messages, le ferme via close, unlock le fichier, post une semaphore(sem_post) pour réveiller le consommateur.
    Le consommateur attend le reveil via sem_wait, lit tout le fichier en mémoire(pread), et traite tous les messages.En cas d'erreur, il lock le fichier, et recopie les données traités dans le fichier (lecture+écriture), rend le lock et se remet en écoute.

    C'est un peu lourd :-). D'ailleurs je me demande si un select ne serait pas possible sur mon fichier, puisque au final open retourne un "file descriptor" ?
    "Il n'existe que deux choses infinies, l'univers et la bêtise humaine... mais pour l'univers, je n'ai pas de certitude absolue." A. Einstein

Discussions similaires

  1. Posix Message Queue vs Win32 Named Pipe
    Par Khan34 dans le forum C++
    Réponses: 2
    Dernier message: 06/03/2012, 12h29
  2. [XL-2007] Test si fichier protégé en lecture (sans ouverture dudit fichier)
    Par chadom dans le forum Macros et VBA Excel
    Réponses: 1
    Dernier message: 16/07/2010, 11h08
  3. Convertir SWf en EXE (lecture sans flashplayer)
    Par Invité dans le forum Flash
    Réponses: 5
    Dernier message: 07/04/2010, 14h51
  4. [AD]Accès en lecture sans pouvoir copier ?
    Par kimz dans le forum Windows Serveur
    Réponses: 0
    Dernier message: 09/05/2009, 11h15
  5. liste,formulaire lecture sans bouton submit
    Par BernardT dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 02/06/2006, 07h43

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo