Maison > Article > Tutoriel système > Technologie d'accès à la mémoire E/S dans les pilotes Linux : principes et méthodes
La mémoire d'E/S est un type spécial de mémoire dans les systèmes Linux. Elle est utilisée pour mapper les registres des périphériques afin que le pilote puisse contrôler les périphériques en lisant et en écrivant la mémoire. L'accès à la mémoire d'E/S est l'une des opérations les plus courantes dans le développement de pilotes Linux. Elle implique des concepts tels que l'adresse physique et l'adresse virtuelle, le mappage de port et le mappage de mémoire, l'accès aux octets et l'accès aux mots, etc. Dans cet article, nous présenterons les technologies d'accès à la mémoire d'E/S dans les pilotes Linux et illustrerons leur utilisation et leurs précautions avec des exemples.
ARM adresse l'espace mémoire et l'espace IO de manière uniforme, donc contrôler le matériel en lisant et en écrivant SFR devient contrôler le matériel en lisant et en écrivant l'adresse SFR correspondante. Cette partie de l'adresse est également appelée Mémoire E/S. Dans x86, les adresses d'E/S et les adresses mémoire sont adressées séparément. Ces adresses d'E/S sont appelées ports d'E/S. Cet article traite uniquement de l'accès à la mémoire IO
Nous savons que afin de gérer les ressources système les plus importantes et de rendre l'adresse physique transparente pour le processus, Linux utilise un mécanisme de mappage de mémoire, c'est-à-dire que si un processus souhaite accéder à une adresse mémoire physique (par exemple, l'adresse SFR), alors il doit d'abord le mapper en adresse virtuelle.
«
”
Linux fournit un ensemble de fonctions pour demander et libérer des plages de mémoire IO. Ces deux API ne sont pas nécessaires lors de l'accès à la mémoire IO, mais elles sont recommandées pour vérifier si les ressources appliquées sont disponibles et augmenter la sécurité de l'accès IO. si disponible, l'application est réussie et marquée comme utilisée. Les autres pilotes ne pourront pas s'appliquer avant que ce processus ne renvoie la ressource.
**request_mem_region()** La fonction macro s'applique à n adresses mémoire de la mémoire. Ces adresses commencent par la première, sont longues et le nom représente le nom de l'appareil. Elle renvoie non NULL en cas de succès et NULL en cas d'échec.
/** * request_mem_region - create a new busy resource region * @start: resource start address * @n: resource region size * @name: reserving caller's ID string */ struct resource * request_mem_region(resource_size_t start, resource_size_t n,const char *name)
**release_mem_region()Comme son nom l'indique, la fonction macro renvoie les ressources mémoire IO demandées par request_mem_region()** au noyau afin que d'autres processus puissent également accéder à la mémoire IO.
/** * release_mem_region - release a previously reserved resource region * @start: resource start address * @n: resource region size */ void release_mem_region(resource_size_t start, resource_size_t n,const char *name)
Après avoir demandé des ressources IO, l'étape suivante consiste à mapper l'adresse physique à l'adresse virtuelle. L'API fournie par le noyau est la suivante
static inline void __iomem *ioremap(unsigned long port, unsigned long size) static inline void iounmap(volatile void __iomem *addr)
Le SFR d'ARM est 32 bits. Après avoir parcouru ioremap, nous pouvons en fait lire l'adresse virtuelle obtenue directement via une conversion de type forcée. Cependant, cette méthode n'est pas assez sûre, pour cette raison. , le noyau également L'API standard fournie pour lire et écrire la mémoire IO rend non seulement le code plus sûr, mais améliore également la lisibilité.
unsigned int ioread8(void *addr) unsigned int ioread16(void *addr) unsigned int ioread32(void *addr)
void iowrite8(u8 val,void *addr) void iowrite16(u8 val,void *addr) void iowrite32(u8 val,void *addr)
void ioread8_rep(void *addr,void *buf,unsigned long len) void ioread16_rep(void *addr,void *buf,unsigned long len) void ioread32_rep(void *addr,void *buf,unsigned long len)
void iowrite8_rep(void *addr,const void *buf,unsigned long len) void iowrite16_rep(void *addr,const void *buf,unsigned long len) void iowrite32_rep(void *addr,const void *buf,unsigned long len)
void memcpy_fromio(void *dest,void *source,unsigned long len) void memcpy_toio(void *dest,void *source,unsigned long len)
void memset_io(void *addr,u8 value,unsigned int len)
通过本文,我们了解了Linux驱动中的I/O内存访问技术,它们可以用来实现对外设寄存器的读写操作。我们应该根据实际需求选择合适的函数,并遵循一些基本原则,如先申请再映射,先释放再取消映射,使用正确的数据类型和大小等。I/O内存访问技术是Linux驱动开发中不可或缺的一部分,它可以实现对外设的控制和配置,也可以提升驱动程序的效率和兼容性。希望本文能够对你有所帮助和启发。
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!