当前位置:网站首页>Mise en œuvre de la synchronisation des Threads d'exécution gérée par stratovirt vcpu

Mise en œuvre de la synchronisation des Threads d'exécution gérée par stratovirt vcpu

2021-11-25 17:43:53 Wx60474997b01e3

  ​

StratoVirtC'est open source.openEulerPlate - forme de virtualisation légère pour la communauté,Faible bruit léger、Forte compétitivité de l'industrie en matière de sécurité.

StratoVirtLe processus fonctionne en mode utilisateur,Avant le démarrage de la machine virtuelle,StratoVirtLa préparation avant le démarrage sera terminée,Inclure l'initialisation de la mémoire de la machine virtuelle、CPUInitialisation du Registre、Initialisation du périphérique, etc.,Démarrage,CPUInitialisation des registres et des machines virtuelles en cours d'exécutionvCPUGestion des événements de piégeage,Tout est fait parStratoVirtDevCPUModule de gestion​CPU​Terminé..VoiciStratoVirtMoyennevCPUComposition du module de gestion,Et sesStratoVirtPosition in.


       
stratovirt├── acpi├── address_space├── boot_loader├── Cargo.lock├── Cargo.toml├── cpu│ ├── Cargo.toml│ └── src│ ├── aarch64│ │ ├── caps.rs│ │ ├── core_regs.rs│ │ └── mod.rs│ ├── lib.rs│ └── x86_64│ ├── caps.rs│ ├── cpuid.rs│ └── mod.rs├── devices├── hypervisor├── machine├── machine_manager├── migration├── migration_derive├── ozone├── pci├── src│ └── main.rs├── sysbus├── util├── vfio└── virtio
  • 1.


StratoVirt vCPU Conception globale du module

StratoVirt La solution de virtualisation est également un ensemble de solutions de virtualisation assistées par du matériel et des logiciels combinés , Son fonctionnement dépend de la virtualisation assistée par le matériel (Par exemple:VT-XOuKunpeng-V).vCPU La mise en œuvre des modules dépend également de cette solution de virtualisation assistée par le matériel . Pour les machines physiques CPUEn termes, La virtualisation assistée par le matériel est CPU Ajout d'un nouveau modèle :Non-RootMode,Dans ce mode,CPU Exécuter des instructions qui ne sont pas des machines physiques , C'est la directive de la machine virtuelle . Cette façon d'exécuter les instructions élimine la plupart des frais généraux de performance ,Très efficace. Mais la directive sur les privilèges (Par exemple:I/ODirectives) Ne peut pas être exécuté de cette façon , Ou forcer CPU Quitter le mode normal (C'est - à - dire:ROOTMode) Passe au noyau KVM Module et état utilisateur StratoVirtVa t'en occuper., Après le traitement, retournez à Non-Root Exécuter la prochaine commande en mode . EtStratoVirtDansvCPU Les modules tournent principalement autour de KVMDans le modulevCPU Pour réaliser ,Pour soutenirKVMDans le moduleCPUSimulation de,CPU Le Sous - système est principalement responsable du traitement des événements de sortie en mode normal , Et selon GuestOS Avant que le noyau ne commence à fonctionner vCPU Initialisation des états matériels virtuels tels que les registres .ToutvCPU Le modèle de conception du module est illustré dans la figure ci - dessous. :


StratoVirt vCPUGestionRust Mise en œuvre de la synchronisation des fils _kvm

StratoVirt Par l'intermédiaire d'une bibliothèque tierce ​​kvm_ioctls​​ Pour finir et KVMInteraction des modules,Par correspondance ​


​vcpu_fd.run()​ La valeur de retour de la fonction pour gérer la sortie vers ROOT Événements en mode , La valeur de retour de cette fonction est un ​


​VcpuExit​​ENUM of, Sortie définie à ROOT Type d'événement pour le mode ,Y compris:I/OLa distribution de、 Événement d'arrêt du système 、 Événement anormal du système, etc. ,Selon le type d'événementvCPU Les différents événements seront traités séparément . L'ensemble du processus ci - dessus est inclus dans un vCPUEn ligne, Les utilisateurs peuvent eux - mêmes vCPU La façon dont les fils sont liés au noyau et ainsi de suite fait que la machine virtuelle vCPU Obtenir la machine physique CPU Performance à 100% . En même temps,C'est exact.vCPU L'initialisation des informations d'état du matériel virtuel du registre est et StratoVirt Un autre module de BootLoaderSe combinent,InBootLoader Une base de Linux Protocole de démarrage démarrage démarrage rapide Linux Méthode de miroir du noyau , Dans ce processus de démarrage ,BootLoader La tradition sera accomplie de façon proactive BIOS Accès à certaines informations matérielles , Enregistrer la table matérielle correspondante dans la mémoire de la machine virtuelle , Certaines informations de réglage du registre seront également fournies , Ces informations de configuration du registre seront transmises à vCPUModule,Via les paramètresvCPU Valeur du Registre dans la structure ,Laisser la machine virtuelleCPU Sauter le mode réel pour passer directement en mode protégé ,Voilà.Linux Le noyau peut fonctionner directement à partir de l'entrée du mode protégé ,De cette façon,StratoVirt Le processus de démarrage devient léger et rapide . Tout au long devCPUDans le module, Parce qu'il s'agit du noyau KVMModule, Pas sans C Code de langue pour l'interaction . En tant que langage de programmation système ,RustC'est exact.FFI Avec un très bon support ,JeanvCPUNeutralisationKVM Partie efficace et sécurisée de l'interaction des modules .


