Skip to topic | Skip to bottom
Home
Linfo
Linfo.CTPSurFichiersr1.2 - 21 Jan 2005 - 12:56 - OlivierDalletopic end

Start of topic | Skip to actions

TP sur fichiers et entrées/sorties

Pensez à consulter feuille de TP10 (pdf) de M. Menez, elle contient des explications générales très intéressantes sur les systèmes de fichiers, mais aussi des indications sur l'utilisation des primitives d'Entrées/Sorties.

A propos de primitives ...

On dispose généralement de deux familles de primitives pour réaliser les entrées/sorties :
  1. Les primitives systèmes de bas-niveau : open(2), read(2), write(2), lseek(2), close(2), ...
    Ces primitives sont le moyen le plus direct de demander une E/S au système d'exploitation Unix, mais ne sont pas toujours très pratiques à utiliser. On peut néanmoins difficilement s'en passer dans certaines situations (par exemple pour programmer des communications entre machines distantes à l'aide de l'API sockets que vous découvrirez bientôt).
  2. Les primitives de haut-niveau, plus pratiques, présentent en plus l'avantage de "tamponner" les entrées/sorties. On les reconnait facilement au fait que leur nom commence systématiquement par la lettre 'f' : fopen(3), fread(3), fwrite(3), fseek(3), fclose(3)...
    Cette famille de fonctions est par ailleurs beauoup plus vaste avec des fonctions plus spécialisées telles que putc(3)/fputc(3), getc(3)/fgetc(3), putchar(3)/getchar(3), gets(3) (à éviter impérativement), fgets(3)/fputs(3) ... Et bien-sûr fprintf(3)/fscanf(3) !
    Nous allons tester la plupart de ces fonctions dans les exercices qui suivent...

Fichier de structures contenant une chaîne de caractères (emprunté à C. Fédèle)

Etude des performances des primitives (emprunté à R. Rousseau)

