Page suivante Page précédente Table des matières

Le Linux Serial Programming HOWTO

par Peter H. Baumann, mailto:Peter.Bauman= n@dlr.de" NAME=3D"Peter.Baumann@dlr.de">
Adaptation fran=E7aise Etienne BERNARD mailto:eb@via.ec= p.fr" NAME=3D"eb@via.ecp.fr">

v1.0, 22 janvier 1998


Ce document d=E9crit comment programmer sous Linux la communication avec de= s p=E9riph=E9riques sur port s=E9rie.
=20

1. Introduction

  • 1.1 Copyright
  • 1.2 Nouvelles versions de ce document.
  • 1.3 Commentaires

    2. D=E9marrage

    -- dans le r=E9pertoire des= exemples) pour transmettre des caract=E8res =E0 votre machine Linux. M= initerm est tr=E8s simple =E0 compiler et transmettra toute entr=E9e clavi= er directement sur le port s=E9rie. Vous n'= avez qu'=E0 adapter la commande #define MODEMDEVICE "/dev/ttyS0" = =E0 vos besoins. Mettez ttyS0 pour COM1, ttyS1 for COM2, = etc... Il est essentiel, pour les tests, que tous les caract=E8res soi= ent transmis bruts (sans traitements= ) au travers de la ligne s=E9rie. Pour tester votre connexion, d=E9marrez <= TT/miniterm/ sur les deux ordinateurs et taper au clavier. Les caract=E8res= =E9crit sur un ordinateur devraient appara=EEtre sur l'autre ordinateur, e= t vice versa. L'entr=E9e clavier sera =E9ga= lement recopi=E9e sur l'=E9cran de l'ordinateur local.

    Pour fabriquer un c=E2ble null-modem, pour devez croiser les lignes TxD (M/transmit/) et RxD (receive). Pour une description du c=E2ble, r=E9f= =E9rez vous =E0 la section 7 du Serial-HOWTO.

    Il est =E9galement possible de faire cet essai avec uniquement un seul ordi= nateur, si vous disposez de deux ports s=E9rie. Vous pouvez lancez deux /miniterm/s sur deux consoles virtuelles. Si vous lib=E9rez un port s=E9rie= en d=E9connectant la souris, n'oubliez= pas de rediriger /dev/mouse si ce fichier existe. Si vous utilise= z une carte s=E9rie =E0 ports multiples, soyez s=FBr de la configurer corre= ctement. La mienne n'=E9tait pas correctement configur=E9e, et tout fonctio= nnait correctement lorsque je testais s= ur mon ordinateur. Lorsque je l'ai connect=E9 =E0 un autre, le port a comme= nc=E9 =E0 perdre des caract=E8res. L'ex=E9cution de deux programmes sur un = seul ordinateur n'est pas totalement asynchrone.

  • 2.2 Configuration des ports

    2.2 Configuration des ports

    Les p=E9riph=E9riques /dev/ttyS* sont destin=E9s =E0 connecter les= terminaux =E0 votre machine Linux, et sont configur=E9s pour cet usage apr= =E8s le d=E9marrage. Vous devez vous en souvenir lorsque vous programmez la= communication avec un p=E9riph=E9rique autre. Pa= r exemple, les ports sont configur=E9s pour afficher les caract=E8res envoy= =E9s vers lui-m=EAme, ce qui normalement doit =EAtre chang=E9 pour la trans= mission de donn=E9es.

    Tous les param=E8tres peuvent =EAtre facilement configur=E9 depuis un progr= amme. La configuration est stock=E9e dans une structure de type struct = termios, qui est d=E9finie dans <asm/termbits.h> :

    #define NCCS 19
    struct termios {
            tcflag_t c_iflag;               /* Modes d'entr=E9e */
            tcflag_t c_oflag;               /* Modes de sortie */
            tcflag_t c_cflag;               /* Modes de contr=F4le */
            tcflag_t c_lflag;               /* Modes locaux */
            cc_t c_line;                    /* Discipline de ligne */
            cc_t c_cc[NCCS];                /* Caract=E8res de contr=F4le */
    };
    

    Ce fichier inclus =E9galement la d=E9finition des constantes. Tous les mode= s d'entr=E9e dans c_iflag prennent en charge le traitement de l'en= tr=E9e, ce qui signifie que les caract=E8res envoy=E9s depuis le p=E9riph= =E9rique peuvent =EAtre trait=E9s avant d'=EAtre lu p= ar read. De la m=EAme fa=E7on, c_oflags se chargent du tr= aitement en sortie. c_cflag contient les param=E8tres du port, com= me la vitesse, le nombre de bits par caract=E8re, les bits d'arr=EAt, etc..= . Les modes locaux, stock=E9s dans c_= lflag d=E9terminent si les caract=E8res sont imprim=E9s, si des signau= x sont envoy=E9s =E0 votre programme, etc... Enfin, le tableau c_cc > d=E9finit les caract=E8res de contr=F4le pour la fin de fichier, le carac= t=E8re stop, etc... Les valeurs par d=E9faut pour= les caract=E8res de contr=F4le sont d=E9finies dans <asm/termios.h&= gt;. Les modes possibles sont d=E9crits dans la page de manuel de = termios(3). La structure termios contient un champ c_line= (discipline de ligne), qui n'es= t pas utilis=E9 sur les syst=E8mes conformes =E0 POSIX.

  • 2.3 Fa=E7ons de lire sur les p=E9riph=E9riques s=E9rie

    2.3 Fa=E7ons de lire sur les p=E9riph=E9riques s=E9rie

    Voici trois fa=E7ons de lire sur les p=E9riph=E9riques s=E9rie. Le moyen ap= propri=E9 doit =EAtre choisi pour chaque application. Lorsque cela est poss= ible, ne lisez pas les cha=EEnes caract=E8re par caract=E8re. Lorsque j'uti= lisais ce moyen, je perdais des caract=E8res, alo= rs qu'un read sur la cha=EEne compl=E8te ne donnait aucune erreur.

    Entr=E9e canonique

    C'est le mode de fonctionnement normal pour les terminaux, mais peut =E9gal= ement =EAtre utilis=E9 pour communiquer avec d'autres p=E9riph=E9riques. To= utes les entr=E9es sont trait=E9es lignes par lignes, ce qui signifie qu'un= read ne renverra qu'une ligne com= pl=E8te. Une ligne est termin=E9e par d=E9faut avec un caract=E8re NL</= TT> (ACII LF), une fin de fichier, ou un caract=E8re de fin de lig= ne. Un CR (le caract=E8re de fin de ligne par d=E9faut de DOS et W= indows) ne terminera pas une ligne, avec le= s param=E8tres par d=E9faut.

    L'entr=E9e canonique peut =E9galement prendre en charge le caract=E8re eras= e, d'effacement de mot, et de r=E9affichage, la traduction de CR v= ers NL, etc...

    Entr=E9e non canonique

    L'entr=E9e non canonique va prendre en charge un nombre fix=E9 de caract=E8= re par lecture, et autorise l'utilisation d'un compteur de temps pour les c= aract=E8res. Ce mode doit =EAtre utilis=E9 si votre application lira toujou= rs un nombre fix=E9 de caract=E8res, ou si le= p=E9riph=E9rique connect=E9 envoit les caract=E8res par paquet.

    Entr=E9e asynchrone

    Les deux modes ci-dessus peut =EAtre utilis=E9 en mode synchrone ou asynchr= one. Le mode synchrone est le mode par d=E9faut, pour lequel un appel =E0 <= TT>read sera bloquant, jusqu'=E0 ce que la lecture soit satisfaite. En= mode asynchrone, un appel =E0 read</= TT> retournera imm=E9diatement et lancera un signal au programme appelant e= n fin de transfert. Ce signal peut =EAtre re=E7u par un gestionnaire de sig= nal.

    Attente d'entr=E9e depuis de multiples sources

    Cela ne constitue pas un mode d'entr=E9e diff=E9rent, mais peut s'av=E9rer = =EAtre utile, si vous prenez en charge des p=E9riph=E9riques multiples. Dan= s mon application, je traitais l'entr=E9e depuis une socket TCP/IP et depui= s une connexion s=E9rie sur un autre ordinate= ur quasiment en m=EAme temps. L'exemple de programme donn=E9 plus loin atte= ndra des caract=E8res en entr=E9e depuis deux sources. Si des donn=E9es sur= l'une des sources deviennent disponibles, elles seront trait=E9es, et le p= rogramme attendra de nouvelles donn=E9es.

    L'approche pr=E9sent=E9e plus loin semble plut=F4t complexe, mais il est im= portant que vous vous rappeliez que Linux est un syst=E8me multi-t=E2che. L= 'appel syst=E8me select ne charge pas le processeur lorsqu'il atte= nd des donn=E9es, alors que le fait de fair= e une boucle jusqu'=E0 ce que des caract=E8res deviennent disponibles ralen= tirait les autres processus.

    3. Exemples de programmes

    ).

    R=E9f=E9rez-vous aux commentaires dans le code source pour l'explication de= s diff=E9rents modes d'entr=E9e. J'esp=E8re que le code est compr=E9hensibl= e. L'exemple sur l'entr=E9e canonique est la plus comment=E9e, les autres e= xemples sont comment=E9s uniquement lorsqu'ils=20= diff=E8rent, afin de signaler les diff=E9rences.

    Les descriptions ne sont pas compl=E8tes, mais je vous encourage =E0 modifi= er les exemples pour obtenir la solution la plus int=E9ressante pour votre = application.

    N'oubliez pas de donner les droits corrects aux ports s=E9rie (par exemple,= chmod a+rw /dev/ttyS1) !

    • 3.1 Traitement canonique

      3.1 Traitement canonique

      #include <sys/types.h>
      #include <sys/stat.h>
      #include <fcntl.h>
      #include <termios.h>
      #include <stdio.h>
      
      /* les valeurs pour la vitesse, baudrate, sont d=E9finies dans <asm/termbit=
      s.h>, qui est inclus
      dans <termios.h> */
      #define BAUDRATE B38400           =20
      /* changez cette d=E9finition pour utiliser le port correct */
      #define MODEMDEVICE "/dev/ttyS1"
      #define _POSIX_SOURCE 1 /* code source conforme =E0 POSIX */
      
      #define FALSE 0
      #define TRUE 1
      
      volatile int STOP=3DFALSE;=20
      
      main()
      {
        int fd,c, res;
        struct termios oldtio,newtio;
        char buf[255];
      /*=20
        On ouvre le p=E9riph=E9rique du modem en lecture/=E9criture, et pas comme
        terminal de contr=F4le, puisque nous ne voulons pas =EAtre termin=E9 si l=
      'on
        re=E7oit un caract=E8re CTRL-C.
      */
       fd =3D open(MODEMDEVICE, O_RDWR | O_NOCTTY );=20
       if (fd <0) {perror(MODEMDEVICE); exit(-1); }
      
       tcgetattr(fd,&oldtio); /* sauvegarde de la configuration courante */
       bzero(&newtio, sizeof(newtio)); /* on initialise la structure =E0 z=E9=
      ro */
      
      /*=20
        BAUDRATE: Affecte la vitesse. vous pouvez =E9galement utiliser cfsetispeed
                  et cfsetospeed.
        CRTSCTS : contr=F4le de flux mat=E9riel (uniquement utilis=E9 si le c=E2b=
      le a
                  les lignes n=E9cessaires. Voir la section 7 du Serial-HOWTO).
        CS8     : 8n1 (8 bits,sans parit=E9, 1 bit d'arr=EAt)
        CLOCAL  : connexion locale, pas de contr=F4le par le modem
        CREAD   : permet la r=E9ception des caract=E8res
      */
       newtio.c_cflag =3D BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
      =20
      /*
        IGNPAR  : ignore les octets ayant une erreur de parit=E9.
        ICRNL   : transforme CR en NL (sinon un CR de l'autre c=F4t=E9 de la ligne
                  ne terminera pas l'entr=E9e).
        sinon, utiliser l'entr=E9e sans traitement (device en mode raw).
      */
       newtio.c_iflag =3D IGNPAR | ICRNL;
      =20
      /*
       Sortie sans traitement (raw).
      */
       newtio.c_oflag =3D 0;
      =20
      /*
        ICANON  : active l'entr=E9e en mode canonique
        d=E9sactive toute fonctionnalit=E9 d'echo, et n'envoit pas de signal au
        programme appelant.
      */
       newtio.c_lflag =3D ICANON;
      =20
      /*=20
        initialise les caract=E8res de contr=F4le.
        les valeurs par d=E9faut peuvent =EAtre trouv=E9es dans
        /usr/include/termios.h, et sont donn=E9es dans les commentaires.
        Elles sont inutiles ici.
      */
       newtio.c_cc[VINTR]    =3D 0;     /* Ctrl-c */=20
       newtio.c_cc[VQUIT]    =3D 0;     /* Ctrl-\ */
       newtio.c_cc[VERASE]   =3D 0;     /* del */
       newtio.c_cc[VKILL]    =3D 0;     /* @ */
       newtio.c_cc[VEOF]     =3D 4;     /* Ctrl-d */
       newtio.c_cc[VTIME]    =3D 0;     /* compteur inter-caract=E8re non utilis=
      =E9 */
       newtio.c_cc[VMIN]     =3D 1;     /* read bloquant jusqu'=E0 l'arriv=E9e d'=
      1 caract=E8re */
       newtio.c_cc[VSWTC]    =3D 0;     /* '\0' */
       newtio.c_cc[VSTART]   =3D 0;     /* Ctrl-q */=20
       newtio.c_cc[VSTOP]    =3D 0;     /* Ctrl-s */
       newtio.c_cc[VSUSP]    =3D 0;     /* Ctrl-z */
       newtio.c_cc[VEOL]     =3D 0;     /* '\0' */
       newtio.c_cc[VREPRINT] =3D 0;     /* Ctrl-r */
       newtio.c_cc[VDISCARD] =3D 0;     /* Ctrl-u */
       newtio.c_cc[VWERASE]  =3D 0;     /* Ctrl-w */
       newtio.c_cc[VLNEXT]   =3D 0;     /* Ctrl-v */
       newtio.c_cc[VEOL2]    =3D 0;     /* '\0' */
      
      /*=20
        =E0 pr=E9sent, on vide la ligne du modem, et on active la configuration
        pour le port
      */
       tcflush(fd, TCIFLUSH);
       tcsetattr(fd,TCSANOW,&newtio);
      
      /*
        la configuration du terminal est faite, =E0 pr=E9sent on traite
        les entr=E9es
        Dans cet exemple, la r=E9ception d'un 'z' en d=E9but de ligne mettra
        fin au programme.
      */
       while (STOP=3D=3DFALSE) {     /* boucle jusqu'=E0 condition de terminaison=
       */
       /* read bloque l'ex=E9cution du programme jusqu'=E0 ce qu'un caract=E8re de
          fin de ligne soit lu, m=EAme si plus de 255 caract=E8res sont saisis.
          Si le nombre de caract=E8res lus est inf=E9rieur au nombre de caract=E8=
      res
          disponibles, des read suivant retourneront les caract=E8res restants.
          res sera positionn=E9 au nombre de caract=E8res effectivement lus */
          res =3D read(fd,buf,255);=20
          buf[res]=3D0;       /* on termine la ligne, pour pouvoir l'afficher */
          printf(":%s:%d\n", buf, res);
          if (buf[0]=3D=3D'z') STOP=3DTRUE;
       }
       /* restaure les anciens param=E8tres du port */
       tcsetattr(fd,TCSANOW,&oldtio);
      }
      

    • 3.2 Entr=E9e non canonique

      3.2 Entr=E9e non canonique

      Dans le mode non canonique, les caract=E8res lus ne sont pas assembl=E9s li= gne par ligne, et ils ne subissent pas de traitement (erase, kill, delete, = etc...). Deux param=E8tres contr=F4lent ce mode : c_cc[VTIME]= positionne le timer de caract=E8r= es, et c_cc[VMIN] indique le nombre minimum de caract=E8res =E0 re= cevoir avant qu'une lecture soit satisfaite.

      Si MIN > 0 et TIME =3D 0, MIN indique le nombre de caract=E8res =E0 rece= voir avant que la lecture soit satisfaite. TIME est =E9gal =E0 z=E9ro, et l= e timer n'est pas utilis=E9.

      Si MIN =3D 0 et TIME > 0, TIME est utilis=E9 comme une valeur de ti= meout. Une lecture est satisfaite lorsqu'un caract=E8re est re=E7u, ou que= la dur=E9e TIME est d=E9pass=E9e (t =3D TIME * 0.1s). Si TIME est d=E9pass= =E9, aucun caract=E8re n'est retourn=E9.

      Si MIN > 0 et TIME > 0, TIME est employ=E9 comme timer entre cha= que caract=E8re. La lecture sera satisfaite si MIN caract=E8res sont re=E7u= s, ou que le timer entre deux caract=E8res d=E9passe TIME. Le time= r est r=E9initialis=E9 =E0 chaque fois qu'un c= aract=E8re est re=E7u, et n'est activ=E9 qu'apr=E8s la r=E9ception du premi= er caract=E8re.

      Si MIN =3D 0 et TIME =3D 0, le retour est imm=E9diat. Le nombre de caract= =E8res disponibles, ou bien le nombre de caract=E8res demand=E9 est retourn= =E9. Selon Antonino (voir le paragraphe sur les participations), vous pouve= z utiliser un fcntl(fd, F_SETFL, FNDELAY)= ; avant la lecture pour obtenir le m=EAme r=E9sultat.

      Vous pouvez tester tous les modes d=E9crit ci-dessus en modifiant newti= o.c_cc[VTIME] et newtio.c_cc[VMIN].

      #include <sys/types.h>
      #include <sys/stat.h>
      #include <fcntl.h>
      #include <termios.h>
      #include <stdio.h>
      
      #define BAUDRATE B38400
      #define MODEMDEVICE "/dev/ttyS1"
      #define _POSIX_SOURCE 1 /* code source conforme =E0 POSIX */
      #define FALSE 0
      #define TRUE 1
      
      volatile int STOP=3DFALSE;=20
      
      main()
      {
        int fd,c, res;
        struct termios oldtio,newtio;
        char buf[255];
      
       fd =3D open(MODEMDEVICE, O_RDWR | O_NOCTTY );=20
       if (fd <0) {perror(MODEMDEVICE); exit(-1); }
      
       tcgetattr(fd,&oldtio); /* sauvegarde de la configuration courante */
      
       bzero(&newtio, sizeof(newtio));
       newtio.c_cflag =3D BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
       newtio.c_iflag =3D IGNPAR;
       newtio.c_oflag =3D 0;
      
       /* positionne le mode de lecture (non canonique, sans echo, ...) */
       newtio.c_lflag =3D 0;
      =20
       newtio.c_cc[VTIME]    =3D 0;   /* timer inter-caract=E8res non utilis=E9 */
       newtio.c_cc[VMIN]     =3D 5;   /* read bloquant jusqu'=E0 ce que 5 */
                                    /* caract=E8res soient lus */
       tcflush(fd, TCIFLUSH);
       tcsetattr(fd,TCSANOW,&newtio);
      
      
       while (STOP=3D=3DFALSE) {       /* boucle de lecture */
         res =3D read(fd,buf,255);   /* retourne apr=E8s lecture 5 caract=E8res */
         buf[res]=3D0;               /* pour pouvoir les imprimer... */
         printf(":%s:%d\n", buf, res);
         if (buf[0]=3D=3D'z') STOP=3DTRUE;
       }
       tcsetattr(fd,TCSANOW,&oldtio);
      }
      

    • 3.3 Lecture asynchrone

      3.3 Lecture asynchrone

      #include <termios.h>
      #include <stdio.h>
      #include <unistd.h>
      #include <fcntl.h>
      #include <sys/signal.h>
      #include <sys/types.h>
      
      #define BAUDRATE B38400
      #define MODEMDEVICE "/dev/ttyS1"
      #define _POSIX_SOURCE 1 /* code source conforme =E0 POSIX */
      #define FALSE 0
      #define TRUE 1
      
      volatile int STOP=3DFALSE;=20
      
      void signal_handler_IO (int status);   /* le gestionnaire de signal */
      int wait_flag=3DTRUE;              /* TRUE tant que re=E7u aucun signal */
      
      main()
      {
        int fd,c, res;
        struct termios oldtio,newtio;
        struct sigaction saio;        /* d=E9finition de l'action du signal */
        char buf[255];
      
        /* ouvre le port en mon non-bloquant (read retourne imm=E9diatement) */
        fd =3D open(MODEMDEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
        if (fd <0) {perror(MODEMDEVICE); exit(-1); }
      
        /* installe le gestionnaire de signal avant de passer le port en
           mode asynchrone */
        saio.sa_handler =3D signal_handler_IO;
        saio.sa_mask =3D 0;
        saio.sa_flags =3D 0;
        saio.sa_restorer =3D NULL;
        sigaction(SIGIO,&saio,NULL);
       =20
        /* permet au processus de recevoir un SIGIO */
        fcntl(fd, F_SETOWN, getpid());
        /* rend le descripteur de fichier asynchrone (la page de manuel
           indique que seuls O_APPEND et O_NONBLOCK fonctionnent avec
           F_SETFL...) */
        fcntl(fd, F_SETFL, FASYNC);
      
        tcgetattr(fd,&oldtio); /* sauvegarde de la configuration courante */
        /* positionne les nouvelles valeurs pour lecture canonique */
        newtio.c_cflag =3D BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
        newtio.c_iflag =3D IGNPAR | ICRNL;
        newtio.c_oflag =3D 0;
        newtio.c_lflag =3D ICANON;
        newtio.c_cc[VMIN]=3D1;
        newtio.c_cc[VTIME]=3D0;
        tcflush(fd, TCIFLUSH);
        tcsetattr(fd,TCSANOW,&newtio);
      =20
        /* on boucle en attente de lecture. g=E9n=E9ralement, on r=E9alise
           des traitements =E0 l'int=E9rieur de la boucle */
        while (STOP=3D=3DFALSE) {
          printf(".\n");usleep(100000);
          /* wait_flag =3D FALSE apr=E8s r=E9ception de SIGIO. Des donn=E9es sont
             disponibles et peuvent =EAtre lues */
          if (wait_flag=3D=3DFALSE) {=20
            res =3D read(fd,buf,255);
            buf[res]=3D0;
            printf(":%s:%d\n", buf, res);
            if (res=3D=3D1) STOP=3DTRUE; /* on arr=EAte la boucle si on lit une
                                      ligne seule */
            wait_flag =3D TRUE;      /* on attend de nouvelles donn=E9es */
          }
        }
        /* restaure les anciens param=E8tres du port */
        tcsetattr(fd,TCSANOW,&oldtio);
      }
      
      /***************************************************************************
      * gestionnaire de signal. Positionne wait_flag =E0 FALSE, pour indiquer =E0=
          *
      * la boucle ci-dessus que des caract=E8res ont =E9t=E9 re=E7us.            =
              *
      ***************************************************************************/
      
      void signal_handler_IO (int status)
      {
        printf("r=E9ception du signal SIGIO.\n);
        wait_flag =3D FALSE;
      }
      

    • 3.4 Multiplexage en lecture

      3.4 Multiplexage en lecture

      Cette section est r=E9duite au minimum, et n'est l=E0 que pour vous guider.= Le code source d'exemple pr=E9sent=E9 est donc r=E9duit au strict minimum.= Il ne fonctionnera pas seulement avec des ports s=E9rie, mais avec n'impor= te quel ensemble de descripteurs de fichi= ers.

      L'appel syst=E8me select et les macros qui lui sont attach=E9es utilisent u= n fd_set. C'est un tableau de bits, qui dispose d'un bit pour chaq= ue descripteur de fichier valide. select accepte un fd_set ayant = les bits positionn=E9s pour les des= cripteurs de fichiers qui conviennent, et retourne un fd_set, dans leq= uel les bits des descripteurs de fichier o=F9 une lecture, une =E9criture o= u une exception sont positionn=E9s. Toutes les manipulations de fd_set<= /TT> sont faites avec les macros fo= urnies. Reportez vous =E9galement =E0 la page de manuel de select(2) T>.

      #include <sys/time.h>
      #include <sys/types.h>
      #include <unistd.h>
      
      main()
      {
         int    fd1, fd2;  /* entr=E9es 1 et 2 */
         fd_set readfs;    /* ensemble de descripteurs */
         int    maxfd;     /* nombre max des descripteurs utilis=E9s */
         int    loop=3D1;    /* boucle tant que TRUE */
      
         /* open_input_source ouvre un p=E9riph=E9rique, configure le port
            correctement, et retourne un descripteur de fichier. */
         fd1 =3D open_input_source("/dev/ttyS1");   /* COM2 */
         if (fd1<0) exit(0);
         fd2 =3D open_input_source("/dev/ttyS2");   /* COM3 */
         if (fd2<0) exit(0);
         maxfd =3D MAX (fd1, fd2)+1; /* num=E9ro maximum du bit =E0 tester */
      
         /* boucle d'entr=E9e */
         while (loop) {
           FD_SET(fd1, &readfs);  /* test pour la source 1 */
           FD_SET(fd2, &readfs);  /* test pour la source 2 */
           /* on bloque jusqu'=E0 ce que des caract=E8res soient
              disponibles en lecture */
           select(maxfd, &readfs, NULL, NULL, NULL);
           if (FD_ISSET(fd1))         /* caract=E8res sur 1 */
             handle_input_from_source1();
           if (FD_ISSET(fd2))         /* caract=E8res sur 2 */
             handle_input_from_source2();
         }
      
      }  =20
      

      L'exemple ci-dessus bloque ind=E9finiment, jusqu'=E0 ce que des caract=E8re= s venant d'une des sources soient disponibles. Si vous avez besoin d'un /timeout/, remplacez juste l'appel =E0 select par :

      int res;
      struct timeval Timeout;
      
      /* fixe la valeur du timeout */
      Timeout.tv_usec =3D 0;  /* millisecondes */
      Timeout.tv_sec  =3D 1;  /* secondes */
      res =3D select(maxfd, &readfs, NULL, NULL, &Timeout);
      if (res=3D=3D0)
      /* nombre de descripteurs de fichiers avec caract=E8res
         disponibles =3D 0, il y a eu timeout */
      

      Cet exemple verra l'expiration du delai de timeout apr=E8s une seconde= . S'il y a timeout, select retournera 0, mais fa=EEtes attention, = Timeout est d=E9cr=E9ment=E9 du temps r=E9ellement attendu par sel= ect. Si la valeur de timeout est 0,= select retournera imm=E9diatement.

      4. Autres sources d'information

      5. Contributions


      Page suivante Page précédente Table des matières