![image](https://image-1305421143.cos.ap-nanjing.myqcloud.com/image/202206141400958.jpeg)
![image](https://bdn.135editor.com/files/images/editor_styles/d1c723e7e296ca791c2fb3b39ebee0f3.jpg)
Annuaire d'articles
Dans Linux
le pilote de périphérique, nous devons résoudre un problème : accès simultané de plusieurs processus à des ressources partagées, l'accès simultané conduira à des conditions de concurrence.
1. Concurrence et concurrence
Concurrence (Concurrency)
: fait référence à plusieurs unités d'exécution exécutées simultanément et en parallèle.
Course (RaceConditions)
: L'accès aux ressources partagées par des unités exécutées simultanément peut facilement conduire à des conditions de course.
Ressources partagées : variables globales, variables statiques, etc. sur les ressources matérielles et logicielles.
La façon de résoudre la course est d'assurer un accès exclusif mutuel aux ressources partagées.
Accès mutuellement exclusif : Lorsqu'une unité d'exécution accède à une ressource partagée, les autres unités d'exécution sont interdites d'y accéder.
Section critique (Critical Sections)
: La zone de code qui accède à une ressource partagée devient une section critique. Les sections critiques doivent être protégées par une sorte de mécanisme d'exclusion mutuelle.
Les mécanismes courants d'exclusion mutuelle incluent : le masquage d'interruptions, les opérations atomiques, les verrous tournants, les sémaphores, les mutex, etc.
2. Occasions où des conditions de course se produisent
[Le transfert d'image du lien externe a échoué, le site source peut avoir un mécanisme de lien antivol, il est recommandé d'enregistrer l'image et de la télécharger directement (img-22GWyopk-1686191322786)(https://image-1305421143.cos.ap- nanjing.myqcloud.com/image/image-20230511140139520.png)]
- Processeurs multiples symétriques (SMP) entre plusieurs processeurs
Plusieurs processeurs utilisent un bus système commun et peuvent accéder aux périphériques et à la mémoire communs. Dans SMP
le cas de multi-cœurs, (CPU0、CPU1)
des conditions de concurrence peuvent survenir dans :
CPU0
entre le processus de etCPU1
le processus deCPU0
CPU1
entre le processus et l'interruption deCPU0
CPU1
entre l'interruption de et l'interruption de
- Au sein d'un même CPU, entre le processus et le processus qui l'a devancé
Dans un seul processeur, plusieurs processus s'exécutent simultanément. Lorsque la tranche de temps d'exécution d'un processus est épuisée, il peut être interrompu par un autre processus hautement prioritaire et une condition de concurrence se produit.
- Entre les interruptions (interruptions logicielles, interruptions matérielles, Tasklets, moitié inférieure) et les processus
Lorsqu'un processus est en cours d'exécution, une interruption externe/interne (interruption logicielle, interruption matérielle, tasklet, etc.) l'interrompt, ce qui entraînera une condition de concurrence.
3. Compilation en panne et exécution en panne
Outre les conditions de concurrence causées par les accès concurrents, il est également nécessaire de comprendre certains problèmes causés par certaines caractéristiques des compilateurs et des processeurs.
3.1 Compilation en panne
Les compilateurs modernes à hautes performances ont la capacité d'optimiser dans le désordre l' optimisation du code objet Afin d'améliorer autant que possible le taux de réussite du cache et l'efficacité du travail de l'unité Load/Store du processeur , le compilateur peut -ordonner les instructions d'accès à la mémoire pour réduire les accès logiques inutiles à la mémoire.
Par conséquent, une fois l'optimisation du compilateur activée, le code assembleur généré n'est pas exécuté strictement selon l'ordre logique du code, ce qui est normal.
Afin de résoudre le problème de désordre de compilation, vous pouvez ajouter barrier()
une barrière de compilation ,
Cette barrière empêche les optimisations du compilateur. Avant et après la mise en place de la barrière, il peut s'assurer que les instructions exécutées ne sont pas désordonnées.
En ajoutant barrier()
une barrière de compilation, l'ordre d'exécution correct peut être garanti.
exemple:
#define barrier() __asm__ __volatile__("": : :"memory")
int main(int argc,char *argv[])
{
int a = 0,b,c,d[4096],e;
e = d[4095];
barrier();
b = a;
c = a;
return 0;
}
3.2 Exécution dans l'ordre
La compilation dans le désordre est le comportement du compilateur et l'exécution dans le désordre est le comportement du processeur au moment de l'exécution.
** Les avancés CPU
réordonnent et exécutent souvent les instructions d'accès à la mémoire en fonction de leurs propres caractéristiques de cache ! ** Cela conduit à plusieurs instructions séquentielles, et les instructions émises ultérieurement peuvent toujours être exécutées en premier.
Ce type d'exécution dans le désordre est très courant chez les multiples
CPU
, ainsi qu'au sein d'un seul .CPU
3.2.1 Entre plusieurs processeurs
Afin de résoudre la situation où CPU
le comportement de l'un CPU
est visible à l'autre entre plusieurs cœurs, ARM
le processeur introduit une instruction de barrière mémoire :
- DMB (barrière de mémoire de données), pour s'assurer que toutes les instructions avant l'instruction, l'accès à la mémoire est terminé, puis accéder à l'action d'accès à la mémoire après l'instruction
- DSB (Data Synchronization Barrier), pour s'assurer que toutes les instructions d'accès mémoire avant cette instruction sont exécutées (accès mémoire, cache, prédiction de saut, maintenance TLB, etc.)
- ISB (Instruction Synchronization Barrier),
Flush
pipeline, garantit que toutes les instructions exécutées après ISB sont obtenues à partir du cache ou de la mémoire.
3.2.2 À l'intérieur d'un seul processeur
Dans la liste
CPU
, nous rencontrons souvent lors de l'accès aux registres périphériques, certains registres périphériques ont des exigences élevées sur la séquence de lecture et d'écriture.Afin d'éviter les désordres d'exécution, certaines instructions de barrière de mémoire sont nécessaires à ce momentCPU
.
CPU
En interne, afin de résoudre ce genre de problème, CPU
quelques consignes de barrière mémoire sont fournies :
peut se référer à
Documentation/memory-devices.txt
etDocumentation/io_ordering.txt
- Barrières de lecture et d'écriture :
mb()
- Barrière de lecture :
rmb()
- barrière en écriture :
wmb()
- enregistrer la barrière de lecture
__iormb()__
- enregistrer la barrière en écriture
__iowmb()__
#define writeb_relaxed(v,c) __raw_writeb(v,c)
#define writew_relaxed(v,c) __raw_writew((__force u16) cpu_to_le16(v),c)
#define writel_relaxed(v,c) __raw_writel((__force u32) cpu_to_le32(v),c)
#define readb(c) ({
u8 __v = readb_relaxed(c); __iormb(); __v; })
#define readw(c) ({
u16 __v = readw_relaxed(c); __iormb(); __v; })
#define readl(c) ({
u32 __v = readl_relaxed(c); __iormb(); __v; })
#define writeb(v,c) ({
__iowmb(); writeb_relaxed(v,c); })
#define writew(v,c) ({
__iowmb(); writew_relaxed(v,c); })
#define writel(v,c) ({
__iowmb(); writel_relaxed(v,c); })
writel
La différence entre etwritel_relaxed
est de savoir s'il y a un obstacle.
4. Résumé
Comme on peut le voir ci-dessus, pour résoudre le problème
- Problèmes de race causés par la concurrence
- Problème de compilation hors service du compilateur hautes performances
CPU
Trouble d'exécution causé par des performances élevées
CPU
Et ARM
les instructions de barrière mémoire fournies par le processeur, etc., c'est aussi le sens du verrouillage du noyau.
Aimez + suivez, ne vous perdez jamais
![image](https://image-1305421143.cos.ap-nanjing.myqcloud.com/image/76f5c092e753e7e745fca85efc1f5106.gif)