This is an old revision of the document!


TP 04 - Processus et le type Box

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).

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,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

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. É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.
  2. 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.
  3. Dans le processus enfant, exécutez la commande “ls -l”. Utilisez execvp. Le premier argument doit être identique à la commande.
  4. 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/03_rust.1679174135.txt.gz · Last modified: 2023/03/18 23:15 by cristiana.andrei
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