vCPU Synchronisation du modèle de fil

vCPU Une autre grande responsabilité du module est de gérer vCPULe cycle de vie de,Y compris:new(Création),realize(Activer),run(Exécution),pause(Pause),resume(Reprise),destroy(Destruction).NewEtrealize Le processus de création de la structure et d'initialisation du registre ,run Le processus est la mise en oeuvre KVMMoyennevCPU Fonctionnement et ​


VCPU_EXIT​ Quitter le processus de traitement des événements . .Les trois autres implémentations du cycle de vie impliquent un contrôle précis de la synchronisation des fils , Par exemple, dans une machine virtuelle destroyEn cours, En général, il n'y a qu'un seul vCPUReçu ​


VCPU_EXIT​Dans ​


SHUTDOWN​Événements,LevCPU Le thread doit passer cet événement à tous les vCPUThread, Synchroniser tous les vCPUL'état du fil, Fermeture élégante de la machine virtuelle .Dans ce scénario,, Nous devons penser à Rust Comment réaliser la synchronisation d'état dans Multithreading .


Rust La synchronisation est réalisée par des variables conditionnelles

RustDans la programmation multithreadée, Il existe une sorte de mécanisme de synchronisation appelé barrière (Barrier), Utilisé pour permettre à plusieurs Threads de synchroniser l'endroit où certains processus commencent , C'est l'équivalent d'une porte ,UtiliserwaitMéthodes, Mettez le fil dans la zone critique et bloquez ,Seulement chaqueBarrier Tout est arrivé. wait Point d'appel de la méthode , Les portes s'ouvriront , Tous les Threads sont synchronisés vers le bas .

Et dans un scénario de synchronisation plus complexe, ,Rust Une autre variable de condition du mécanisme de synchronisation est également fournie (Condition Variable) Pour soutenir des scénarios de synchronisation plus complexes , Il fonctionne comme une barrière , Mais il ne bloque pas tout le processus , Au lieu de cela, bloquez un processus qui obtient un mutex jusqu'à ce que les conditions spécifiées soient remplies .C'est - à - dire,Par variables conditionnelles, On peut bloquer un fil avant d'atteindre une condition , Cette fonctionnalité nous permet de synchroniser les fils .

Pour soutenir le contrôle synchrone de différents scénarios , Les variables conditionnelles fournissent également trois méthodes :

  • notify_one(): Utilisé pour aviser un Thread de blocage à la fois , Si plusieurs fils sont bloqués , notify_one
    Est consommé par un fil bloqué , Ne passe pas à un autre Thread de blocage .
  • notify_all(): Utilisé pour aviser tous les fils bloqués .
  • wait_timeout(): Bloquez le thread courant dans la zone critique et attendez la notification ,Vous pouvez définir un timeout
    Pour définir le temps maximum de blocage , Afin d'éviter un blocage permanent qui pourrait entraîner un blocage du programme .

