新聞中心
探秘linux ioremap:物理地址映射的奧秘

站在用戶的角度思考問題,與客戶深入溝通,找到廊坊網(wǎng)站設計與廊坊網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗,讓設計與互聯(lián)網(wǎng)技術結合,創(chuàng)造個性化、用戶體驗好的作品,建站類型包括:成都網(wǎng)站設計、網(wǎng)站制作、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣、申請域名、網(wǎng)站空間、企業(yè)郵箱。業(yè)務覆蓋廊坊地區(qū)。
Linux操作系統(tǒng)已經(jīng)成為世界上最廣泛使用的操作系統(tǒng)之一,它具有高度的可定制性和多線程優(yōu)化,是開發(fā)人員和運維人員的首選之一。盡管Linux在應用程序開發(fā)、安全性以及系統(tǒng)性能等方面達到了驚人的高度,但是針對硬件的處理卻仍然是非常復雜的。雖然Linux可以通過文件系統(tǒng)或映射文件的方式訪問外部硬件,但是這種方式并不是最為高效的。因此,Linux內核特別提供了一個叫做 ioremap() 的功能來處理這個問題。
性質和用途
ioremap()是Linux內核提供給系統(tǒng)開發(fā)人員的一種機制,用來映射物理地址空間到虛擬地址空間。具體的來說,ioremap()可以將從內核訪問的物理地址轉換為在用戶空間下可用的虛擬地址。這個轉換的過程實際上涉及到對某些特殊內存區(qū)域進行訪問,因此必須謹慎地處理這個過程。
在Linux中,訪問一些系統(tǒng)資源,如帶有Memory-Mapped I/O、Direct Memory Access、系統(tǒng)緩存等的硬件設備,需要直接訪問物理內存地址,而不能使用標準的Linux系統(tǒng)調用。這是因為在這些場景下,訪問效率非常的關鍵。因此,Linux內核提供了ioremap()這個接口,它可以直接訪問物理內存地址。正是因為它具有這種特殊性質,所以ioremap()是Linux內核開發(fā)人員不可或缺的工具之一。
內部機制
ioremap()函數(shù)的具體實現(xiàn)和具體的架構息息相關。 Linux 內核體系結構非常復雜,所以涉及到不同架構的計算機時,可能會出現(xiàn)平臺相關性問題。但是,不管是哪一種架構,ioremap() 都是通過直接地址映射的方式將物理地址映射到虛擬地址空間的。
當系統(tǒng)開發(fā)人員需要使用ioremap()函數(shù)時,首先需要向系統(tǒng)內核請求一個虛擬地址。內核會為調用者分配并返回一個適當?shù)奶摂M地址。系統(tǒng)內核在返回的虛擬地址中記錄了映射位置以及相關信息,以便在需要的時候該函數(shù)可以返回正確的地址。
此時ioremap()函數(shù)已經(jīng)在虛擬地址空間中設置了要關聯(lián)的范圍和屬性,當需要讀取一個特定硬件設備的值時,開發(fā)人員在確定了正確的物理地址之后,使用ioremap()函數(shù)將其映射到虛擬地址。一個已經(jīng)映射的物理地址所對應的虛擬地址是通過讀取對應的寄存器來響應的。這個過程很快,而且可以在通過虛擬地址指針讀取或寫入為硬件保留的寄存器的同時,實際上是在讀取或寫入內存中對應的值。
iolist()函數(shù)是Linux內核提供給系統(tǒng)開發(fā)人員的一種高效的機制,用于將物理地址轉換為用戶可訪問的虛擬地址。在Linux內核中,訪問某些系統(tǒng)資源需要直接訪問物理內存地址,這時必須使用特殊的方法來實現(xiàn),而iolist()正是為此而生。雖然iolist()在不同架構的機器上需要進行平臺相關性的處理,但是它在提高系統(tǒng)性能和優(yōu)化系統(tǒng)開發(fā)方面的作用是不可小覷的。
相關問題拓展閱讀:
- 在Linux內核中,注冊字符設備驅動程序的函數(shù)是?
在Linux內核中,注冊字符設備驅動程序的函數(shù)是?
字符設備驅動程序框架 1、寫出open、write函數(shù) 2、告訴內核 1)、定義一個struct file_operations結構并填充好 static struct file_operations first_drv_fops = { .owner = THIS_MODULE, /* 這是一個宏,推向編譯模塊時自動創(chuàng)建的__this_module變量 */ .open = first_drv_open, .write = first_drv_write, }; 2)、把struct file_operations結構體告訴內核 major = register_chrdev(0, “first_drv”, &first_drv_fops); // 注冊, 告訴內核相關參數(shù):之一個,設備號,0自動分配主設備號,否則為主設備號0-255 第二個:設備名第灶銷二個:struct file_operations結構體 4)、register_chrdev由誰調用(入口函數(shù)調用) static int first_drv_init(void) 5)、入口函數(shù)須使用內核宏來修飾 module_init(first_drv_init); module_init會定義一個結構體,這個結構體里面有一個函數(shù)指針指向first_drv_init這個函數(shù),當我們加載或安裝一個驅動時,內核會自動找到這個結構體,然后調用里面的函數(shù)指針,這個函數(shù)指針指向first_drv_init這個函數(shù),first_drv_init這個函數(shù)就是把struct file_operations結構體告訴內核 6)、有入口函數(shù)就有出口函數(shù) module_exit(first_drv_exit); 最后加上協(xié)議 MODULE_LICENSE(“GPL”); 3、mdev根據(jù)系統(tǒng)信息自動創(chuàng)建設備節(jié)點: 每次寫驅動都要手動創(chuàng)建設備文件過于麻煩,使用設備管理文件系統(tǒng)則方便很多。在2.6的內核以前一直使用的是devfs,但是它存在許多缺陷。它創(chuàng)建了大量的設備文件,其實這些設備更本不存在。而且設備與設備文件的映射具有不確定性,比如U盤即可能對應sda,又可能對應sdb。沒有足夠的主/輔設備號。2.6之后的內核引入了sysfs文件系統(tǒng),它掛載在/sys上,配合udev使用,可以很好的完成devfs的功能,并彌補了那些缺點。(這里說一下,當今內核已經(jīng)使用隱物游netlink了)。 udev是用戶空間的一個應用程序,在嵌入式中用的是mdev,mdev在busybox中。mdev是udev的精簡版。首先在busybox中添加支持mdev的選項: Linux System Utilities —> mdev Support /etc/mdev.conf Support subdirs/symlinks Support regular expressions substitutions when renaming device Support command execution at device addition/removal 然后修改/etc/init.d/rcS: echo /螞乎in/mdev > /proc/sys/kernel/hotplug /in/mdev -s 執(zhí)行mdev -s :以‘-s’為參數(shù)調用位于 /in目錄寫的mdev(其實是個鏈接,作用是傳遞參數(shù)給/bin目錄下的busybox程序并調用它),mdev掃描 /sys/class 和 /sys/block 中所有的類設備目錄,如果在目錄中含有名為“dev”的文件,且文件中包含的是設備號,則mdev就利用這些信息為這個設備在/dev 下創(chuàng)建設備節(jié)點文件。一般只在啟動時才執(zhí)行一次 “mdev -s”。熱插拔事件:由于啟動時運行了命 令:echo /in/mdev > /proc/sys/kernel/hotplug ,那么當有熱插拔事件產(chǎn)生時,內核就會調用位于 /in目錄的mdev。這時mdev通過環(huán)境變量中的 ACTION 和 DEVPATH,來確定此次熱插拔事件的動作以及影響了/sys中的那個目錄。接著會看看這個目錄中是否“dev”的屬性文件,如果有就利用這些信息為 這個設備在/dev 下創(chuàng)建設備節(jié)點文件重新打包文件系統(tǒng),這樣/sys目錄,/dev目錄就有東西了下面是create_class的原型: #define class_create(owner, name) / ({ / static struct lock_class_key __key; / __class_create(owner, name, &__key); / }) extern struct class * __must_check __class_create(struct module *owner, const char *name, struct lock_class_key *key); class_destroy的原型如下: extern void class_destroy(struct class *cls); device_create的原型如下: extern struct device *device_create(struct class *cls, struct device *parent, dev_t devt, void *drvdata, const char *fmt, …) __attribute__((format(printf, 5, 6))); device_destroy的原型如下: extern void device_destroy(struct class *cls, dev_t devt); 具體使用如下,可參考后面的實例: static struct class *firstdrv_class; static struct class_device *firstdrv_class_dev; firstdrv_class = class_create(THIS_MODULE, “firstdrv”); firstdrv_class_dev = class_device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, “xyz”); /* /dev/xyz */ class_device_unregister(firstdrv_class_dev); class_destroy(firstdrv_class); 下面再來看一下應用程序如何找到這個結構體的在應用程序中我們使用open打開一個設備:如:open(/dev/xxx, O_RDWR); xxx有一個屬性,如字符設備為c,后面為讀寫權限,還有主設備名、次設備名,我們注冊時 通過register_chrdev(0, “first_drv”, &first_drv_fops)(有主設備號,設備名,struct file_operations結構體)將first_drv_fops結構體注冊到內核數(shù)組chrdev中去的,結構體中有open,write函數(shù),那么應用程序如何找到它的,事實上是根據(jù)打開的這個文件的屬性中的設備類型及主設備號在內核數(shù)組chrdev里面找到我們注冊的first_drv_fops,實例代碼: #include #include #include #include #include #include #include #include #include #include static struct class *firstdrv_class; static struct class_device *firstdrv_class_dev; volatile unsigned long *gpfcon = NULL; volatile unsigned long *gpfdat = NULL; static int first_drv_open(struct inode *inode, struct file *file) { //printk(“first_drv_open\n”); /* 配置GPF4,5,6為輸出 */ *gpfcon &= ~((0x3); return 0; } if (strcmp(argv, “on”) == 0) { val = 1; } else { val = 0; } write(fd, &val, 4); return 0; }linux ioremap的介紹就聊到這里吧,感謝你花時間閱讀本站內容,更多關于linux ioremap,探秘linux ioremap:物理地址映射的奧秘,在Linux內核中,注冊字符設備驅動程序的函數(shù)是?的信息別忘了在本站進行查找喔。
成都網(wǎng)站設計制作選創(chuàng)新互聯(lián),專業(yè)網(wǎng)站建設公司。
成都創(chuàng)新互聯(lián)10余年專注成都高端網(wǎng)站建設定制開發(fā)服務,為客戶提供專業(yè)的成都網(wǎng)站制作,成都網(wǎng)頁設計,成都網(wǎng)站設計服務;成都創(chuàng)新互聯(lián)服務內容包含成都網(wǎng)站建設,小程序開發(fā),營銷網(wǎng)站建設,網(wǎng)站改版,服務器托管租用等互聯(lián)網(wǎng)服務。
本文名稱:探秘linux ioremap:物理地址映射的奧秘 (linux ioremap)
網(wǎng)站鏈接:http://fisionsoft.com.cn/article/djceoog.html


咨詢
建站咨詢
