日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

内核request_mem_region 和 ioremap的理解

發布時間:2025/3/21 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 内核request_mem_region 和 ioremap的理解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

幾乎每一種外設都是通過讀寫設備上的寄存器來進行的,通常包括控制寄存器、狀態寄存器和數據寄存器三大類,外設的寄存器通常被連續地編址。根據CPU體系結構的不同,CPU對IO端口的編址方式有兩種:

  (1)I/O映射方式(I/O-mapped)

  典型地,如X86處理器為外設專門實現了一個單獨的地址空間,稱為"I/O地址空間"或者"I/O端口空間",CPU通過專門的I/O指令(如X86的IN和OUT指令)來訪問這一空間中的地址單元。

  (2)內存映射方式(Memory-mapped)

  RISC指令系統的CPU(如MIPS ARM PowerPC等)通常只實現一個物理地址空間,像這種情況,外設的I/O端口的物理地址就被映射到內存地址空間中,外設I/O端口成為內存的一部分。此時,CPU可以象訪問一個內存單元那樣訪問外設I/O端口,而不需要設立專門的外設I/O指令。

  但是,這兩者在硬件實現上的差異對于軟件來說是完全透明的,驅動程序開發人員可以將內存映射方式的I/O端口和外設內存統一看作是"I/O內存"資源。

  一般來說,在系統運行時,外設的I/O內存資源的物理地址是已知的,由硬件的設計決定。但是CPU通常并沒有為這些已知的外設I/O內存資源的物理地址預定義虛擬地址范圍,驅動程序并不能直接通過物理地址訪問I/O內存資源,而必須將它們映射到核心虛地址空間內(通過頁表),然后才能根據映射所得到的核心虛地址范圍,通過訪內指令訪問這些I/O內存資源。Linux在io.h頭文件中聲明了函數ioremap(),用來將I/O內存資源的物理地址映射到核心虛地址空間。

但要使用I/O內存首先要申請,然后才能映射,使用I/O端口首先要申請,或者叫請求,對于I/O端口的請求意思是讓內核知道你要訪問這個端口,這樣內核知道了以后它就不會再讓別人也訪問這個端口了.畢竟這個世界僧多粥少啊.申請I/O端口的函數是request_region, 申請I/O內存的函數是request_mem_region,來自include/linux/ioport.h,?如下:

