TP3 - Correction

ppompeani_forksync.c

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

extern int errno;

int parent();
void enfant();

int main() {
    pid_t id;

    id = fork(); // À partir de cette ligne, deux processus exécutent le code en parallèle

    switch (id) {
        case -1:
            perror("fork error");
            return errno;
        case 0:
            // Code exécuté uniquement par l'enfant
            enfant();
            return EXIT_SUCCESS; 
        default:
            // Code exécuté uniquement par le parent
            return parent();
    }
}

int parent() {
    pid_t id;

    id = fork();

    switch (id) {
        case -1:
            perror("fork error");
            return errno;
        case 0:
            // Code exécuté uniquement par l'enfant
            enfant();
            return EXIT_SUCCESS; 
        default:
            // Code exécuté uniquement par le parent
	    wait(NULL);
	    wait(NULL);
    }
    return EXIT_SUCCESS;
}

void enfant() {
	printf("Je suis l'enfant au PID %d\n", getpid());
	sleep(3);
}

ppompeani_forkglob.c

#include <stdio.h>     /* printf, perror, NULL... */
#include <stdlib.h>    /* exit */
#include <unistd.h>    /* fork, getpid, getppid */
#include <errno.h>
#include <sys/types.h> /* pid_t */
#include <sys/wait.h>  /* wait */

extern int errno;      /* Modifiée en cas d'erreur */

void parent();
void enfant();

int *MA_GLOBALE = NULL;

// Création d'un processus enfant et exécution d'une fonction particulière
// par chaque processus (parent et enfant).
int main() {
    pid_t id;

    MA_GLOBALE = (int*)malloc(sizeof(int));

    id = fork(); // À partir de cette ligne, deux processus exécutent le code en parallèle

    printf("Cette ligne va être affichée deux fois\n");

    switch (id) {
        case -1:
            perror("fork error");
            return errno;
        case 0:
            // Code exécuté uniquement par l'enfant
            enfant();
            return EXIT_SUCCESS; 
        default:
            // Code exécuté uniquement par le parent
            parent();
    }
    return EXIT_SUCCESS;
}

void parent() {
  for (int i = 0; i < 100; i++) {
	  *MA_GLOBALE = *MA_GLOBALE + 1;
	  printf("Parent : i=%d, MA_GLOBALE=%d\n", i, *MA_GLOBALE);
  }
}

void enfant() {
  for (int i = 0; i < 100; i++) {
	  *MA_GLOBALE = *MA_GLOBALE + 1;
	  printf("Enfant : i=%d, MA_GLOBALE=%d\n", i, *MA_GLOBALE);
  }
}

ppompeani_forkshared.c

#include <errno.h>
#include <stdio.h>     /* printf, perror, NULL... */
#include <stdlib.h>    /* exit */
#include <sys/types.h> /* pid_t */
#include <sys/wait.h>  /* wait */
#include <unistd.h>    /* fork, getpid, getppid */

extern int errno; /* Modifiée en cas d'erreur */

void parent();
void enfant();

int *MA_GLOBALE = NULL;

// Création d'un processus enfant et exécution d'une fonction particulière
// par chaque processus (parent et enfant).
int main() {
  pid_t id;

  FILE *file = fopen("sharedfile.txt", "w");

  MA_GLOBALE = (int *)malloc(sizeof(int));

  id = fork(); // À partir de cette ligne, deux processus exécutent le code en
               // parallèle

  printf("Cette ligne va être affichée deux fois\n");

  switch (id) {
  case -1:
    perror("fork error");
    return errno;
  case 0:
    // Code exécuté uniquement par l'enfant
    enfant(file);
    return EXIT_SUCCESS;
  default:
    // Code exécuté uniquement par le parent
    parent(file);
    return EXIT_SUCCESS;
  }
}

void parent(FILE *f) {
  usleep(1);
  for (int i = 0; i < 1000; i++) {
    fprintf(
        f,
        "Je suis le "
        "peeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
        "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
        "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeere\n");
  }
  wait(NULL);
  fclose(f);
}

void enfant(FILE *f) {
  for (int i = 0; i < 100; i++) {
    fprintf(
        f,
        "Je suis le "
        "fiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii"
        "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii"
        "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiils\n");
  }
}

ppompeani_forksharedwait.c

#include <errno.h>
#include <stdio.h>     /* printf, perror, NULL... */
#include <stdlib.h>    /* exit */
#include <sys/types.h> /* pid_t */
#include <sys/wait.h>  /* wait */
#include <unistd.h>    /* fork, getpid, getppid */

extern int errno; /* Modifiée en cas d'erreur */

void parent();
void enfant();

int main() {
  pid_t id;
  id = fork();

  switch (id) {
  case -1:
    perror("fork error");
    return errno;
  case 0:
    // Code exécuté uniquement par l'enfant
    enfant();
    return EXIT_SUCCESS;
  default:
    // Code exécuté uniquement par le parent
    parent();
    return EXIT_SUCCESS;
  }
}

void parent() {
  wait(NULL);

  FILE *file = fopen("sharedfile.txt", "a");

  for (int i = 0; i < 1000; i++) {
    fprintf(
        file,
        "%d: Je suis le "
        "peeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
        "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
        "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeere\n", i);
  }
  fclose(file);
}

void enfant() {

  FILE *file = fopen("sharedfile.txt", "w");

  for (int i = 0; i < 100; i++) {
    fprintf(
        file,
        "%d: Je suis le "
        "fiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii"
        "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii"
        "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiils\n", i);
  }
  fclose(file);
}

ppompeani_reponses.md

# Exercice 1.1

a.
`ls`
Si on lui donne un fichier en argument, ls affiche uniquement le nom du fichier.
Si on lui donne un dossier en argument, ls affiche le contenu de ce dossier au lieu du dossier courant.

b.
`cd`
Sans argument, cd ramène au dossier personnel (`/home/<username>`).
Avec l'argument `-`, cd ramène au dossier où on était juste avant le dossier actuel.

# Exercice 1.2

a.
`/proc/self` est un lien symbolique (*symlink*) vers le dossier du processus courant dans `/proc`.

b.
Par défaut, `ls` affiche son dossier courant.
`/proc/self/cwd/` est un lien symbolique vers le dossier courant du processus en cours d'exécution, dans ce cas, la commande `ls`.
Donc les deux commandes font la même chose.

# Exercice 1.3

a.
La touche `/` permet de chercher un mot. Exemple : `/pipi` pour chercher pipi.

b.
La touche `q` permet de quitter.

c.
Oui, on peut scroller avec la molette dans `less`. C'est cool.

d.
`man` lance `less` de lui-même quand il détecte que la sortie standard est le terminal.
Quand on envoie la sortie de standard de `man` dans `less`, ça fait la même chose : `less` se charge de nous afficher le contenu du manuel.

# Exercice 1.4

a. `grep root /etc/passwd`

b. `cut -d : -f 1 /etc/passwd` nous affiche la première colonne du fichier, correspondant aux noms des users.

# Exercice 2.1

a.
Le PID du processus parent est le même que le PPID du processus enfant.
Ça nous permet de vérifier que le parent est bien le parent de l'enfant.

b.
Le processus parent de notre processus parent est `bash`.
C'est le shell, c'est à dire le programme principal qui s'exécute dans le terminal, chargé de lancer les commandes qu'on tape.

c.
Quand le processus parent quitte, le processus enfant change de processus parent.
C'est `systemd` qui l'adopte, le gestionnaire de session.