linux x86 io端口映射,linux中的 IO端口映射和IO內存映射

下面是今天看到兩篇關于linux中的 IO端口映射和IO內存映射的文章,時間關系,沒來得及深入理解,有空好好看看

CPU地址空間

CPU地址空間

(一)地址的概念

1)物理地址:CPU地址總線傳來的地址,由硬件電路控制其具體含義。物理地址中很大一部分是留給內存條中的內存的,但也常被映射到其他存儲器上?(如顯存、BIOS等)。在程序指令中的虛擬地址經過段映射和頁面映射后,就生成了物理地址,這個物理地址被放到CPU的地址線上。

物理地址空間,一部分給物理RAM(內存)用,一部分給總線用,這是由硬件設計來決定的,因此在32?bits地址線的x86處理器中,物理地址空間是2的32次方,即4GB,但物理RAM一般不能上到4GB,因為還有一部分要給總線用(總線上還掛著別的?許多設備)。在PC機中,一般是把低端物理地址給RAM用,高端物理地址給總線用。

2)總線地址:總線的地址線或在地址周期上產生的信號。外設使用的是總線地址,CPU使用的是物理地址。

物理地址與總線地址之間的關系由系統的設計決定的。在x86平臺上,物理地址就是總線地址,這是因為它們共享相同的地址空間——這句話有點難理解,詳見下?面的“獨立編址”。在其他平臺上,可能需要轉換/映射。比如:CPU需要訪問物理地址是0xfa000的單元,那么在x86平臺上,會產生一個PCI總線?上對0xfa000地址的訪問。因為物理地址和總線地址相同,所以憑眼睛看是不能確定這個地址是用在哪兒的,它或者在內存中,或者是某個卡上的存儲單元,?甚至可能這個地址上沒有對應的存儲器。

3)虛擬地址:現代操作系統普遍采用虛擬內存管理(Virtual?Memory?Management)機制,這需要MMU(Memory?Management?Unit)的支持。MMU通常是CPU的一部分,如果處理器沒有MMU,或者有MMU但沒有啟用,CPU執行單元發出的內存地址將直接傳到芯片引腳上,被?內存芯片(物理內存)接收,這稱為物理地址(Physical?Address),如果處理器啟用了MMU,CPU執行單元發出的內存地址將被MMU截獲,從CPU到MMU的地址稱為虛擬地址(Virtual?Address),而MMU將這個地址翻譯成另一個地址發到CPU芯片的外部地址引腳上,也就是將虛擬地址映射成物理地址。

Linux中,進程的4GB(虛擬)內存分為用戶空間、內核空間。用戶空間分布為0~3GB(即PAGE_OFFSET,在0X86中它等于?0xC0000000)

,剩下的1G為內核空間。程序員只能使用虛擬地址。系統中每個進程有各自的私有用戶空間(0~3G),這個空間對系統中的其他進程是不可見的。

CPU發出取指令請求時的地址是當前上下文的虛擬地址,MMU再從頁表中找到這個虛擬地址的物理地址,完成取指。同樣讀取數據的也是虛擬地址,比如mov?ax,?var.?編譯時var就是一個虛擬地址,也是通過MMU從也表中來找到物理地址,再產生總線時序,完成取數據的。

(二)編址方式

1)外設都是通過讀寫設備上的寄存器來進行的,外設寄存器也稱為“I/O端口”,而IO端口有兩種編址方式:獨立編址和統一編制。

統一編址:外設接口中的IO寄存器(即IO端口)與主存單元一樣看待,每個端口占用一個存儲單元的地址,將主存的一部分劃出來用作IO地址空間,如,在?PDP-11中,把最高的4K主存作為IO設備寄存器地址。端口占用了存儲器的地址空間,使存儲量容量減小。

統一編址也稱為“I/O內存”方式,外設寄存器位于“內存空間”(很多外設有自己的內存、緩沖區,外設的寄存器和內存統稱“I/O空間”)。

如,Samsung的S3C2440,是32位ARM處理器,它的4GB地址空間被外設、RAM等瓜分:

0x8000?1000????LED?8*8點陣的地址

0x4800?0000?~?0x6000?0000??SFR(特殊暫存器)地址空間

0x3800?1002???鍵盤地址

0x3000?0000?~?0x3400?0000??SDRAM空間

