Ziirish's Home :: Blog

Ziirish's Pub

 
 

(référence à Bashfr devenu Danstonchat...)

Alors oui, je suis toujours occupé de bosser sur "mon" shell histoire de passer le temps pendant les vacances, mais aussi d'apprendre. Ça paraît bête comme ça, probablement inutile aussi, mais pourtant j'en apprends tous les jours avec "petit" projet.

Que pouvons-nous bien apprendre avec un tel projet ?

Avant de commencer, je pense qu'il est utile de revenir sur le fonctionnement du Shell puisque je ne vous l'ai pas encore rappelé réellement.

Nous avions déjà vu la "fiche fonctionnelle", à savoir : 1. attente d'une saisie au clavier 2. parsage de la saisie 3. exécution de la ou des commande(s) 4. retour en 1

Pour simplifier au maximum, on pourrait dire que tout cela repose sur 2 appels systèmes : fork et exec. Le premier appel permet de dupliquer un processus à partir de l'appel de ce dernier.

Exemple :


#include <unistd.h>

int
main (int argc, char **argv)
{
    pid_t p;
    puts ("Hello world!");
    p = fork ();
    puts ("Goodbye!");
    return 0;
}

Retourne :


$ gcc -o fork fork.c
$ ./fork            
Hello world!
Goodbye!
Goodbye!

Vu comme ça, c'est facile, non ? (pourquoi on nous a pas montré un exemple comme ça quand j'étais étudiant ?)

Le second appel quant à lui permet d'écraser le contexte d'exécution courant. C'est un peu plus complexe à expliquer, mais typiquement, un programme est une suite d'instructions exécutées par le processeur. L'appel de la commande exec permet de remplacer à la volée ce contexte à partir de l'appel à cette fonction.

Exemple :


#include <unistd.h>

int
main (int argc, char **argv)
{
    puts ("Hello World!");
    execvp ("./test.sh", (char *[]){"./test.sh", NULL});
    puts ("Goodbye!");
    return 0;
}

Donne :


$ cat test.sh 
#!/bin/bash
echo toto
exit 0
$ gcc -o exec exec.c
$ ./exec
Hello World!
toto

Il ne reste plus qu'à remettre en ordre ces différents éléments, et on a un shell fonctionnel !