Il est important de noter que la variable conditionnelle doit être utilisée avec la serrure , Et en cours d'exécution , Chaque variable conditionnelle ne peut avoir qu'un seul mutex à la fois (ParMutex L'emballage isolock peut être appelé mutex )Utilisation.


vCPU Contrôle du cycle de vie et synchronisation des fils

In​CPU​ Lors de l'initialisation de la structure de données , Créer une énumération mutuellement exclusive du cycle de vie (​​CpuLifecycleState​​) Et une variable conditionnelle .


       
pub fn new( vcpu_fd: Arc < VcpuFd >, id: u8, arch_cpu: Arc < Mutex <ArchCPU>>, vm: Arc < Mutex <dyn MachineInterface + Send + Sync>>, ) -> Self { CPU { id, fd: vcpu_fd, arch_cpu, state: Arc::new((Mutex::new(CpuLifecycleState::Created), Condvar::new())), work_queue: Arc::new((Mutex::new(0), Condvar::new())), task: Arc::new(Mutex::new(None)), tid: Arc::new(Mutex::new(None)), vm: Arc::downgrade( &vm), } }
  • 1.


PardestoryExemple de cycle de vie,In​​x86_64​​Sous Architecture,Quand quelqu'unvCPUThread received​VcpuExit::Shutdown​Après l'événement, Ce thread ​​CpuLifecycleState​​Modifier comme suit:​​Stopped​​, Et l'appel est enregistré dans ​CPU​ Une machine virtuelle dans la structure de données pointant vers la superstructure ​​destroy​​Méthodes, Cette méthode peut traverser une zone qui contient tout ​CPU​ Un tableau de structures de données , Exécuter chacun des tableaux ​CPU​De​destory()​Méthodes, Cette fonction est implémentée comme suit :


       
fn destory( &self) -> Result < () > { let (cpu_state, cvar) = &*self.state; if *cpu_state.lock().unwrap() == CpuLifecycleState::Running { *cpu_state.lock().unwrap() = CpuLifecycleState::Stopping; } else { *cpu_state.lock().unwrap() = CpuLifecycleState::Stopped; } /* Omettre la logique d'arrêt spécifique */ let mut cpu_state = cpu_state.lock().unwrap(); cpu_state = cvar .wait_timeout(cpu_state, Duration::from_millis(32)) .unwrap() .0;
if *cpu_state == CpuLifecycleState::Stopped { *cpu_state = CpuLifecycleState::Nothing; Ok(()) } else { Err(ErrorKind::DestroyVcpu(format!("VCPU still in {:?} state", *cpu_state)).into()) }}
  • 1.
  • 2.


En tant que​CPU​Méthode d'adhésion,​​destory​​ La fonction obtient chaque ​CPU​ Variables d'état et de condition mutuellement exclusives pour la structure des données , À ce moment - là, la Division déclenchera vCPU Tout à l'extérieur ​CPU​ Déverrouillage de l'état exclusif des données , Et l'état de l'exécution ​​Running​​Modifier comme suit:vCPU À l'arrêt ​​Stopping​​.Faites attention ici., À ce stade, tous ​CPU​De​​destroy​​ Toutes les fonctions déclenchent un événement d'arrêt vCPU En cours ,Pas à chaquevCPU Dans leurs processus respectifs .

Immédiatement après l'entrée​​Stopping​​Après l'état,​​destroy​​ La fonction exécute chaque vCPU Logique d'arrêt respective , Y compris les déclencheurs vCPU, Cette partie est encore principalement liée à KVMLes modules interagissent, Effectuer des changements dans l'état de sortie, etc. .À la fin de la mise en œuvrevCPU Après la logique d'arrêt de , La variable de condition entre dans ​​wait_timeout​​ L'état d'attente de , Ses paramètres sont pour chaque vCPUDe​​CpuLifecycleState​​ Dénombrement de l'état du cycle de vie et temps d'attente , C'est - à - dire avant que l'état de l'énumération du cycle de vie ne change , Le thread est bloqué .

À ce stade, à l'exception du déclenchement vCPUÀ l'extérieurvCPUEn ligne,​​CpuLifecycleState​​ Tout est entré ​​Stopping​​Statut,Dans tous lesvCPUEn ligne,vCPU Fonction analogique d'instruction pour ​kvm_vcpu_exec()​ Tout tourne en boucle , Pour chaque entrée de cycle ,Sera exécuté​ready_for_running()​ La fonction entre dans le jugement de continuer ou non la simulation , Dans cette fonction, chaque vCPUCorrespondant​​CpuLifecycleState​​Surveillance,Quand on découvre​​CpuLifecycleState​​Est devenu​​Stopping​​Heure,vCPU Va sortir du cycle , Ne pas continuer vCPUSimulation de, Après avoir quitté le cycle simulé , Sera modifié ​​CpuLifecycleState​​Pour​​Stopped​​:


       
// The vcpu thread is about to exit, marking the state of the CPU state as Stopped.let (cpu_state, _) = &*self.thread_cpu.state;*cpu_state.lock().unwrap() = CpuLifecycleState::Stopped;
  • 1.


ModifiervCPU Après l'énumération des états du cycle de vie mutuellement exclusifs dans le thread , Déclenchera le blocage correspondant dans le thread ​wait_timeout()​Fonctions,En même temps,LevCPU Fin du cycle de vie du fil . Et pour les fils bloqués , Quand le reste vCPU L'état du thread est devenu ​​Stopped​​Après,Débranchement,En ce moment,Tous lesvCPU Les Threads sont tous en état de synchronisation ​​Stopped​​, Synchronisation réussie de l'état du fil .

On peut le faire de la même façon. pause(Pause)Etresume(Reprise)Contrôle du cycle de vie.


Suivez - nous

StratoVirt Il est déjà openEuler Open Source communautaire . Par la suite, nous aurons une série de sujets à partager ,Si vous avez raison StratoVirt Intérêt pour l'utilisation et la mise en oeuvre , Bienvenue à visiter et rejoindre .

 

版权声明
本文为[Wx60474997b01e3]所创,转载请带上原文链接,感谢
https://chowdera.com/2021/11/20211125172127564q.html

随机推荐