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

Linux Discussion :

Événements sous Linux


Sujet :

Linux

  1. #1
    Membre extrêmement actif
    Avatar de Madmac
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2004
    Messages
    1 685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Alimentation

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 685
    Points : 1 376
    Points
    1 376
    Billets dans le blog
    7
    Par défaut Événements sous Linux
    J'ai surtout programmé sur Mac. Comme tous les intercommunications entre les l'applis passaient par les AppleEvents. Je suis un peu (beaucoup) comme un poisson hors de l'eau pour ce qui est intercommunication entre applis sur Linux!

    J'aimerai testé un modéle d'applis avec d'autre événement. D'après ce que j'ai compris, il y aurait une queue pour le clavier, une queue pour la souris et une queue pour XWindow.

    Comment fait-on pour faire une queue qui est accessible aux applis?

    Un résumé ou un renvoi sur le bon document serait apprécié!

  2. #2
    Membre à l'essai
    Profil pro
    Inscrit en
    Juin 2004
    Messages
    16
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juin 2004
    Messages : 16
    Points : 15
    Points
    15
    Par défaut
    Bonjour Madmac,

    Sous linux, il existe plusieurs techniques pour faire communiquer des processus entre eux. Les tubes, les FIFO et les IPC (Inter Communication Process). Comme j'ai pas trouvé en recherchant, voici un petit résumé sur ces techniques. A noter que je n'ai jamais programmé avec les tubes ou les FIFO, par contre les ipc, un peu.

    Les TUBES. Un tube est un flux de données à sens uniques entre des processus : toutes données écrites par un processus vers le tube sont acheminées par le noyau vers un autre processus, qui peut ainsi les lire. Les commandes shell (dans le terminal) |, > et < permettent cet acheminement. De même que les commandes systèmes (dans un programme C, C++,...) pipe(), read(), write() et close(). Les tubes sont à sens unique, il en faudra deux pour relier deux processus...

    Les FIFO. Depuis la sortie de System V Release 3, les FIFO sont implémentés en tant qu'objets fullduplex (bidirectionnels). Les fichiers FIFO comportent un inode de disque (et donc un nom de fichier accessible par le programme), mais n'utilisent pas de blocs de données. Les données sont stockées dans des tampons du noyau, ce qui est plus performant que d'utiliser des fichiers temporaires.... Un processus créer un FIFO en émettant l'appel système mknod() (qui peut servir à créer presque n'importe quel type fichier, sauf répertoires et sockets). Toutefois mkfifo() existe depuis System V Release 4. Les appels systèmes open(), read(), write() et close() peuvent accèder au FIFO une fois qu'il est créé.

    Les IPC : ces techniques permettent à des processus de partager de la mémoire partagée, de se synchroniser grâce à des sémaphores et de s'échanger des messages. Voici comment utiliser la mémoire partagée :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    #include<sys/types.h>
    #include<sys/ipc.h>
    #include<sys/shm.h>
    int shmget(key_t key, int size, int shmflg);
    char *shmat(int shmid, car *shmadrr, int shmflg);
    int shmdt(chmadrr);
    int shmctl(int shmid, int cmd, struct shmid_ds *buf);
    shmget() donne l'identifiant du segment ayant la clef key (Pour constituer une clef, utiliser key_t ftok(char *pathname, char project)). Un nouveau segment de taille size est crée si key est IPC_PRIVATE, ou bien si les indicateurs de shmflg conntiennent IPC_CREAT. Combinées, les options IPC_EXCL | IPC_CRET indiquent que le segment ne doit pas exister auparavant. les bits de poids faible de shmflg indiquent les droits d'accès.

    shmat() attache le segment shmid en mémoire, avec les droits spécifiées dans shmflag (SHM_R, SHM_W, SHM_RDONLY). shmadrr précise où ce segment doit être situé dans l'espace mémoire (la valeur NULL demande un emplacement automatique). shmat() renvoie l'adresse où le segment a été placé.

    shmdt() sert à détacher le segmentsi on ne l'utilise plus.

    shmctl() permet de paramétrer ou de supprimer un segment partagé.

    Code : 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
     
    // extraits choisis d'un simulateur d'ordonnanceurs
    int id, err;
    struct bcp * b;
    // Création du segment de mémoire partagée
    id = shmget( ftok( ".", '@'), sizeof( struct bcp )+10000, IPC_CREAT | IPC_EXCL | 0777 );
    if ( id < 0 )
    {
    	printf("erreur shmget().\n");
    	exit( -1 );
    }
    // Attribution de la mémoire partagée à la structure de données.
    b = (struct bcp *)shmat( id, 0, SHM_W );
    if ( b == NULL )
    {
    	printf("erreur, shmat() == null.");
    	exit( -1 );
    }
    // Détachement du segment de la structure.
    err = shmctl( bcp->id, IPC_RMID, NULL );
    if (err==-1)
    	err = shmdt(bcp);
    	printf("kill bcp err = %d.\n", err );
    La commande ipcs affiche des informations sur les segments/sémaphores/messages qui existent ; la commande ipcrm les supprime.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    [bnet@localhost bnet]$ ipcs
     
    ------ Segment de mémoire partagé --------
    clé        shmid      propriétaire perms      octets     nattch     états
    0x00000000 32768      bnet      600        393216     2          dest
     
    ------ Tableaux de sémaphores --------
    clé        semid      propriétaire perms      nsems
     
    ------ Queues de messages --------
    clé        msqid      propriétaire perms      octets-utilisés messages
    Synchroniser des processus :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    #include<sys/types.h>
    #include<sys/ipc.h>
    #include<sys/sem.h>
    int semget(key_t key, int nsems, int semflg);
    int semop(int semid, struct sembuf *sops, unsigned nsops);
    int semctl(int semid, int semnum, int cmd, union semun arg);
    La fonction semget() demande à travailler sur le sémaphore généralisé identifié par la clef key (cf. ci-dessus), et qui contient nsems sémaphores individuels. Un nouveau sémaphore est créé, avec les droits données par les 9 bits de poids faible de semflg, si key est IPC_PRIVATE, ou si semflg contient IPC_CREAT.
    La fonction semop() agit sur le sémaphore semid en appliquant simultanément à plusieurs sémaphores individuels les actions décrites dans les nsops premiers éléments du tableau sops.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    struct sembuf {
    ...
    short sem_num;
    short sem_op;
    short sem_flg;
    }
    sem_num est le numéro du sémaphore individuel sur lequel porte l'opération
    sem_op est un entier destiné (sauf s'il est nul) à être ajouté à la valeur courante semval du sémaphore. L'opération se bloque si sem_op + semval < 0. Cas particulier : si sem_op est 0, l'opération est bloquée tant que semval est non nul. Rq : les valeurs des sémaphores ne sont mises à jour que lorsqu'aucun d'eux n'est bloqué.
    La fonction semctl permet de réaliser diverses opérations sur les sémaphores, selon la commande demandée. En particulier, on peut fixer le n-ième sémaphore à la valeur val en faisant semctl(sem, n, SETVAL, val);


    Code : 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
     
    #include <unistd.h>
    #include <sys/time.h>
    #include <sys/sem.h>
    #include <signal.h>
    #include <errno.h>
    #include <stdio.h>
     
    // Opération V ( +1 ) sur le 1er sémaphore de l'ensemble d'id sem.
    void V( int sem )
    {
    	struct sembuf buf;
    	buf.sem_num = 0;
    	buf.sem_op = 1;
    	buf.sem_flg = 0;
    //	printf("< V(%d) dans pid %d . \n", sem, getpid() );
    	semop( sem, &buf, 1 );
    //	printf("V(%d) dans pid %d. > \n", sem, getpid() );
    }
     
    // Opération P ( -1 ) sur le 1er sémaphore de l'ensemble d'id sem.
    void P( int sem )
    {
    	struct sembuf buf;
    	buf.sem_num = 0;
    	buf.sem_op = -1;
    	buf.sem_flg = 0;
    //	printf("< P(%d) dans pid %d . \n", sem, getpid() );
    	semop( sem, &buf, 1 );
    //	printf("P(%d) dans pid %d. > \n", sem, getpid() );
    }
     
    int new_semaphore( char id )
    {
    	int _id, err;
    //	printf("semaphore %d en création.\n", id );
    	_id = semget( ftok( ".", id ), 1, IPC_CREAT | IPC_EXCL | 0777 );
    	if ( _id == -1 )
    	{
    		printf("semget id : %c.\n", id );
    		perror( "semget()" );
    		exit( -1 );
    		return -1;
    	}
    	err = semctl( _id, 0, SETVAL, 1 );
    	if ( err == -1 )
    	{
    		perror( "semclt(SETVAL)" );
    		exit( -1 );
    		return -1;
    	}
    //	printf("semaphore %d crée ->%d \n", id, _id );
    	return _id;
    }
     
    // détruit l'ensemble de sémaphores identifié par sema.
    void kill_semaphore( int sema )
    {
    //	printf("kill semaphore %d.\n", sema );
    	semctl( sema, 0, IPC_RMID, NULL );
    }
    Files de messages : ce mécanismes permet l'échange de messages par des processus. Chaque message possède un corps de longueur variable, et un type (entier strictement positif) qui peut servir à préciser la nature des informations contenues dans le corps. Au moment de la réception on peut choisir de sélectionner les messages d'un type donné.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    #include<sys/types.h>
    #include<sys/ipc.h>
    #include<sys/msg.h>
    int msgget(key_t key, int msgflg);
    int msgsnd(int msqid, struct *msgp, int msgflg);
    int msgrcv(int msqid, struct *msgp, int msgsz, int msgtyp, int msgflg);
    int msgctl(int msqid, int cmd, struct msqid_ds *buf);
    msgget() demande l'accès à (ou la création de) la file de message avec la clef key et retourne la valeur de l'identificateur de file.
    msgsnd() envoie un message dans la file msqid. Le corps de ce message contient msgsz octets. Il est placé, précédé par le type, dans le tampon pointé par msgp.
    Ce tampon est de la forme :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    struct msgbuf {
    long mtype;
    char mtext[..];
    }
    msgrcv() lit dans la file un message d'un type donné (si type>0) ou indifférent (si type==0), et le place dans le tampon pointé par msgp. La taille du corps ne pourra excéder msgsz octets, sinon il sera tronqué. Renvoie la taille du corps du message. Là par contre, pas d'exemple.

    En espérant que tu y trouvera ton bonheur, je te souhaite bon courage.

    ++

  3. #3
    Membre extrêmement actif
    Avatar de Madmac
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2004
    Messages
    1 685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Alimentation

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 685
    Points : 1 376
    Points
    1 376
    Billets dans le blog
    7
    Par défaut
    Merci Benetrixman

    C'est beaucoup plus que j'en espérais! Je vais pouvoir m'occuper pour un moment avec ce projet.
    Mais le potentiel en vaut la peine. Il ne manque à Linux que quelles bonnes idées, pour en faire un système qui peut compétionné avec celui du Mac, sans avoir ses faiblesses....

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Série] Accès au port série sous linux
    Par ghost dans le forum Entrée/Sortie
    Réponses: 10
    Dernier message: 10/10/2007, 10h43
  2. Comment désinstaller MySQL sous linux
    Par nahmsath dans le forum Installation
    Réponses: 5
    Dernier message: 18/09/2007, 10h46
  3. installer jbuilder7 sous linux
    Par rtlinfo34 dans le forum JBuilder
    Réponses: 5
    Dernier message: 30/10/2002, 19h16
  4. Réponses: 2
    Dernier message: 25/10/2002, 22h19
  5. Je ne peux établir une connexion cliente sous Linux.
    Par Anonymous dans le forum CORBA
    Réponses: 5
    Dernier message: 16/04/2002, 15h57

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