Systèmes Répartis
LA PROGRAMMATION C SOUS UNIX
C-SYSTEME
C-SYSTEME C-SYSTEME
Edition March OOOO
ESAT/DGF/DMSI/SYST
1/13
Systèmes Répartis
LA PROGRAMMATION C SOUS UNIX
C-SYSTEME
SOMMAIRE I) INTRODUCTION _____________________________________________________________________________3 II) ATTACHEMENT D'UN PROCESSUS À UN TERMINAL___________________________________________3 III) ENTRÉES-SORTIES SUR UN TERMINAL______________________________________________________4 IV) PARAMÉTRAGE D'UNE LIAISON_____________________________________________________________5 1) LA STRUCTURE "TERMIOS"________________________________________________________________________5 2) LES PRIMITIVES DE MANIPULATION DE PARAMÈTRES________________________________________________________7 3) UTILISATION__________________________________________________________________________________8 V) STRUCTURE TERMIO________________________________________________________________________9 1) GÉNÉRALITÉS_________________________________________________________________________________9 2) MODIFICATION DES PARAMÈTRES____________________________________________________________________9 3) CONTRÔLE DES DESCRIPTEURS DE FICHIERS_____________________________________________________________12 INDEX________________________________________________________________________________________13
Edition March OOOO
ESAT/DGF/DMSI/SYST
2/13
Systèmes Répartis
LA PROGRAMMATION C SOUS UNIX
C-SYSTEME
I) INTRODUCTION Les terminaux jouent un rôle important puisqu'ils permettent l'interaction entre les utilisateurs et les applications. L'interface avec chaque terminal relié à l'ordinateur par une voie asynchrone est paramétrée par un certain nombre de valeurs qui indiquent au contrôleur de la voie les opérations à réaliser lors de l'émission ou la réception des caractères (vitesse de transmission, traitement des caractères spéciaux, contrôle de parité,...). Au niveau du shell, c'est la commande stty qui permet de connaître ou modifier ces paramètres. II)ATTACHEMENT D'UN PROCESSUS À UN TERMINAL Un processus a un terminal d'attachement (ou de contrôle ) qu'il peut désigner en utilisant le fichier spécial /dev/tty ou en utilisant son nom de fichier complet /dev/tty… Le processus, et tous ceux de son groupe de processus (processus descendant d'un processus leader qui a créé un nouveau groupe ), recevra les signaux SIGINT lorsque l'utilisateur frappera <Suppr>, SIGQUIT lorsque l'utilisateur frappera le caractère et SIGHUP lorsque le processus leader se terminera. Un processus peut demander son détachement du terminal de contrôle en invoquant la primitive int setgrp(). Dans ce cas ce processus devient processus leader d'un nouveau groupe de processus. La macro int isatty (int desc) permet de savoir si le descripteur passé en paramètre est associé à un terminal ou non.
Edition March OOOO
ESAT/DGF/DMSI/SYST
3/13
Systèmes Répartis
LA PROGRAMMATION C SOUS UNIX
C-SYSTEME
III) ENTRÉES-SORTIES SUR UN TERMINAL L'entrée de caractères sur un terminal (via son descripteur de fichier ) interrompt le processus appelant jusqu'à ce qu'une ligne complète ait été lue (par détection du caractère newline (ascii 10) ou du caractère return (ascii 13). Les entrées-sorties sont réalisées selon deux modes différents : Le mode canonique : c'est le mode par défaut, décrit ci-dessus. La saisie est modifiable par l'utilisation des touches <Erase> ou <Suppr> ; et ne sera traitée qu'après avoir appuyé sur la touche <Entrée>. Le mode non-canonique ou local : il n'y a plus de possibilité d'édition. Chaque caractère entré est traité immédiatement. Ce mode local est lui-même subdivisé en deux sous-modes : Le mode CBREAK, où <EOF> = 1 et <EOL> est quelconque. Les autres caractères spéciaux conservent leur signification. L'écho des caractères entrés est réalisé. Le mode RAW : c'est un mode CBREAK dans lequel il n'y a plus aucun caractère spécial. L'écho des caractères n'est plus réalisé, le contrôle de flux est aboli. Il existe plusieurs caractères spéciaux. Ceux-ci peuvent être définis, en primitive du terminal utilisé, grâce à la commande stty ou la primitive ioctl().
Par ailleurs une lecture sur un terminal est bloquante en mode canonique et non-bloquante en mode non-canonique.
Edition March OOOO
ESAT/DGF/DMSI/SYST
4/13
Systèmes Répartis
LA PROGRAMMATION C SOUS UNIX
C-SYSTEME
IV) PARAMÉTRAGE D'UNE LIAISON 1) La structure "termios" L'ensemble des caractéristiques d'une voie de communication est rassemblé dans la structure termios prédéfinie dans le fichier header .Cette structure correspond à l'ensemble des attributs qui déterminent le comportement du système relativement aux opérations sur le terminal correspondant.
#define NCC (8) struct termios { tcflag_t c_iflag; tcflag_t c_oflag; tcflag_t c_cflag; tcflag_t c_lflag; cc_t c_cc[NCCS]; };
/* nombre de caractères spéciaux */ /* modes d'entrée */ /* modes de sortie */ /* modes de contrôle */ /* modes locaux */ /* caractères de contrôle */
Explication des éléments : les modes d'entrée (tcflag_t c_iflag) : Ils définissent en certain nombre de traitements à appliquer aux caractères en provenance d'un terminal. les modes de sortie (tcflag_t c_oflag) : Ils définissent les transformations à appliquer aux caractères à destination d'un terminal. (majuscule, return, newline, etc.) les modes de contrôle (tcflag_t c_cflag) : Ils correspondent à des informations de contrôle relatives au niveau matériel telles que la parité ou la taille des caractères (7 ou 8 bits). les modes locaux (tcflag_t c_lflag) : Ce sont le plus importants. Ils définissent le comportement général d'une ligne en ce qui concerne les caractères de contrôle et déterminent le primitivement de la primitive read().
Edition March OOOO
ESAT/DGF/DMSI/SYST
5/13
Systèmes Répartis
LA PROGRAMMATION C SOUS UNIX
C-SYSTEME
Valeurs prédéfinies de c_lflag : #define ISIG 00000001 /* traitement des caractères spéciaux : les caractères intr, quit et susp sont des caractères de contrôle provoquant respectivement l'envoi des signaux SIGINT, SIGQUIT et SIGTSTP */ #define ICANON 00000002 /* mode canonique : les caractères lus au cours d'une opération de lecture sur un terminal sont extraits dans une ligne. Tout caractère non suivi d'un caractère de fin de ligne n'est pas accessible en lecture */ #define ECHO 00000010 /* écho */ #define ECHOE 00000020 /* dans ce mode et en ICANON, le caractère de contrôle erase a un écho provoquant l'effacement du dernier caractère sur l'écran */ #define ECHOK 00000040 /* dans ce mode et en ICANON, le caractère de contrôle kill a comme écho le caractère de fin de ligne */ #define ECHONL 00000100 /* écho de newline */ #define NOFLSH 00000200 /* pas de vidage tampon si it */ Valeurs prédéfinies des caractères spéciaux (c_cc[NCCS]) : Pour un caractère, être caractère de contrôle d'un terminal signifie ne pas pouvoir être lu (avec read() par exemple) par un processus via un descripteur de ce terminal. Chacun des éléments du tableau c_cc[NCCS] possède un nom symbolique (par exemple EOF) et sa position dans le tableau est symboliquement désignée par ce nom précédé du caractère V (c_cc[VEOF] est la valeur de retour du caractère de contrôle EOF). ERASE : en mode canonique ICANON, efface le dernier caractère. KILL : en mode canonique ICANON, tous les caractères de la ligne en cours de frappe sont effacés. EOF : en mode canonique ICANON, rend tous les caractères qui précèdent accessible en lecture sans avoir à taper de caractère de fin de ligne. EOL : en mode canonique ICANON, est équivalent au caractère de fin de ligne. INTR : en mode ISIG, la frappe de ce caractère provoque l'envoi du signal SIGINT à tous les processus appartenant au groupe de processus. QUIT : en mode ISIG, la frappe de ce caractère provoque l'envoi du signal SIGQUIT à tous les processus appartenant au groupe de processus. MIN : en mode non canonique, la valeur de ce paramètre définit le nombre de caractères que doit contenir le tampon de lecture pour que les caractères soient accessibles en lecture. TIME : en mode non canonique, la valeur de ce paramètre correspond à un intervalle de temps exprimé en dixièmes de seconde entre la frappe des caractères, au-delà duquel les caractères du tampon de lecture deviennent accessibles en lecture.
Edition March OOOO
ESAT/DGF/DMSI/SYST
6/13
Systèmes Répartis
LA PROGRAMMATION C SOUS UNIX
C-SYSTEME
2) Les primitives de manipulation de paramètres La primitive tcgetattr() extrait les paramètres courants appliqués à un descripteur de terminal et la copie en zone mémoire.
#include int tcgetattr (int desc, struct termios *pt_termios);
Explication des paramètres : int desc : Descripteur du terminal dont on veut les paramètres struct termios *pt_termios : Zone mémoire où seront enregistrés les valeurs des paramètres extraits La primitive tcsetattr() installe des paramètres prédéfinis pour un descripteur de terminal.
#include int tcsetattr (int desc, int option, struct termios *pt_termios);
Explication des paramètres : int desc : Descripteur du terminal où seront appliqués les paramètres int option : Option d'installation TCSANOW : les attributs du terminal sont changés immédiatement TCSADRAIN : les sorties en cours sont réalisées avant l'installation des nouveaux attributs TCSAFLUSH : les sorties en cours sont réalisées et le tampon de lecture est vidé struct termios *pt_termios : Zone mémoire contenant les paramètres à appliquer La primitive tcdrain() bloque le processus jusqu'à ce que tous les caractères à destination d'un terminal aient été transmis.
#include int tcdrain (int desc);
Explication des paramètres : int desc : Descripteur du terminal
Edition March OOOO
ESAT/DGF/DMSI/SYST
7/13
Systèmes Répartis
LA PROGRAMMATION C SOUS UNIX
C-SYSTEME
La primitive tcflush() permet de vider un ou les deux tampons associés à un terminal.
#include int tcflush (int desc, int tampon);
Explication des paramètres : int desc : Descripteur du terminal int tampon : Spécifie le tampon voulu TCIFLUSH : tampon en entrée TCOFLUSH : tampon en sortie TCIOFLUSH : tampon en entrée-sortie 3) Utilisation Quand le mode local est non canonique, une lecture par read() n'est satisfaite que lorsque VMIN caractères ont été reçus ou que le laps de temps VTIME (en dixième de secondes ) s'est écoulé depuis la réception du premier caractère. VMIN et VTIME sont respectivement stockées dans c_cc[VEOF] et c_cc[VEOC].(ces valeurs indiquent le caractère de fin de fichier et de fin de ligne en mode canonique). Elles ne sont prises en considération qu'en mode local non canonique. Si VMIN > 1 et VTIME > 0 : le timer est lancé dès la réception du premier caractère si VTIME est écoulé avant que le système ait reçu VMIN caractères seuls les caractères entrés au clavier sont retournés par read() Si VMIN = 0, le retour de read() est immédiat : les caractères présents dans le tampon d'entrée sont retournés Si VTIME = 0, le timer ne joue aucun rôle
Edition March OOOO
ESAT/DGF/DMSI/SYST
8/13
Systèmes Répartis
LA PROGRAMMATION C SOUS UNIX
C-SYSTEME
V) STRUCTURE TERMIO 1) Généralités Dans les versions antérieures, la structure Unix correspondant à un état de la liaison s'appelle termio et est définie dans termio.h. Elle possède les mêmes champs que termios plus un champ c_line dont la valeur est nécessairement 0. La structure termio contient l'ensemble des paramètres d'une voie. Chaque élément de la structure a la même signification que dans la structure termios.
#define NCC 8 struct termio { tcflag_t c_iflag; tcflag_t c_oflag; tcflag_t c_cflag; tcflag_t c_lflag; char c_line; cc_t c_cc[NCCS]; };
/* nombre de caractères spéciaux */ /* modes d'entrée */ /* modes de sortie */ /* modes de contrôle */ /* modes locaux */ /* comportement */ /* caractères de contrôle */
2) Modification des paramètres La primitive ioctl() modifier le mode local d'entrée-sortie (parité, vitesse, etc.) d'un terminal.
#include int ioctl (int desc , int command , struct termio arg);
Explication des paramètres : int desc : descripteur du terminal : 0 clavier 1 sortie standard 2 sortie erreur int command : nature de la requête de modification TCGETA : Met les paramètres du device dans la structure arg (lecture des paramètres ) TCSETA : Initialise les paramètres du device avec ceux contenus dans la structure arg TCSETAW : Idem que TCSETA, mais la modification est différée jusqu'à la fin de l'écoulement du flux de caractères en cours de sortie struct termio arg : structure de type termio
Edition March OOOO
ESAT/DGF/DMSI/SYST
9/13
Systèmes Répartis
LA PROGRAMMATION C SOUS UNIX
C-SYSTEME
Si les modifications apportées par l'utilisation de la primitive ioctl(), lors de l'exécution d'un programme, font que le terminal ne peut plus être utilisé normalement, on peut lancer la commande shell :
stty sane
Cette commande remet la ligne avec ses paramètres par défaut (qui n'étaient peut-être pas ceux utilisés avant l'invocation). Pour utiliser ioctl() on commence par récupérer le status du device en transférant les renseignements nécessaires dans une structure termio par la requête TCGETA. Une fois cette lecture faite, on modifie les champs désirés dans arg et on transfère l'ensemble, dans l'autre sens, par la requête TCSETA. Le tableau suivant donne la correspondance entre les deux structures : #include struct termios etat tcgetattr(d, &etat); tcsetattr(d, TCSANOW, &etat); tcsetattr(d, TCSADRAIN, &etat); tcsetattr(d, TCSAFLUSH, &etat);
Edition March OOOO
#include struct termio etat ioctl(d, TCGETA, &etat); ioctl(d, TCSETA, &etat); ioctl(d, TCSETAW, &etat); ioctl(d, TCSETAF, &etat);
ESAT/DGF/DMSI/SYST
10/13
Systèmes Répartis
LA PROGRAMMATION C SOUS UNIX
C-SYSTEME
Exemple : Modification du mode de contrôle en entrée du terminal : la lecture est rendue non bloquante, en mode non-mémorisé et l'écho et supprimé. void modifie_term(void) { int n; struct termio ioctl_init, ioctl_tmp; /* Sauvegarde de l'état initial du terminal : */ if ((n=ioctl (0, TCGETA, & ioctl_init)) == -1) { perror("Echec lors de la modification de mode"); exit(errno); } /* Préparation d'une nouvelle structure termio */ ioctl_tmp=ioctl_init; /* copie des informations */ /* Passage en mode non canonique : */ ioctl_tmp.c_flag=ioctl_tmp.c_flag & ~ (ICANON); /* Suppression de l'echo : */ ioctl_tmp.c_flag=ioctl_tmp.c_flag & ~ (ECHO); /* Main rendue au processus tous les 0 caractères => non bloquant */ ioctl_tmp.c.cc[VEOF]=0; /* Modification effective du mode de contrôle par ioctl () : */ if ((n=ioctl (0 ,TCSETA, &ioctl_tmp)) == -1) { perror ("Echec lors de la modification de mode"); exit(errno); } }
Edition March OOOO
ESAT/DGF/DMSI/SYST
11/13
Systèmes Répartis
LA PROGRAMMATION C SOUS UNIX
C-SYSTEME
3) Contrôle des descripteurs de fichiers La primitive fcntl()permet de réaliser des opérations de contrôle ou des modifications de mode sur les descripteurs de fichiers.
#include <sys/types.h> #include #include int fcntl (int desc, int com, int arg);
Explication des paramètres : int desc : descripteur du fichier concerné int com : opération à réaliser F_GETFD : la valeur de retour de la primitive indique si l'ouverture du fichier est maintenue lors d'un recouvrement (valeur paire implique que le fichier reste ouvert). F_SETFD : positionne le drapeau précédent en utilisant une valeur arg paire ou impaire. F_GETFL : retourne l'entier donnant le mode d'ouverture (convention de arg ci-dessus). F_SETFL : le mode d'ouverture est modifié en primitive de la valeur de arg. int arg : arguments éventuels pour réaliser l'opération. O_RDONLY : ouverture en mode seule O_WRONLY : ouverture en écriture seule O_RDWR : ouverture en lecture / écriture O_NDELAY : débloque une opération normalement bloquante (exemple : lecture dans un tube vide ou écriture dans un tube plein) O_APPEND : les écritures se font en fin de fichier Exemple : #include main ( ) { int n, m_init; char c; printf("Valeurs initiales des indicateurs : %d\n" , m_init=fcntl(0, F_GETFL, 0)); while (read(0, &c, 1), c != '\n'); /* lecture bloquante */ fcntl(0 ,F_SETFL, m_init^0_NDELAY);/* lecture non-bloquante */ n=read (0, &c, 1); printf("Valeurs des indicateurs après modification : %d\n", fcntl(0, F_GETFL, 0)); printf(" Valeur de retour de read : %d\n", n); fcntl (0, F_SETFL, m_init); /* restauration mode initial */ }
Seul l'appel à read() permet de mettre en œuvre le contrôle de flux des E/ S. Les autres primitives (scanf(), getchar(), etc.)ne sont utilisables que pour la lecture d'un seul caractère.
Edition March OOOO
ESAT/DGF/DMSI/SYST
12/13
Systèmes Répartis
LA PROGRAMMATION C SOUS UNIX
C-SYSTEME
INDEX
Edition March OOOO
ESAT/DGF/DMSI/SYST
13/13