Heim  >  Artikel  >  System-Tutorial  >  I/O-Speicherzugriffstechnologie in Linux-Treibern: Prinzipien und Methoden

I/O-Speicherzugriffstechnologie in Linux-Treibern: Prinzipien und Methoden

王林
王林nach vorne
2024-02-11 12:10:031182Durchsuche

I/O-Speicher ist eine besondere Art von Speicher im Linux-System. Er wird zum Zuordnen der Register von Peripheriegeräten verwendet, sodass der Treiber die Peripheriegeräte durch Lesen und Schreiben des Speichers steuern kann. Der E/A-Speicherzugriff ist einer der häufigsten Vorgänge bei der Entwicklung von Linux-Treibern. Er umfasst Konzepte wie physische Adresse und virtuelle Adresse, Portzuordnung und Speicherzuordnung, Bytezugriff und Wortzugriff usw. In diesem Artikel stellen wir I/O-Speicherzugriffstechnologien in Linux-Treibern vor und veranschaulichen deren Verwendung und Vorsichtsmaßnahmen anhand von Beispielen.

I/O-Speicherzugriffstechnologie in Linux-Treibern: Prinzipien und Methoden

ARM adressiert den Speicherplatz und den E/A-Bereich einheitlich, sodass die Steuerung der Hardware durch Lesen und Schreiben von SFR zur Steuerung der Hardware durch Lesen und Schreiben der entsprechenden SFR-Adresse wird. Dieser Teil der Adresse wird auch „I/O-Speicher“ genannt. In x86 werden E/A-Adressen und Speicheradressen separat adressiert. Solche E/A-Adressen werden als „E/A-Ports“ bezeichnet. In diesem Artikel geht es nur um den E/A-Speicherzugriff IO-Speicherzugriffsprozess

Wir wissen, dass Linux einen Speicherzuordnungsmechanismus verwendet, um die wichtigsten Systemressourcen zu verwalten und die physische Adresse für den Prozess transparent zu machen. Das heißt, wenn ein Prozess auf eine physische Speicheradresse (z. B. SFR-Adresse) zugreifen möchte, dann muss es es zuerst in eine virtuelle Adresse abbilden.

I/O-Speicherzugriffstechnologie in Linux-Treibern: Prinzipien und Methoden

IO-Speicheranwendung/-rückgabe

Linux bietet eine Reihe von Funktionen zum Beantragen und Freigeben von IO-Speicherbereichen. Diese beiden APIs sind beim Zugriff auf IO-Speicher nicht erforderlich, sie können jedoch überprüfen, ob die verwendeten Ressourcen verfügbar sind, und die Sicherheit des IO-Zugriffs erhöhen. Wenn verfügbar, ist die Anwendung erfolgreich und wird als verwendet markiert. Andere Treiber können nicht angewendet werden, bevor dieser Prozess die Ressource zurückgibt. **request_mem_region()** Die Makrofunktion gilt für n Speicheradressen aus dem Speicher. Diese Adressen beginnen von vorne, sind lang und der Name stellt den Namen des Geräts dar. Bei Erfolg wird ein Wert ungleich NULL zurückgegeben.

/**
 * 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()

Wie der Name schon sagt, gibt die Makrofunktion die von

request_mem_region()** angeforderten IO-Speicherressourcen an den Kernel zurück, sodass auch andere Prozesse auf den IO-Speicher zugreifen können.

/**
 * 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)

IO-Speicherzuordnung/-aufhebung der Zuordnung

Nach der Beantragung von IO-Ressourcen besteht der nächste Schritt darin, die physische Adresse der virtuellen Adresse zuzuordnen. Die vom Kernel bereitgestellte API lautet wie folgt
static inline void __iomem *ioremap(unsigned long port, unsigned long size)
static inline void iounmap(volatile void __iomem *addr)

IO-Speicherzugriffs-API

ARMs SFR ist 32-Bit, wir können die erhaltene virtuelle Adresse tatsächlich durch erzwungene Typkonvertierung lesen. Wenn Sie jedoch nicht vorsichtig sind, lesen Sie die falsche Adresse , Der Kernel bietet auch eine Standard-API zum Lesen und Schreiben von E/A-Speichern, die nicht nur den Code sicherer macht, sondern auch die Lesbarkeit verbessert.

读IO

unsigned int ioread8(void *addr)
unsigned int ioread16(void *addr)
unsigned int ioread32(void *addr)

写IO

void iowrite8(u8 val,void *addr)
void iowrite16(u8 val,void *addr)
void iowrite32(u8 val,void *addr)

读一串IO内存

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)

写一串IO内存

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)

复制IO内存

void memcpy_fromio(void *dest,void *source,unsigned long len)
void memcpy_toio(void *dest,void *source,unsigned long len)

设置IO内存

void memset_io(void *addr,u8 value,unsigned int len)

通过本文,我们了解了Linux驱动中的I/O内存访问技术,它们可以用来实现对外设寄存器的读写操作。我们应该根据实际需求选择合适的函数,并遵循一些基本原则,如先申请再映射,先释放再取消映射,使用正确的数据类型和大小等。I/O内存访问技术是Linux驱动开发中不可或缺的一部分,它可以实现对外设的控制和配置,也可以提升驱动程序的效率和兼容性。希望本文能够对你有所帮助和启发。

Das obige ist der detaillierte Inhalt vonI/O-Speicherzugriffstechnologie in Linux-Treibern: Prinzipien und Methoden. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:lxlinux.net. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen