Exercice 1

Créer un fichier dans votre répertoire de travail. Écrivez ensuite un programme qui ouvre ce fichier et affichez la valeur (de l’index) du descripteur associé. Cette valeur est-elle conforme à vos attentes? Que se passe t-il si vous exécuter la commande close(STDIN_FILENO) avant l’appel de open?

Exercice 2

Écrivez un programme qui redirige tous ses printf dans un fichier output.txt plutôt que sur sa sortie standard (sans modifier les appels à printf dans le programme).

Exercice 3

Écrire une commande mycat qui écrive caractère par caractère le contenu de son entrée standard sur sa sortie standard. Pour effectuer les entrées-sorties on utilisera le couple de fonctions read / write. Testez votre programme en lui faisant afficher le code source, comme ceci :

$ ./mycat < mycat.c

Modifiez votre programme pour lire/écrire N caractères à la fois (en définissant une constante dans le source).

Exercice 4

Écrivez un programme qui ouvre un fichier quelconque et qui affiche la valeur de l’index de descripteur associé. Exécutez ce programme directement en le lançant depuis un terminal puis de nouveau en créant un processus fils qui fait un exec de ce même programme. Que constatez-vous?

Exercice 5

Écrire deux commandes pour lire et enregistrer un entier de 32 bits non signé à une position donnée d’un fichier donné. Les deux commandes auront les prototypes suivants:

enregister-entier fichier position valeur
lire-entier fichier position
  • Tester ces commandes en utilisant un fichier membre d’un répertoire de votre compte.

  • Utiliser la commande hexdump pour visualiser le contenu du fichier.

  • Que constate-t-on si l’on cherche lire / écrire après la fin du fichier?

Exercice 6

Écrire la commande reverse input-file-name output-file-name qui écrit le miroir du premier fichier dans le second. On utilisera la fonction lseek() pour déterminer la taille du fichier source.

  • Comment limiter le nombre de lseek ? Le faire.

Exercice 7

On dispose d’une commande ecrire dont le programme source est listé ci-dessous :

int main(int argc, char *argv[]) {
  int i, fd;
  if(argc != 2) {
    fprintf(stderr , "Usage: %s <position_depart>\n", argv[0]);
    exit (1);
  }
  fd = open("fich", O_WRONLY | O_CREAT, 0666);
  for (i = atoi(argv[1]); i < 10; i += 2) {
    lseek(fd , i*sizeof(int), SEEK_SET);
    write(fd, &i, sizeof(int));
    sleep (1);
  }
  close(fd) ;
  return 0 ;
}
  1. Décrivez précisément le contenu du fichier fich après l’exécution de la commande shell suivante :
$ ecrire 0
  1. Même question lorsque l’on exécute consécutivement ces deux commandes :
$ ecrire 0
$ ecrire 1
  1. Que se passe-t-il si l’on exécute les deux commandes ecrire 0 et ecrire 1 en parallèle (en les lançant simultanément dans deux terminaux) ? Que pouvez-vous dire à propos du fichier fich ?

Exercice 8

Interpréter les résultats produit par l’exécution du code suivant :

int main(int argc, char *argv[]) {
  printf("hello ");
  write(1, "world", 5);
  return 1;
}

Que se passe-t-il si l’on remplace la première chaîne par “hello\n” ? Tester aussi lors d’une redirection dans un fichier.

Que se passe-t-il si l’on remplace la sortie standard par la sortie standard d’erreur ?

Proposer une clarification du code.