0x2000?0020?~?0x2000?002e??IDE

0x1900?0300???CS8900

獨立編址(單獨編址):IO地址與存儲地址分開獨立編址,I/0端口地址不占用存儲空間的地址范圍,這樣,在系統中就存在了另一種與存儲地址無關的IO地?址,CPU也必須具有專用與輸入輸出操作的IO指令(IN、OUT等)和控制邏輯。獨立編址下,地址總線上過來一個地址,設備不知道是給IO端口的、還是?給存儲器的,于是處理器通過MEMR/MEMW和IOR/IOW兩組控制信號來實現對I/O端口和存儲器的不同尋址。如,intel?80x86就采用單獨編址,CPU內存和I/O是一起編址的,就是說內存一部分的地址和I/O地址是重疊的。

獨立編址也稱為“I/O端口”方式,外設寄存器位于“I/O(地址)空間”。

對于x86架構來說,通過IN/OUT指令訪問。PC架構一共有65536個8bit的I/O端口,組成64K個I/O地址空間,編號從?0~0xFFFF,有16位,80x86用低16位地址線A0-A15來尋址。連續兩個8bit的端口可以組成一個16bit的端口,連續4個組成一個?32bit的端口。I/O地址空間和CPU的物理地址空間是兩個不同的概念,例如I/O地址空間為64K,一個32bit的CPU物理地址空間是4G。?如,在Intel?8086+Redhat9.0?下用“more?/proc/ioports”可看到:

0000-001f?:?dma1

0020-003f?:?pic1

0040-005f?:?timer

0060-006f?:?keyboard

0070-007f?:?rtc

0080-008f?:?dma?page?reg

00a0-00bf?:?pic2

00c0-00df?:?dma2

00f0-00ff?:?fpu

0170-0177?:?ide1

……

不過Intel?x86平臺普通使用了名為內存映射(MMIO)的技術,該技術是PCI規范的一部分,IO設備端口被映射到內存空間,映射后,CPU訪問IO端口就如同訪?問內存一樣。看Intel?TA?719文檔給出的x86/x64系統典型內存地址分配表:

系統資源??占用

------------------------------------------------------------------------

BIOS??1M

本地APIC??4K

芯片組保留?2M

IO?APIC??4K

PCI設備??256M

PCI?Express設備?256M

PCI設備(可選)?256M

顯示幀緩存?16M

TSEG??1M

對于某一既定的系統,它要么是獨立編址、要么是統一編址,具體采用哪一種則取決于CPU的體系結構。?如,PowerPC、m68k等采用統一編址,而X86等則采用獨立編址,存在IO空間的概念。目前,大多數嵌入式微控制器如ARM、PowerPC等并?不提供I/O空間,僅有內存空間,可直接用地址、指針訪問。但對于Linux內核而言,它可能用于不同的CPU,所以它必須都要考慮這兩種方式,于是它采?用一種新的方法,將基于I/O映射方式的或內存映射方式的I/O端口通稱為“I/O區域”(I/O?region),不論你采用哪種方式,都要先申請IO區域:request_resource(),結束時釋放?它:release_resource()。

2)對外設的訪問

1、訪問I/O內存的流程是:request_mem_region()?->?ioremap()?->?ioread8()/iowrite8()?->?iounmap()?->?release_mem_region()?。

前面說過,IO內存是統一編址下的概念,對于統一編址,IO地址空間是物理主存的一部分,對于編程而言,我們只能操作虛擬內存,所以,訪問的第一步就是要把設備所處的物理地址映射到虛擬地址,Linux2.6下用ioremap():

void?*ioremap(unsigned?long?offset,?unsigned?long?size);

然后,我們可以直接通過指針來訪問這些地址,但是也可以用Linux內核的一組函數來讀寫:

ioread8(),?iowrite16(),?ioread8_rep(),?iowrite8_rep()......

2、訪問I/O端口

訪問IO端口有2種途徑:I/O映射方式(I/O-mapped)、內存映射方式(Memory-mapped)。前一種途徑不映射到內存空間,直接使用?intb()/outb()之類的函數來讀寫IO端口;后一種MMIO是先把IO端口映射到IO內存(“內存空間”),再使用訪問IO內存的函數來訪問?IO端口。

void?ioport_map(unsigned?long?port,?unsigned?int?count);