Cpp代碼??
  • ??/*?Convenience?shorthand?with?allocation?*/??
  • #define?request_region(start,n,name)????__request_region(&ioport_resource,?(start),?(n),?(name))??
  • #define?request_mem_region(start,n,name)?__request_region(&iomem_resource,?(start),?(n),?(name))??
  • #define?rename_region(region,?newname)?do?{?(region)->name?=?(newname);?}?while?(0)??
  • extern?struct?resource?*?__request_region(struct?resource?*,??
  • ?????????????????????????????????????????resource_size_t?start,??
  • ?????????????????????????????????????????resource_size_t?n,?const?char?*name);??
  • 這里關鍵來解析一下request_mem_region函數。

    Linux把基于I/O映射方式的I/O端口和基于內存映射方式的I/O端口資源統稱為“I/O區域”(I/O Region)。I/O Region仍然是一種I/O資源,因此它仍然可以用resource結構類型來描述。

    Linux是以一種倒置的樹形結構來管理每一類I/O資源(如:I/O端口、外設內存、DMA和IRQ)的。每一類I/O資源都對應有一顆倒置的資源樹,樹中的每一個節點都是一個resource結構,而樹的根結點root則描述了該類資源的整個資源空間。

    1.結構體

    Cpp代碼??
  • 1.1>struct?resource?iomem_resource?=?{?"PCI?mem",?0x00000000,?0xffffffff,?IORESOURCE_MEM?};??
  • ???1.2>struct?resource?{??
  • ????????????????const?char?*name;??
  • ????????????????unsigned?long?start,?end;??
  • ????????????????unsigned?long?flags;??
  • ????????????????struct?resource?*parent,?*sibling,?*child;??
  • ?????????????};??
  • 2.調用函數
    request_mem_region(S1D_PHYSICAL_REG_ADDR,S1D_PHYSICAL_REG_SIZE, "EpsonFB_RG")
    #define request_mem_region(start,n,name) __request_region(&iomem_resource, (start), (n), (name))
    __request_region檢查是否可以安全占用起始物理地址S1D_PHYSICAL_REG_ADDR之后的連續S1D_PHYSICAL_REG_SIZE字節大小空間

    Cpp代碼??
  • struct?resource?*?__request_region(struct?resource?*parent,?unsigned?long?start,?unsigned?long?n,?const?char?*name)??
  • {??
  • ????struct?resource?*res?=?kmalloc(sizeof(*res),?GFP_KERNEL);??
  • ??
  • ????if?(res)?{??
  • ????????memset(res,?0,?sizeof(*res));??
  • ?????????res->name?=?name;??
  • ?????????res->start?=?start;??
  • ?????????res->end?=?start?+?n?-?1;??
  • ?????????res->flags?=?IORESOURCE_BUSY;??
  • ??
  • ?????????write_lock(&resource_lock);??
  • ??
  • ????????for?(;;)?{??
  • ????????????struct?resource?*conflict;??
  • ??
  • ?????????????conflict?=?__request_resource(parent,?res);??????
  • ?????????????//sibling?parent下的所有單元,檢測申請部分是否存在交疊沖突??
  • ????????????if?(!conflict)???????????????????????????????????
  • ?????????????//conflict=0;申請成功,正常安置了[start,end]到相應位置??
  • ????????????????break;??
  • ????????????if?(conflict?!=?parent)?{??
  • ?????????????????parent?=?conflict;??
  • ????????????????if?(!(conflict->flags?&?IORESOURCE_BUSY))??
  • ????????????????????continue;??
  • ????????????}??
  • ??????????????kfree(res);?????????????????????????????????????
  • ?????????????//檢測到了資源交疊沖突,kfree歸還kmalloc申請的內存??
  • ?????????????res?=?NULL;??
  • ????????????break;??
  • ????????}??
  • ?????????write_unlock(&resource_lock);??
  • ????}??
  • ????return?res;??
  • }??
  • ??
  • static?struct?resource?*?__request_resource(struct?resource?*root,?struct?resource?*new)??
  • {??
  • ????unsigned?long?start?=?new->start;??
  • ????unsigned?long?end?=?new->end;??
  • ????struct?resource?*tmp,?**p;??
  • ??
  • ????if?(end?<?start)??
  • ????????return?root;??
  • ????if?(start?<?root->start)??
  • ????????return?root;??
  • ????if?(end?>?root->end)??
  • ????????return?root;??
  • ?????p?=?&root->child;????????????????????????????????????????
  • ????//root下的第一個鏈表元素*p.[child鏈表是以I/O資源物理地址從低到高的順序排列的]??
  • ????for?(;;)?{??
  • ?????????tmp?=?*p;??
  • ????????if?(!tmp?||?tmp->start?>?end)?{??
  • ????????????new->sibling?=?tmp;??
  • ????????????*p?=?new;??
  • //可以從root->child=null開始我們的分析考慮,此時tmp=null,那么第一個申請將以!tmp條件滿足而進入??
  • //這時root->child的值為new指針,new->sibling?=?tmp?=?null;當第二次申請發生時:如果tmp->start?>?end成立,??
  • //那么,root->child的值為new指針,new->sibling?=?tmp;這樣就鏈接上了,空間分布圖如:??
  • //child=[start,end]-->[tmp->start,tmp->end](1);??
  • //如果條件tmp->start?>?end不成立,那么只能是!tmp條件進入??
  • //那么,root->child的值不變,tmp->sibling?=?new;new->sibling?=?tmp?=?null這樣就鏈接上了,空間分布圖如:??
  • //child=[child->start,child->end]-->[start,end](2);??
  • //當第三次申請發生時:如果start在(2)中的[child->end,end]之間,那么tmp->end?<?start將成立,繼而continue,??
  • //此時tmp?=?(2)中的[start,end],因為tmp->start?<?end,所以繼續執行p?=?&tmp->slibing?=?null,??
  • //因為tmp->end?>?start,所以資源沖突,返回(2)中的[start,end]域??
  • //綜上的兩個邊界值情況和一個中間值情況的分析,可以知道代碼實現了一個從地地址到高地址的順序鏈表??
  • //模型圖:childe=[a,b]-->[c,d]-->[e,f],此時有一個[x,y]需要插入進去,tmp作為sibling指針游動??
  • //tmp指向child=[a,b],??
  • //tmp指向[a,b],當tmp->start>y時,插入后的鏈接圖為:child=[x,y]-->[a,b]-->[c,d]-->[e,f]-->null;當tmp->end>=x時,沖突返回tmp??
  • //tmp指向[c,d],當tmp->start>y時,插入后的鏈接圖為:child=[a,b]-->[x,y]-->[c,d]-->[e,f]-->null;當tmp->end>=x時,沖突返回tmp??
  • //tmp指向[e,f],當tmp->start>y時,插入后的鏈接圖為:child=[a,b]-->[c,d]-->[x,y]-->[e,f]-->null;當tmp->end>=x時,沖突返回tmp??
  • //tmp指向null??????????????????,插入后的鏈接圖為:child=[a,b]-->[c,d]-->[e,f]-->[x,y]-->null;??
  • //順利的達到了檢測沖突,順序鏈接的目的??
  • ????????????new->parent?=?root;??????
  • ????????????return?NULL;??
  • ????????}??
  • ?????????p?=?&tmp->sibling;??
  • ????????if?(tmp->end?<?start)??
  • ????????????continue;??
  • ????????return?tmp;??
  • ????}??
  • }??
  • 其實說白了,request_mem_region函數并沒有做實際性的映射工作,只是告訴內核要使用一塊內存地址,聲明占有,也方便內核管理這些資源。

    重要的還是ioremap函數,ioremap主要是檢查傳入地址的合法性,建立頁表(包括訪問權限),完成物理地址到虛擬地址的轉換。

    void * ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags);

      iounmap函數用于取消ioremap()所做的映射,原型如下:

    void iounmap(void * addr);

      這兩個函數都是實現在mm/ioremap.c文件中。

      在將I/O內存資源的物理地址映射成核心虛地址后,理論上講我們就可以象讀寫RAM那樣直接讀寫I/O內存資源了。為了保證驅動程序的跨平臺的可移植性,我們應該使用Linux中特定的函數來訪問I/O內存資源,而不應該通過指向核心虛地址的指針來訪問。如在x86平臺上,讀寫I/O的函數如下所示:

    Cpp代碼??
  • #define?readb(addr)?(*(volatile?unsigned?char?*)?__io_virt(addr))??
  • #define?readw(addr)?(*(volatile?unsigned?short?*)?__io_virt(addr))??
  • #define?readl(addr)?(*(volatile?unsigned?int?*)?__io_virt(addr))??
  • #define?writeb(b,addr)?(*(volatile?unsigned?char?*)?__io_virt(addr)?=?(b))??
  • #define?writew(b,addr)?(*(volatile?unsigned?short?*)?__io_virt(addr)?=?(b))??
  • #define?writel(b,addr)?(*(volatile?unsigned?int?*)?__io_virt(addr)?=?(b))??
  • #define?memset_io(a,b,c)?memset(__io_virt(a),(b),(c))??
  • #define?memcpy_fromio(a,b,c)?memcpy((a),__io_virt(b),(c))??
  • #define?memcpy_toio(a,b,c)?memcpy(__io_virt(a),(b),(c))??
  • 最后,特別強調驅動程序中mmap函數的實現方法。用mmap映射一個設備,意味著使用戶空間的一段地址關聯到設備內存上,這使得只要程序在分配的地址范圍內進行讀取或者寫入,實際上就是對設備的訪問。

    總結

    以上是生活随笔為你收集整理的内核request_mem_region 和 ioremap的理解的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: av午夜精品 | 亚洲精选在线 | 激情久久免费视频 | 6090伦理 | avwww| 午夜激情网 | 久久久久久激情 | 爱操av | 人人狠狠 | 久久精品无码中文字幕 | 欧美韩日国产 | 日本成人一区二区三区 | 欧美日韩高清一区二区 国产亚洲免费看 | 91直接看| 亚洲精品aⅴ中文字幕乱码 国产精品调教视频 | 双性人hdsexvideos| 欧美暧暧视频 | 免费黄色一级片 | 国产精品永久 | 欧美a级免费 | 黄色精品网站 | 国产人妻精品一区二区三区 | 人人妻人人爽欧美成人一区 | 97福利视频 | 国产一页| 东北高大丰满bbbbzbbb | 亚洲精品欧美精品 | 日韩欧美激情在线 | 亚洲av片在线观看 | 午夜精品久久久久久久久久久久久蜜桃 | 欧美特级黄色大片 | 97在线观看视频免费 | 少妇精品久久久一区二区三区 | 人妻少妇一区 | 熟妇高潮喷沈阳45熟妇高潮喷 | 久久中出 | 筱田优全部av免费观看 | 超碰网站在线 | 色综合久久天天综合网 | 欧美精品国产一区 | 国产免费av电影 | 五月天男人天堂 | 三级影片在线免费观看 | 欧美老熟妇一区二区三区 | 古代玷污糟蹋np高辣h文 | 欧美一区二区 | 亚洲精品www久久久久久广东 | 日本性高潮视频 | 婷婷在线综合 | 一本视频在线 | 大香蕉视频一区二区 | 三级黄色短视频 | 欧美在线观看视频一区 | 91丝袜视频| 四虎影院在线看 | 中文字幕丰满孑伦无码专区 | 亚洲第一成人在线 | 激情播播网 | 亚洲第一在线 | 欧美久久久久久 | 91av免费| 日本一区高清 | 手机看片日韩福利 | 丝袜国产一区 | 日本欧美一级片 | 免费国产黄色片 | 男人操女人的视频 | 在线观看视频免费 | 亚洲欧美强伦一区二区 | 日日色av| 91小视频在线观看 | 亚洲www视频| 欧美精品 在线观看 | 精品一区二区久久久 | 欧美日韩成人免费 | 国产在线精 | www.youjizz日本 | 成年人看片网站 | 成人免费高清视频 | 美日韩一区二区三区 | 秋霞久久精品 | 色欲狠狠躁天天躁无码中文字幕 | 精品国产乱码久久久久久1区2区 | 麻豆影视在线免费观看 | 国产欧美精品 | 在线精品一区 | 日本免费黄视频 | caopor在线 | 香蕉视频性| 日本中文字幕在线免费观看 | 色欲欲www成人网站 老色鬼av | 色倩网站| 欧美激情第三页 | 日本欧美国产一区二区三区 | 免费黄色小视频在线观看 | 天堂资源在线 | 国产3p露脸普通话对白 | 一级国产黄色片 | 8x国产一区二区三区精品推荐 |