TP 06 - Signaux

Assignment

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

Objectifs

Le but de ce TP est d'apprendre à utiliser

  • Les signaux

Signaux en Rust

Les processus tels que les applications en ligne de commande doivent réagir aux signaux envoyés par le système d'exploitation. L'exemple le plus courant est probablement Ctrl + C, le signal qui indique généralement à un processus de se terminer. Pour gérer les signaux dans les programmes Rust, vous devez considérer comment vous pouvez recevoir ces signaux ainsi que comment vous pouvez y réagir.

Un signal est une interruption logicielle dans le flux d'exécution de processus normal.

L'ensemble des types de signaux est fini; le système d'exploitation conserve, pour chaque processus, un tableau d'actions choisi par lui, pour chaque type de signal. À tout moment, ces actions sont bien déterminées. Au début du processus, la table d'actions est initialisée avec les valeurs par défaut. Le mode de traitement du signal n'est pas décidé lors de la réception du signal par le processus, mais il est automatiquement choisi dans le tableau. Les signaux sont synchrones / asynchrones avec le flux d'exécution de processus qui reçoit le signal si l'événement qui provoque l'envoi du signal est synchrone / asynchrone avec le flux d'exécution de processus.

Emission et réception de signaux

Lorsqu'un signal est généré, il passe dans un état en attente. Normalement, il reste dans cet état pendant très peu de temps et est ensuite envoyé au processus de destination. Cependant, si ce type de signal est actuellement verrouillé, il pourrait rester indéfiniment en état de veille jusqu'à ce que les signaux de ce type soient déverrouillés. Une fois ce type de signal déverrouillé, il sera envoyé immédiatement. Lorsque le signal a été reçu, immédiatement ou tard, l'action spécifiée pour ce signal est exécutée. Pour certains signaux, tels que SIGKILL et SIGSTOP , l'action est fixe (le processus est terminé), mais, pour la plupart des signaux, le programme peut choisir de:

  • ignore le signal
  • spécifier une fonction de type handler
  • accepte l'action par défaut pour ce type de signal.

Types de signaux standard

Cette section présente les noms des différents types de signaux standard et décrit le type d'événements qu'ils indiquent.

Chaque nom de signal est une définition de macro qui représente, en fait, un entier positif (le numéro de ce type de signal).

Un programme ne doit jamais faire d'hypothèses sur le code numérique d'un type particulier de signal, mais plutôt s'y référer toujours par son nom. En effet, un nombre pour un type de signal peut varier d'un système à l'autre, mais leurs noms sont standard. Pour la liste complète des signaux pris en charge par un système, vous pouvez exécuter sur la ligne de commande:

$ kill -l
 
     1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL
     5) SIGTRAP      6) SIGABRT      7) SIGBUS       8) SIGFPE
     9) SIGKILL     10) SIGUSR1     11) SIGSEGV     12) SIGUSR2
    13) SIGPIPE     14) SIGALRM     15) SIGTERM     17) SIGCHLD
    18) SIGCONT     19) SIGSTOP     20) SIGTSTP     21) SIGTTIN
    22) SIGTTOU     23) SIGURG      24) SIGXCPU     25) SIGXFSZ
    26) SIGVTALRM   27) SIGPROF     28) SIGWINCH    29) SIGIO
    30) SIGPWR      31) SIGSYS      33) SIGRTMIN    34) SIGRTMIN+1
    35) SIGRTMIN+2  36) SIGRTMIN+3  37) SIGRTMIN+4  38) SIGRTMIN+5
    39) SIGRTMIN+6  40) SIGRTMIN+7  41) SIGRTMIN+8  42) SIGRTMIN+9
    43) SIGRTMIN+10 44) SIGRTMIN+11 45) SIGRTMIN+12 46) SIGRTMIN+13
    47) SIGRTMIN+14 48) SIGRTMIN+15 49) SIGRTMAX-15 50) SIGRTMAX-14
    51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10
    55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7  58) SIGRTMAX-6
    59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
    63) SIGRTMAX-1  64) SIGRTMAX

Les noms de signaux sont définis dans l'en-tête signal.h sous Unix. En général, les signaux ont des rôles prédéfinis, mais ils peuvent être remplacés par le programmeur. Les plus connus sont les signaux suivants:

  • SIGINT - transmis lorsque la combinaison est enfoncée CTRL+C;
  • SIGQUIT - transmis lorsque la combinaison est enfoncée CTRL+\;
  • SIGSEGV - transmis lors de l'accès à un emplacement de mémoire invalide, etc.
  • SIGKILL - ne peut pas être ignoré ou remplacé. La transmission de ce signal a pour effet de mettre fin au processus, quel que soit le contexte.

Pour gerer les signaux en Rust on utilise nix::sys::signal::signal.

Tuer des processus

Si un processus Linux ne répond plus ou consomme trop de ressources, vous devrez peut-être le tuer.

La plupart des processus ont leurs propres méthodes d'arrêt. Malheureusement, les processus peuvent mal fonctionner et ne pas se laisser arrêter. Si un processus d'arrière-plan en cours d'exécution ne répond pas, il devient nécessaire d'utiliser une commande pour le tuer.

En Rust, on utilise la fonction kill qui force le processus fils à se fermer. Si l'enfant est déjà sorti, une erreur InvalidInput est renvoyée. Cela équivaut à envoyer un SIGKILL sur les plates-formes Unix.

Exemple:

use std::process::Command;
 
let mut command = Command::new("yes");
if let Ok(mut child) = command.spawn() {
    child.kill().expect("command wasn't running");
} else {
    println!("yes command didn't start");
}

Sugestions

Transformer un String en &[u8] peut être fait en utilisant

s.as_bytes()

Transformer un descripteur de fichier en File peut être fait en utilisant

let mut f = unsafe { fs::File::from_raw_fd(fd) };

Bibliographie

Sujets

  1. Compilez ex1. Exécutez-le et utilisez la commande shell kill pour lui envoyer des signaux.
    1. Modifiez-le pour qu'à chaque fois qu'il reçoit un signal, il imprime une lettre différente : a - SIGHUP, b - SIGINT, n - SIQUIT, s - SIGTRAP, espace - SIGFPE. Écrivez un autre programme en Rust qui lui envoie des signaux pour qu'il imprime bannanas bannanas. Le deuxième programme reçoit le pid de destination à partir d'un argument de ligne de commande. On utlise la fonction kill pour envoyer un certain signal a un certain processus, en mentionant le PID et le type de signal:
        kill(Pid::from_raw(/*ici on met le pid*/), Signal::/*type de signal*/); 

      Hint: Pour trouver le pid du processus ex1, utilisez la commande top dans le terminal.

  2. Créez un programme qui fait fork et entre dans une boucle infinie (avec un sleep). Son enfant attend quelques secondes puis sort. Écrivez un message à l'écran lorsque l'enfant sort. Utilisez SIGCHLD.
  3. Essayez de stocker une valeur dans un pointeur null. Lors de la réception du signal SIGSEGV, imprimez l'adresse où le défaut de segmentation s'est produit.
    1. Essayez de stocker une valeur dans un pointeur pour une constante. Maintenant, voyez ce qui se passe.
sde2/laboratoare/06_rust.txt · Last modified: 2023/04/11 08:14 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