TP 04 - Processus et le type Box

Vous devez accepter le assignment d'ici et travailler avec ce repository: Lab4

Objectifs

Le but de ce TP est d'apprendre à utiliser

  • Le type Box
  • Utiliser des descripterus de fichers
  • Utiliser dup2
  • Utiliser fork et exec

Le type Box

Pointeurs

Un pointeur est un concept général pour une variable qui contient une adresse en mémoire. Cette adresse fait référence à, ou “pointe vers”, d'autres données. Le type de pointeur le plus courant dans Rust est une référence.

Les références sont indiquées par le symbole & et empruntent la valeur vers laquelle elles pointent. Ils n'ont pas de capacités spéciales autres que la référence aux données et n'ont pas de surcharge.

Les smart pointers, d'autre part, sont des structures de données qui agissent comme un pointeur mais qui ont également des métadonnées et des capacités supplémentaires. Le concept de smart pointer n'est pas propre à Rust : les pointeurs intelligents sont originaires de C++ et existent également dans d'autres langages.

Rust, avec son concept de propriété et d'emprunt, a une différence supplémentaire entre les références et les pointeurs intelligents : alors que les références n'empruntent que des données, dans de nombreux cas, les smart pointers possèdent les données vers lesquelles ils pointent.

Box<T>

Le smart pointer le plus simple est une box, dont le type est écrit Box<T>. Les boxes vous permettent de stocker des données sur le tas plutôt que sur la pile. Ce qui reste sur la pile est le pointeur vers les données du tas.

Les boxes n'ont pas de surcharge de performances, à part le stockage de leurs données sur le tas plutôt que sur la pile. Mais ils n'ont pas beaucoup de capacités supplémentaires non plus. Vous les utiliserez le plus souvent dans ces situations :

  • Lorsque vous avez un type dont la taille ne peut pas être connue au moment de la compilation et que vous souhaitez utiliser une valeur de ce type dans un contexte qui nécessite une taille exacte
  • Lorsque vous avez une grande quantité de données et que vous souhaitez transférer la propriété, mais assurez-vous que les données ne seront pas copiées lorsque vous le ferez
  • Lorsque vous voulez posséder une valeur et que vous vous souciez seulement qu'il s'agisse d'un type qui implémente un trait particulier plutôt que d'être d'un type spécifique
fn main() {
    let b = Box::new(5);
    println!("b = {}", b);
}

Nous définissons la variable b comme ayant la valeur d'une Box qui pointe vers la valeur 5, qui est allouée sur le tas. Ce programme imprimera b = 5; dans ce cas, nous pouvons accéder aux données dans la boîte de la même manière que nous le ferions si ces données étaient sur la pile. Comme toute valeur possédée, lorsqu'une boîte sort de la portée, comme le fait b à la fin de main, elle sera désallouée. La désallocation se produit à la fois pour la boîte (stockée sur la pile) et les données vers lesquelles elle pointe (stockées sur le tas).

Processus

