Differences

This shows you the differences between two versions of the page.

Link to this comparison view

sde2:laboratoare:03_rust [2023/03/18 23:15]
cristiana.andrei created
sde2:laboratoare:03_rust [2023/03/20 23:45] (current)
cristiana.andrei
Line 1: Line 1:
-====== TP 04 Processus ​et le type Box ======+====== TP 03 Fichiers ​et descripterus de fichiers ​====== 
 + 
 +===== Assignment ===== 
 +<note warning>​ 
 +Vous devez **accepter** le assignment d'ici et travailler avec ce repository: [[https://​classroom.github.com/​a/​7L73IFBY|Lab3]] 
 +</​note>​
  
 ===== Objectifs ===== ===== Objectifs =====
 Le but de ce TP est d'​apprendre à utiliser ​ Le but de ce TP est d'​apprendre à utiliser ​
-  * Le type //Box// 
   * Utiliser des descripterus de fichers   * Utiliser des descripterus de fichers
-  * Utiliser dup2  +  * Utiliser dup2  ​
-  * Utiliser fork et exec +
  
-===== Le type Box =====+===== Linux Standard Streams ​===== 
 +Sous Linux, ''​stdin''​ est le flux d'​entrée standard. Cela accepte le texte comme entrée. La sortie texte de la commande au shell est transmise via le flux ''​stdout''​ (sortie standard). Les messages d'​erreur de la commande sont envoyés via le flux ''​stderr''​ (erreur standard).
  
-=== Pointeurs === +Vous pouvez donc voir qu'il existe deux flux de sortie''​stdout''​ et ''​stderr''​et un flux d'entrée, ''​stdin''​Étant donné que les messages d'​erreur et la sortie normale ont chacun leur propre conduit pour les acheminer vers la fenêtre du terminal, ils peuvent être traités indépendamment les uns des autres.
-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éesLe 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 pointentIls n'ont pas de capacités spéciales autres que la référence aux données ​et n'ont pas de surcharge. +Les flux sous Linux, comme presque tout le reste, ​sont traités comme s'ils étaient des **fichiers**. Vous pouvez lire du texte à partir d'un fichier ​et vous pouvez écrire du texte dans un fichierCes deux actions impliquent un flux de données. ​Ainsile concept de traitement ​d'un flux de données ​en tant que fichier ​n'est pas si exagéré.
- +
-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.+
  
 <​note>​ <​note>​
-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.+Chaque fichier associé à un processus se voit attribuer un **numéro unique** pour l'identifier. C'est ce qu'on appelle le **descripteur ​de fichier**. Chaque fois qu'une action doit être effectuée sur un fichier, le descripteur de fichier est utilisé pour identifier le fichier.
 </​note>​ </​note>​
  
-=== Box<​T> ​=== +Ces valeurs sont toujours utilisées pour ''​stdin'',​ ''​stdout''​ et ''​stderr''​ :​ 
-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**.+  * 0: stdin 
 +  * 1: stdout 
 +  * 2: stderr 
 +===== Les appels système dup et dup2 =====
  
-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 :​ +=== dup === 
-  * 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 +L'appel système dup() crée **une copie** d'un descripteur ​de fichier. 
-  * 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 +  * Il utilise ​le descripteur inutilisé portant le numéro ​le plus bas pour le nouveau descripteur
-  * 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+  * 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.
  
-<code c> +=== dup2 === 
-fn main() +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 basil utilise le numéro de descripteur **spécifié par l'​utilisateur**.
-    let b = Box::new(5)+
-    println!("​b = {}"b); +
-+
-</​code>​+
  