通過這個函數,可以把port開始的count個連續的IO端口映射為一段“內存空間”,然后就可以在其返回的地址是像訪問IO內存一樣訪問這些IO端口。

Linux下的IO端口和IO內存

CPU對外設端口物理地址的編址方式有兩種:一種是IO映射方式,另一種是內存映射方式。

Linux將基于IO映射方式的和內存映射方式的IO端口統稱為IO區域(IO region)。

IO region仍然是一種IO資源,因此它仍然可以用resource結構類型來描述。

Linux管理IO region:

1) request_region()

把一個給定區間的IO端口分配給一個IO設備。

2) check_region()

檢查一個給定區間的IO端口是否空閑,或者其中一些是否已經分配給某個IO設備。

3) release_region()

釋放以前分配給一個IO設備的給定區間的IO端口。

Linux中可以通過以下輔助函數來訪問IO端口:

inb(),inw(),inl(),outb(),outw(),outl()

“b”“w”“l”分別代表8位,16位,32位。

對IO內存資源的訪問

1) request_mem_region()

請求分配指定的IO內存資源。

2) check_mem_region()

檢查指定的IO內存資源是否已被占用。

3) release_mem_region()

釋放指定的IO內存資源。

其中傳給函數的start address參數是內存區的物理地址(以上函數參數表已省略)。

驅動開發人員可以將內存映射方式的IO端口和外設內存統一看作是IO內存資源。

ioremap()用來將IO資源的物理地址映射到內核虛地址空間(3GB - 4GB)中,參數addr是指向內核虛地址的指針。

Linux中可以通過以下輔助函數來訪問IO內存資源:

readb(),readw(),readl(),writeb(),writew(),writel()。

Linux在kernel/resource.c文件中定義了全局變量ioport_resource和iomem_resource,來分別描述基于IO映射方式的整個IO端口空間和基于內存映射方式的IO內存資源空間(包括IO端口和外設內存)。

1)關于IO與內存空間:

在X86處理器中存在著I/O空間的概念,I/O空間是相對于內存空間而言的,它通過特定的指令in、out來訪問。端口號標識了外設的寄存器地址。Intel語法的in、out指令格式為:

IN 累加器, {端口號│DX}

OUT {端口號│DX},累加器

目前,大多數嵌入式微控制器如ARM、PowerPC等中并不提供I/O空間,而僅存在內存空間。內存空間可以直接通過地址、指針來訪問,程序和程序運行中使用的變量和其他數據都存在于內存空間中。

即便是在X86處理器中,雖然提供了I/O空間,如果由我們自己設計電路板,外設仍然可以只掛接在內存空間。此時,CPU可以像訪問一個內存單元那樣訪問外設I/O端口,而不需要設立專門的I/O指令。因此,內存空間是必須的,而I/O空間是可選的。

(2)inb和outb:

在Linux設備驅動中,宜使用Linux內核提供的函數來訪問定位于I/O空間的端口,這些函數包括:

· 讀寫字節端口(8位寬)

unsigned inb(unsigned port);

void outb(unsigned char byte, unsigned port);

· 讀寫字端口(16位寬)

unsigned inw(unsigned port);

void outw(unsigned short word, unsigned port);

· 讀寫長字端口(32位寬)

unsigned inl(unsigned port);

void outl(unsigned longword, unsigned port);

· 讀寫一串字節

void insb(unsigned port, void *addr, unsigned long count);

void outsb(unsigned port, void *addr, unsigned long count);

· insb()從端口port開始讀count個字節端口,并將讀取結果寫入addr指向的內存;outsb()將addr指向的內存的count個字節連續地寫入port開始的端口。

· 讀寫一串字

void insw(unsigned port, void *addr, unsigned long count);

void outsw(unsigned port, void *addr, unsigned long count);

· 讀寫一串長字

void insl(unsigned port, void *addr, unsigned long count);

void outsl(unsigned port, void *addr, unsigned long count);

上述各函數中I/O端口號port的類型高度依賴于具體的硬件平臺,因此,只是寫出了unsigned。

來源:

http://blog.csdn.net/zyhorse2010/article/details/6590488

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/273038.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/273038.shtml
英文地址,請注明出處:http://en.pswp.cn/news/273038.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

單例模式 創建對象

