Le but de ce TP est d'apprendre à utiliser
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.
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 :
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).
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.
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.
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"), }
L'appel système dup() crée une copie d'un descripteur de fichier.
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.
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.
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.
Une liste d'autres fonctions Unix peut être trouvée dans la section Bibliographie.
CString::new("ls").unwrap()
// utilisé pour trouver le descripteur de fichier use std::os::unix::io::AsRawFd;