Examen de Systèmes II (Licence - Juin 2001)

Exercice

  1. Pourquoi existe-t'il une notion de propriétaire et groupe effectif et propriétaire et groupe réel ?
  2. La norme POSIX indique qu'après chaque écriture réussie dans un fichier les bits S_ISUID et S_ISGID de l'inoeud correspondant sont systématiquement remis à zéro. Pourquoi ?

Exercice

Écrivez une commande temps <cmd> permettant d'obtenir le temps d'exécution d'une commande passée en paramètre. On distinguera, à l'affichage, le temps "utilisateur" et "système". Ex :

<shell> temps ls -ail R /
...
...
temps utilisateur : 40.23 secondes
temps système     : 23.12 secondes

Exercice

Soit le programme suivant :

#define N une_certaine_valeur
static int n=N;
int main(int argc,char *argv[]) {
  int i;
  for (i=0; i<n; i++) if (fork()==0) { n--; main(argc,argv[]); }
  while (wait(NULL)!=-1);
  exit(EXIT_SUCCESS);
}
  1. Combien de processus sont-ils créés lors d'une exécution ?
  2. Comment cette commande termine-t'elle ?
  3. Que ce passe-t'il si l'on remplace l'appel à main(argc,argv[]) par un appel à execvp(argv[0],argv) ?

Exercice

Soit le programme suivant :

#include <tout_ce_qui_est_utile.h>

typedef struct noeud { struct noeud *suivant; unsigned int valeur; } noeud;

static noeud *debut, *fin;
static unsigned int n_noeuds;

void ajoute(int sig) {
  noeud *p;
  p = (noeud *)malloc(sizeof(noeud));
  if (p==NULL) { fprintf(stderr,"Erreur allocation\n"); exit(EXIT_FAILURE); }
  p->valeur = (unsigned int)random()%10;
  switch(sig) {
  case SIGUSR1:
    p->suivant = debut;
    debut = p;
    n_noeuds++;
    if (fin==NULL) fin = debut;
    break;
  case SIGUSR2:
    p->suivant = NULL;
    if (debut==NULL) {
      debut = fin = p;
      n_noeuds = 1;
    } else {
      fin->suivant = p;
      n_noeuds++;
    }
    break;
  }
}

void capte(int sig) {
  noeud *p;
  fprintf(stdout,"N=%d\n",n_noeuds);
  for (p = debut; p!=NULL; p=p->suivant) fprintf(stdout,"valeur=%d\n",p->valeur);
}

int main(int argc,char *argv[]) {
  struct sigaction action;

  srandom((unsigned int)getpid());

  action.sa_handler = capte;
  sigemptyset(&(action.sa_mask));
  action.sa_flags = 0;
  sigaction(SIGQUIT,&action,NULL);

  action.sa_handler = ajoute;
  sigaction(SIGUSR1,&action,NULL);
  sigaction(SIGUSR2,&action,NULL);

  while (pause()==-1 && errno==EINTR);

  exit(EXIT_SUCCESS);
}
  1. Indiquez ce que fait ce programme. Donnez une séquence de commande permettant d'illustrer votre réponse.
  2. En quoi ses réactions à la réception de signaux n'est elle pas conforme à ce que l'on voudrait faire ?
  3. Indiquez quelles corrections (simples) il est possible d'apporter afin de corriger les problèmes.
  4. Reste-t'il des comportements que l'on ne peut corriger ?

Exercice

Écrivez-une commande comptemot <mot> <fichier1> ... <fichiern> permettant de compte le nombre d'occurrences du mot dans les fichiers donnés en arguments. Pour cela, il est demandé de compter les occurrences du mot en exécutant de façon concurrente la commande grep -c <mot> <fichier> sur chacun des fichiers. Les résultats seront collectés dans un tube anonyme.

Exercice

Écrivez-une commande comptelettre <fichier1> ... <fichiern> permettant de compter le nombre d'occurrences de chaque lettre de l'alphabet (en ignorant la différence entre majuscules et minuscules) dans l'ensemble des fichiers donnés en argument. Pour cela il est demandé de collecter les résultats dans un segment de mémoire partagée pouvant contenir 26 entiers (ie : un compteur par lettre de l'alphabet). D'autre part le comptage devra être réalisé en parallèle dans tous les fichiers.