Pour éviter les surprises liées au protocole de partage de fichiers NFS (utilisé pour vous permettre d'accéder à votre compte depuis toutes les machines), vous exécuterez tous les tests d'exécution de cet exercice dans un répertoire local à votre machine : /tmp/ Et pensez à faire le ménage en partant...

Copiez le fichier ~dalle/MOTS dans /tmp.

read(2)/write(2)

Écrire un programme cat1-readwrite.c qui recopie sur sa voie standard de sortie les caractères lus sur sa voie standard d'entrée. Ce programme utilisera les appels systèmes read(2) et write(2) et un tampon de taille paramétrée par #define BUFFSIZE qui sera définie dans le Makefile.

Ce programme sera utilisé pour générer trois programmes binaires, cat0-readwrite, cat1a-readwrite et cat1b-readwrite avec un tampon de taille respective de 8Ko, 32o et 100Ko. N'oubliez pas d'afficher les éventuelles erreurs sur la standard d'erreur, à l'aide la fonction perror(3) . Ces programmes afficheront de plus sur la voie standard d'erreur la taille du tampon, le nombre de caractères lus et le nombre d'appels à la primitive de lecture. Tester ces programmes avec le fichier MOTS en entrée, et en enchaînant leur sortie vers la commande wc à l'aide d'un tube. On testera aussi le programme cat0-readwrite en lisant les données tapées au clavier (deux ou trois lignes de quelques caractères) et en les redirigeant sur une fichier disque TRES. Un examen du fichier TRES doit donner les mêmes caractères !

getc(3)/putc(3) (et getchar/putchar)

Écrire un programme cat2-getcputc.c qui réalise comme précédemment la recopie sur la voie standard de sortie de la voie d'entrée, mais en utilisant les primitives getchar/putchar ou getc/putc, c.-à-d. en utilisant un tampon de 1 caractère. Ce programmme utilisera la constante GETCHAR qui sera définie ou non dans le Makefile. Si cette constante est définie, le programme utilisera les macros getchar/putchar, sinon, les routines fgetc/fputc.

Ce programme affichera sur la voie standard d'erreurs les mêmes statistiques que précédemment et sera testé de la même manière.

fgets(3)/fputs(3)

Écrire un programme cat3-fgetsfputs.c qui réalise comme précédemment la recopie sur la voie standard de sortie de la voie d'entrée, mais en utilisant les primitives gets/fputs , c.-à-d. en utilisant un tampon d'1 ligne de MAXLINE caractères (par exemple 100 octets). Ce programme affichera sur la voie standard d'erreurs les mêmes statistiques que précédemment et sera testé de la même manière.

scanf(3)/printf(3)

Erire un programme cat4-scanfprintf.c qui réalise comme précédemment la recopie sur la voie standard de sortie de la voie d'entrée, mais en utilisant les primitives scanf/printf, avec un tampon d'un seul caractère. Ce programme affichera sur la voie standard d'erreurs les mêmes statistiques que précédemment et sera testé de la même manière.

Comparaison des performances

Utilisez le script tests_cat pour mesurer et analyser les performances des programmes précédents.

La primitive lseek (emprunté à R. Rousseau)

Meme chose que précédemment : placez-vous dans /tmp/ pour cet exercice...

Quand lseek fonctionne-t-elle ?

Écrire un programme can_seek qui teste la primitive lseek(2) sur la voie standard d'entrée, en écrivant sur la voie stdout un message de succès ou d'échec.

Tester ce programme sur les cas suivants ~:

  • fichier disque : can_seek < /etc/motd
  • terminal ou pseudo terminal : can_seek < /dev/tty
  • idem, avec la voie standard d'entrée : can_seek
  • tube unix : cat /etc/motd | can_seek

Écriture de trous dans un fichier avec lseek(2)

Écrire un programme write_a_hole qui crée un fichier de nom file.hole, écrit une chaîne, puis un trou de taille paramétrée, puis une chaîne. Après chaque écriture ou déplacement de la position d'écriture par lseek , on affichera la position d'écriture.

La taille du trou sera donnée en paramètre au lancement du programme.

Testez ce programme (dans /tmp) avec une taille de trou de 10 octets, puis 1.000.000 d'octets.

Après chaque exécution, faîtes les tests suivants :

  • examen du contenu du fichier file.hole avec emacs ou od -c ·| more,
  • examen de la taille avec la commande ls,
  • taille du répertoire avec la commande du,
  • effet d'une lecture séquentielle du fichier file.hole avec la commande wc,
  • effet de la commande cp file.hole file.hole2 et examen de l'encombrement disque du résultat, avec la commande du (ou ls -s )
  • effet de la commande cat < file.hole > file.hole3 et examen de l'encombrement disque du résultat, avec la commande du (ou ls -s )

Correction

Les corrections qui suivent ont été écrites par M. Rousseau, qui les a abondamment commentées. Elles font par ailleurs appel à des procédures génériques de gestion d'erreur empruntées à R. Stevens (auteur de nombreux livres de référence tq. "Programmation Système Avancée sous Unix" ou "Programmation Réseaux sous Unix"). Ces macros (par exemple ERRNO_EXIT ), et un certain nombre d'autres choses utiles (comme les fichiers d'inclusion tels que stdio.h ), sont déclarées grâce à un unique fichier stevens.h. Le code des fonctions de traitement d'erreur est lui fourni au travers du fichier rr_error.c.

Ainsi, pour produire les programmes de correction à partir des fichiers sources suivants, il faut faire attention aux choses suivantes :

  • mettre le répertoire ou se trouve le fichier stevens.h dans les chemins de recherche des fichiers d'inclusion avec l'option -I
  • lier le code objet du fichier de correction avec celui du fichier rr_error.c
  • Définir la macro LINUX quand on compile un programme devant s'exécuter sur un machine Linux

Par exemple, pour produire le programme cat0-readwrite, une solution est de lancer la commande suivante (en supposant que stevens.h se trouve dans le répertoire courant) :

   gcc -Wall -DLINUX -I. -DBUFFSIZE=32 rr_error.c cat1-readwrite.c -o cat0-readwrite

Voici maintenant les fichiers de correction:

-- OlivierDalle - 21 Jan 2005
to top

I Attachment sort Action Size Date Who Comment
ficChaines.h manage 0.1 K 09 Jan 2005 - 16:43 OlivierDalle  
ficChaines1.c manage 0.9 K 09 Jan 2005 - 16:44 OlivierDalle  
ficChaines2.c manage 0.4 K 09 Jan 2005 - 16:44 OlivierDalle  
tests_cat manage 3.1 K 09 Jan 2005 - 19:46 OlivierDalle  
ficChainesbis.h manage 0.2 K 21 Jan 2005 - 12:40 OlivierDalle  
ficChaines1bis.c manage 0.9 K 21 Jan 2005 - 12:40 OlivierDalle  
ficChaines2bis.c manage 0.4 K 21 Jan 2005 - 12:40 OlivierDalle  
stevens.h manage 7.6 K 21 Jan 2005 - 13:03 OlivierDalle  
rr_error.c manage 4.3 K 21 Jan 2005 - 13:04 OlivierDalle  
cat1-readwrite.c manage 8.1 K 21 Jan 2005 - 13:04 OlivierDalle  
cat2-getcputc.c manage 0.5 K 21 Jan 2005 - 13:05 OlivierDalle  
cat3-fgetsfputs.c manage 0.4 K 21 Jan 2005 - 13:05 OlivierDalle  
cat4-scanfprintf.c manage 0.4 K 21 Jan 2005 - 13:05 OlivierDalle  
can_seek.c manage 0.2 K 21 Jan 2005 - 13:11 OlivierDalle  
write_a_hole.c manage 1.1 K 21 Jan 2005 - 13:11 OlivierDalle  

You are here: Linfo > ProgrammationImperative > CTPSurFichiers

to top

Copyright © 1999-2017 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding WIKIDeptinfo? Send feedback