兩種選擇 1 使用pthread_once, once是類的成員變量 只執行一次Create create的作用是創建一個對象 2 使用 static lock 如下所示,注意lock必須是static的,否則是局部變量,每個線程都有自己的lock,無法保證只執行一次。…

Linux c編譯庫路徑,【一點一點學Linux C】交叉編譯時候如何配置連接庫的搜索路徑...

交叉編譯的時候不能使用本地(i686機器,即PC機器,研發機器)機器上的庫,但是在做編譯鏈接的時候默認的是使用本地庫,即/usr/lib,/lib兩個目錄。因此,在交叉編譯的時候,要采取一些方法使得在編譯鏈接的時候找到…

[NBUT 1458 Teemo]區間第k大問題,劃分樹

裸的區間第k大問題&#xff0c;劃分樹搞起。 #pragma comment(linker, "/STACK:10240000") #include <map> #include <set> #include <cmath> #include <ctime> #include <deque> #include <queue> #include <stack> #inc…

Linux的軟件包封裝格式有,linux軟件安裝包詳解---全

詳細介紹了常見的四種Linux應用軟件安裝包及其安裝方法。一、解析Linux應用軟件安裝包&#xff0c;通常Linux應用軟件的安裝包有四種&#xff1a;1) tar包&#xff0c;如software-1.2.3-1.tar.gz。他是使用UNIX系統的打包工具tar打包的。2) rpm包&#xff0c;如software-1.2.3-…

人生的第一個博客(●'?'●)??--開博典禮

嘛&#xff0c;說實話&#xff0c;現在才開始&#xff0c;實在是有點晚了&#xff0c;一不小心大學都過去1年了_(:3 」∠)_ 我在專業方面的起步也是相當晚的&#xff0c;身為計算機專業&#xff0c;編程卻從大學才開始正式接觸&#xff0c;進入大學時其他方面的能力也都約等于0…

linux查看運行鐘的tomcat,linux查看tomcat啟動運行日志