Lancer une application signifie allouer des ressources système (processeur, mémoire, périphériques d'entrée / sortie) pour exécuter l'application. Une application qui s'exécute, c'est-à-dire utilise des ressources système pour exécuter du code et traiter des données, est appelée un processus. Lorsque nous démarrons une application, un processus est créé; lorsque nous arrêtons l'application, ou lorsqu'elle termine son exécution, nous entendons la fin de l'exécution du processus.

Le processus démarre à partir d'un fichier exécutable contenant le code de l'application (instructions) et les données. Le fichier exécutable est également appelé image du processus . Le fichier exécutable est un programme. Nous disons que le processus est un programme en cours d'exécution.

Identifier un processus

PID ( Process Id ) est l'attribut essentiel du processus, un index qui identifie le processus au niveau du système. Un processus est identifié par PID et non par nom d'exécutable (CMD). Nous pouvons créer plusieurs processus à partir du même exécutable, chaque processus ayant son propre PID.

Fork

La fonction fork() crée un nouveau processus enfant dupliquant le processus parent. Après avoir appelé l'appel système fork (avec succès), deux processus seront créés qui sont identiques à l'exception de leur pid et de la valeur de retour de cette fonction.

use nix::sys::wait::waitpid;
use nix::sys::unistd::{fork, ForkResult, write};
 
match unsafe{fork()} {
   Ok(ForkResult::Parent { child, .. }) => {
       println!("Continuing execution in parent process, new child has pid: {}", child);
       waitpid(child, None).unwrap();
   }
   Ok(ForkResult::Child) => {
       // Unsafe to use `println!` (or `unwrap`) here. See Safety.
       write(libc::STDOUT_FILENO, "I'm a new child process\n".as_bytes()).ok();
       unsafe { libc::_exit(0) };
   }
   Err(_) => println!("Fork failed"),
}

Fonctions Unix

Les appels système dup et dup2

dup

L'appel système dup() crée une copie d'un descripteur de fichier.

  • Il utilise le descripteur inutilisé portant le numéro le plus bas pour le nouveau descripteur.
  • Si la copie est créée avec succès, les descripteurs de fichier d'origine et de copie peuvent être utilisés de manière interchangeable.
  • Ils se réfèrent tous les deux à la même description de fichier ouvert et partagent donc les indicateurs de décalage de fichier et d'état de fichier.

dup2

L'appel système dup2() est similaire à dup() mais la différence fondamentale entre eux est qu'au lieu d'utiliser le descripteur de fichier inutilisé portant le numéro le plus bas, il utilise le numéro de descripteur spécifié par l'utilisateur.

Lors de l'appel de dup2 dans Rust, les paramètres donnés doivent être l'ancien descripteur de fichier et le nouveau.

execvp()

La fonction execvp() remplace l'image de processus actuelle par une nouvelle image de processus spécifiée par file. La nouvelle image est construite à partir d'un fichier exécutable standard appelé le nouveau fichier d'image de processus. Aucun retour n'est effectué car l'image de processus appelante est remplacée par la nouvelle image de processus.

Ici, vous pouvez lire comment execvp est utilisé dans la Rust.

waitpid()

L'appel système waitpid() suspend l'exécution du processus appelant jusqu'à ce qu'un enfant spécifié par l'argument pid ait changé d'état. Par défaut, waitpid() attend uniquement les enfants terminés, mais ce comportement est modifiable via l'argument options, comme décrit ci-dessous.

Details sur waitpid en Rust.

Une liste d'autres fonctions Unix peut être trouvée dans la section Bibliographie.

Bibliographie

Sugestions

Transformer un String en CString peut être fait en utilisant

CString::new("ls").unwrap()

// utilisé pour trouver le descripteur de fichier 
use std::os::unix::io::AsRawFd;

Sujets

  1. Créer un programme de sorte que la contenu d'un fichier qui est recu comme premier argument soit redirigée vers un fichier reçu en tant que deuxième argument - une fonctionnalité similaire à l'utilitaire cp de Linux.
  2. Écrivez un programme qui alloue dynamiquement un String à l'aide de Box. Lisez un texte au clavier et ajoutez-le aux String allouée. Imprimez le String.
  3. Créez un programme qui utilise fork pour créer un processus enfant.
    1. dans le processus parent, imprimez son PID (des parents) et le PID de l'enfant. Dans le processus enfant, imprimez le PID du parent et son PID.
    2. Dans le processus enfant, attendez quelques secondes et imprimez ensuite un message.
    3. Dans le processus parent, affichez “En attente de la sortie du processus enfant”, attendez qu'il se termine (waitpid) et imprimez un message avant de quitter.
  4. Dans le processus enfant, exécutez la commande “ls -l”. Utilisez execvp. Le premier argument doit être identique à la commande.
  5. Redirigez la sortie du processus enfant (fd 1) vers un fichier appelé output.txt. Ouvrez le fichier en écriture et utilisez dup2.
    1. N'écrasez pas le fichier output.txt, ajoutez-y des données (fs :: OpenOptions)
sde2/laboratoare/04_rust.txt · Last modified: 2023/03/28 08:02 by alexandru.radovici
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0