-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). +<​note>​ 
- +Lors de l'​appel de [[https://​docs.rs/nix/0.23.1/nix/unistd/fn.dup2.html|dup2]] dans Rustles paramètres donnés doivent être l'ancien descripteur de fichier et le nouveau
-===== Fork ===== +</note>
-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. +
- +
-<code c> +
-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`) hereSee Safety. +
-       ​write(libc::​STDOUT_FILENO"I'm a new child process\n"​.as_bytes()).ok();​ +
-       ​unsafe { libc::​_exit(0) }; +
-   } +
-   ​Err(_) => println!("​Fork failed"​),​ +
-} +
-</code> +
- +
-===== Fonctions Unix ======+
  
 +=== Redirections ===
 +Quand vous voulez rediriger stdout vers un fichier vous pouvez le faire en ouvrant un fichier à l'aide de l'​appel système **open()**, puis en dupliquant ce descripteur de fichier sur //stdout// en utilisant **dup2()**, de sorte que la sortie standard soit maintenant représentée par le fichier ouvert et non par la console.
  
 ===== Bibliographie ===== ===== Bibliographie =====
-  * Understanding ownership ​[[https://​doc.rust-lang.org/​book/ch04-00-understanding-ownership.html|en]], [[https://jimskapt.github.io/rust-book-fr/​ch04-00-understanding-ownership.html|fr]]- ​ +  * OpenOptions ​[[https://​doc.rust-lang.org/​std/fs/​struct.OpenOptions.html]] 
-  * Using Box<​T>​ to Point to Data on the Heap [[https://​doc.rust-lang.org/​book/ch15-01-box.html|en]],​ [[https://jimskapt.github.io/​rust-book-fr/​ch15-01-box.html|fr]] +  * Stdin https://doc.rust-lang.org/std/io/fn.stdin.html 
-  * fork [[https://​docs.rs/​nix/​0.23.1/​nix/​unistd/​fn.fork.html]] +  * Stdout ​https://​doc.rust-lang.org/​std/io/fn.stdout.html 
-  * Unix functions [[https://​docs.rs/​nix/​0.23.1/​nix/​unistd/​index.html]] +  * dup et dup2 https://​docs.rs/​nix/​0.23.1/​nix/​unistd/​fn.dup.html https://​docs.rs/​nix/​0.23.1/​nix/​unistd/​fn.dup2.html
- +
-===== Sugestions ===== +
-<​note>​ +
-Transformer un String en CString peut être fait en utilisant  +
- +
-<code rust> +
-CString::​new("​ls"​).unwrap() +
-</​code>​ +
-</​note>​ +
- +
-<​note>​ +
-<code rust> +
-// utilisé pour trouver le descripteur de fichier  +
-use std::​os::​unix::​io::​AsRawFd;​ +
-</​code>​ +
-</​note>​+
  
 ===== Sujets ===== ===== Sujets =====
-  - Écrivez un programme qui alloue dynamiquement un String ​à l'aide de BoxLisez un texte au clavier et ajoutez-le aux String allouéeImprimez ​le String.  +  - Lisez votre nom à partir du clavier en utilisant [[https://​doc.rust-lang.org/​std/​io/​fn.stdin.html|stdin]]. Imprimer ​le nom en utilisant ​ [[https://​doc.rust-lang.org/​std/​io/​fn.stdout.html|stdout]].//​N'​utilisez pas le println!// 
-  - Créez ​un programme qui utilise fork pour créer un processus enfant.  +  - Imprimer le contenu d'un fichier reçu en tant qu'​argument de ligne de commande sur [[https://​doc.rust-lang.org/​std/​io/​fn.stdout.html|stdout]]. //​N'​utilisez pas le println!// 
-    dans le processus parent, imprimez son PID (des parents) et le PID de l'​enfantDans le processus enfant, imprimez le PID du parent et son PID.  +  Lisez 3 chiffres sur le clavier en utilisant //stdin//. Écrivez ​le maximum ​de ces 3 nombres dans le fichier maximum.txt
-    Dans le processus enfant, attendez quelques secondes et imprimez ensuite ​un message.  +  Copiez ​le contenu d'un fichier donné comme argument depuis la ligne de commande dans un fichier nommé copy.txt 
-    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.  +  Ouvrez 2 instances ​du même fichier ​(ouvrez le fichier 2 fois). Lisez 10 octets de chaque instance ​et imprimez-les. Ouvrez une nouvelle instance du fichier et utilisez **dup()** pour faire une copie du descripteur de fichier ​de cette nouvelle instance. Lisez à partir des deux descripteurs de fichiers et voyez les différences entre la première situation et celle-ci
-  - Dans le processus enfant, exécutez ​la commande "​ls ​-l"Utilisez execvpLe premier argument doit être identique à la commande.  +  - Écrivez ​la date d'​aujourd'​hui par **redirection** de stdout dans un fichier appelé output.txt en utilisant la fonction [[https://​doc.rust-lang.org/​std/​io/​fn.stdout.html|write_all]]
-  - Redirigez la sortie ​du processus enfant (fd 1) vers un fichier ​appelé output.txt. Ouvrez ​le fichier en écriture ​et utilisez dup2 +  - Lisez 5 noms de filles à partir ​du clavier en utilisant [[https://​doc.rust-lang.org/​std/​io/​fn.stdin.html|stdin]] et ecrivez-les dans un fichier ​appelee //names.txt// en utilisant stdoutExecutez encore une fois le programme ​et Lisez 5 noms de garçons à partir du clavierIl faut **ajouter** les noms de garçons aux noms des filles deja existantes dans //​names.txt//, ​pas d'​écraser ​le fichier! //Hint: utilisez [[https://​doc.rust-lang.org/​std/​fs/struct.OpenOptions.html|OpenOptions]] pour ajouter au fichier //
-    - 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