Linux0&period;11內核--進程調度分析之2&period;調度[版權所有,轉載請注明出處.出處:http://www.cnblogs.com/joey-hua/p/5596830.html ] 上一篇說到進程調度歸根結底是調用timer_interrupt函數, ...iReport 下載地址iReport 下載地址: https://osdn.jp/projects/sfnet…

8月面試題目收錄

面試題收錄 常見兼容性問題&#xff1f; * png24位的圖片在iE6瀏覽器上出現背景&#xff0c;解決方案是做成PNG8.* 瀏覽器默認的margin和padding不同。解決方案是加一個全局的*{margin:0;padding:0;}來統一。* IE6雙邊距bug:塊屬性標簽float后&#xff0c;又有橫行的margin情況…

linux如何升級php版本升級,Linux?升級php版本

近來因工作需要,又沒有服務器維護人員,只能自己上陣啦。從php5.3.28->5.5.30,先自己下載php包到/usr/local/下?&#xff0c;# 解壓縮安裝包tar zxvf php-5.5.30.tar.gz# 進入目錄cd php-5.5.30// 編譯的時候一定要加入參數--enable-fpm#./configure --prefix/usr/local/php…

opencv配置

OpenCV的簡單安裝和一次性配置在這里就不贅述了&#xff0c;網上教程很多&#xff0c;可以參考一下這個鏈接里面的教程http://wenku.baidu.com/view/3b40de25453610661ed9f46b.html。 但是很多情況下面&#xff0c;我們新建一個項目就要重新配置一次OpenCV&#xff0c;那就相當…

linux ftp 工作過程,linux中ftp的安裝過程記錄[運維篇]

安裝FTP的全過程記錄&#xff0c;對于相同情況希望有所幫助。【centOS】1、查詢本機是否安裝vsftpd: rpm -qa |grep vsftpd &#xff1b;2、安裝ftp服務 yum install vsftpd;3、開啟ftp服務 chkconfig vsftpd on&#xff0c;開機啟動&#xff1b;4、手動操作ftp服務&#xff0c…

代碼命名,代碼里的命名規則:錯誤的和正確的對比 命名方法總結 “自我描述的源代碼”用代碼表達出你的思想,讓其他人通過代碼能明白你的意圖。...

http://www.aqee.net/express-names-in-code-bad-vs-clean/ 編程初學者總是把大量的時間用在學習編程語言&#xff0c;語法&#xff0c;技巧和編程工具的使用上。他們認為&#xff0c;如果掌握了這些技術技巧&#xff0c;他們就能成為不錯的程序員。然而&#xff0c;計算機編程…

linux 動態執行cp,Linux常用命令之cp、mv、rm、cat、more、head、tail、ln命令講解

上一章節中&#xff0c;我們了解到了Linux系統的最基礎的幾個文件處理命令&#xff0c;核心的是ls命令&#xff0c;在今天這章中&#xff0c;我們來繼續學習Linux對于文件操作相關的一些命令&#xff0c;比如復制、移動、刪除、查看等命令。1、cp 命令解釋命令名稱&#xff1a;…

使用DBI(perl)實現文本文件的導入導出mysql

DBI 是perl腳本連接數據庫的一個模塊。perl腳本相對shell更靈活&#xff0c;功能更強大&#xff0c;跨平臺能力強。相對可執行jar包要簡單很多。 ?1、下載安裝包DBI-1.631.tar.gzperl腳本下載的網站http://www.cpan.org/ 很多perl的組件都可以在這個網站上下載 2、解壓tar -xz…

linux 車載視頻監控,基于Linux平臺車載視頻監控系統研發-計算機科學與技術專業論文.docx...

基于Linux平臺車載視頻監控系統研發-計算機科學與技術專業論文目錄HYPERLINK \l "_bookmark0" 第一章 緒論1 HYPERLINK \l "_bookmark1" 1.1 研究背景1 HYPERLINK \l "_bookmark2" 1.2 研究動態1 HYPERLINK \l "_bookmark3" 1.3 本文工…

Linux鼠標回報率修改,鼠標回報率怎么調? 設置鼠標回報率的三種方法

鼠標回報率如何設置呢&#xff1f;鼠標回報率又稱刷新率&#xff0c;是指鼠標MCU與電腦傳輸數據頻率。鼠標回報率對于游戲玩家而言至關重要&#xff0c;但同時鼠標回報率與電腦性能息息相關。只有電腦硬件性能良好&#xff0c;才能適當提升鼠標回報率&#xff0c;以實現更高的鼠…

linux下vi修改文件用法

進入vi的命令 vi filename :打開或新建文件&#xff0c;并將光標置于第一行首 vi n filename &#xff1a;打開文件&#xff0c;并將光標置于第n行首 vi filename &#xff1a;打開文件&#xff0c;并將光標置于最后一行首 vi /pattern filename&#xff1a;打開文件&#xff…

linux在芯片設計與實現,基于Linux的Atheros無線芯片網卡驅動的設計與實現

Design and Implementation of Linux based Atheros wireless network cards driverDU Qingbo1杜清波(1985-)&#xff0c;男&#xff0c;碩士研究生&#xff0c;主要研究方向&#xff1a;嵌入式系統與網絡通信1、School of Computer Science,Beijing University of Posts and T…

[轉載]孫婧妍:高考語文148分是這樣煉成的(附:孫婧妍

原文地址&#xff1a;孫婧妍&#xff1a;高考語文148分是這樣煉成的(附&#xff1a;孫婧妍2013高考作文《手機論》)作者&#xff1a; 語文新高考高考語文148分是這樣煉成的 (附&#xff1a;孫婧妍2013高考作文《手機論》) 來源&#xff1a;網絡 作者&#xff1a;孫婧妍…

linux ps 命令安裝,Linux上安裝pstree命令(-bash: pstree: command not found)

一、pstree命令的安裝1、在Mac OS上brew install pstree2、在Fedora/Red Hat/CentOSyum -y install psmisc3、在 Ubuntu/Debianapt-get install psmisc二、pstree命令詳解pstree指令用ASCII字符顯示樹狀結構&#xff0c;清楚地表達程序間的相互關系。如果不指定程序識別碼或用戶…

c語言字符串逆置,字符串逆置

滿意答案9n7j5j3m4o2013.12.03采納率&#xff1a;49% 等級&#xff1a;11已幫助&#xff1a;15198人47911 zxl0714 1358 Accepted 164K 15MS G 0.46K 2007-04-08 10:32:38#include using namespace std;void reverse(char* ch){int i, len;char tmp;len strlen( ch );for (…