Processus

Exercice 1

Ecrire un programme C qui crée deux fils, l'un affiche les entiers de 1 à 50, l'autre de 51 à 100.

Corrigé

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int main(void)
{  pid_t pid;
   int i;

   if ((pid = fork()) == -1)
   {  perror("fork"); exit(1);
   }
   if (pid == 0)
   {  /* fils1 */
      for (i = 1; i <= 50; i++)
         printf("%d\n", i);
      return 0;
   }
   if ((pid = fork()) == -1)
   {  perror("fork"); exit(1);
   }
   if (pid == 0)
   {  /* fils2 */
      for (i = 51; i <= 100; i++)
         printf("%d\n", i);
      return 0;
   }
   return 0;
}

Exercice 2

Modifier le programme précédent pour que l'affichage soit 1 2...100.

Corrigé

Peut-être les nombres s'affichent déjà en ordre. Pour observer l'exécution asynchrone des deux fils, ajoutez une boucle de ralentissement, par exemple

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int main(void)
{  pid_t pid;
   int i, j;
   double x = 123.456;

   if ((pid = fork()) == -1)
   {  perror("fork"); exit(1);
   }
   if (pid == 0)
   {  /* fils1 */
      for (i = 1; i <= 50; i++)
      {  printf("%d\n", i);
         for (j = 0; j < 100000; j++) x = exp(log(x));
      }
      return 0;
   }
   if ((pid = fork()) == -1)
   {  perror("fork"); exit(1);
   }
   if (pid == 0)
   {  /* fils2 */
      for (i = 51; i <= 100; i++)
      {  printf("%d\n", i);
         for (j = 0; j < 100000; j++) x = exp(log(x));
      }
      return 0;
   }
   return 0;
}

L'affichage sera semblable

51
52
1
2
3
4
53
54
55
56
...
46
47
96
97
98
99
48
49
50
100

Lancez le programme plusieurs fois et observez que l'ordre n'est pas toujours le même. Pourquoi ?

Pour synchroniser l'affichage, il suffit d'ajouter wait avant la crèation du second fils.

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int main(void)
{  pid_t pid;
   int i, j;
   double x = 123.456;

   if ((pid = fork()) == -1)
   {  perror("fork"); exit(1);
   }
   if (pid == 0)
   {  /* fils1 */
      for (i = 1; i <= 50; i++)
      {  printf("%d\n", i);
         for (j = 0; j < 100000; j++) x = exp(log(x));
      }
      return 0;
   }
   
   wait(NULL);
   
   if ((pid = fork()) == -1)
   {  perror("fork"); exit(1);
   }
   if (pid == 0)
   {  /* fils2 */
      for (i = 51; i <= 100; i++)
      {  printf("%d\n", i);
         for (j = 0; j < 100000; j++) x = exp(log(x));
      }
      return 0;
   }
   return 0;
}

Exercice 3

Ecrire un programme C permettant de lancer la commande passée en argument.

Corrigé

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char **argv)
{  if (argc < 2)
   {  fprintf(stderr,"Usage: %s commande [arg] [arg] ...\n", argv[0]);
      exit(1);
   }
   execvp(argv[1], argv + 1);
   perror("execvp");
   exit(1);
}

Exemples d'exécution

[stefan@ecrins tp]$ monexec ls -l /etc/httpd/conf.d/
total 36
-rw-r--r--    1 root     root         3424 Sep  2  2002 auth_pgsql.conf
-rw-r--r--    1 root     root          814 Sep  3  2002 perl.conf
-rw-r--r--    1 root     root          459 Sep  3  2002 php.conf
-rw-r--r--    1 root     root          988 Sep  2  2002 python.conf
-rw-r--r--    1 root     root          180 Sep  4  2002 README
-rw-r--r--    1 root     root          251 Aug  6  2002 squirrelmail.conf
-rw-r--r--    1 root     root        11140 Sep  4  2002 ssl.conf
[stefan@ecrins tp]$ monexec echo a b
a b
[stefan@ecrins tp]$ monexec
Usage: monexec commande [arg] [arg] ...
[stefan@ecrins tp]$ monexec toto titi
execvp: No such file or directory

Exercice 4

Ecrire un programme C équivalent à la commande shell suivante :
  1. who & ps & ls -l
  2. who; ps; ls -l

Corrigé

Les commandes séparées par & s'exécutent simultanément.

#include<stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int main(void)
{  pid_t pid;

   if ((pid = fork()) == -1)
   {  perror("fork"); exit(1);
   }
   if (pid == 0)
   {  execlp("who", "who", NULL);
      perror("execlp");
      exit(1);
   }

   if ((pid = fork()) == -1)
   {  perror("fork"); exit(1);
   }
   if (pid == 0)
   {  execlp("ps", "ps", NULL);
      perror("execlp");
      exit(1);
   }

   execlp("ls", "ls", "-l", NULL);
   perror("execlp");
   exit(1);
}

Les commandes séparées par ; s'exécutent successivement.

#include<stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int main(void)
{  pid_t pid;

   if ((pid = fork()) == -1)
   {  perror("fork"); exit(1);
   }
   if (pid == 0)
   {  execlp("who", "who", NULL);
      perror("execlp");
      exit(1);
   }

   wait(NULL);
   if ((pid = fork()) == -1)
   {  perror("fork"); exit(1);
   }
   if (pid == 0)
   {  execlp("ps", "ps", NULL);
      perror("execlp");
      exit(1);
   }

   wait(NULL);
   execlp("ls", "ls", "-l", NULL);
   perror("execlp");
   exit(1);
}

Exercice 5

Ecrire un programme C qui prend en paramètre une série de fichiers source .c, les compile chacun séparément et simultanément puis édite les liens pour produire un exécutable. Ce programme doit :

Envoyez votre programme ici. N'oubliez pas à préciser votre nom et prénom.