自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Linux設(shè)備驅(qū)動程序--與硬件通信

運維 系統(tǒng)運維
外設(shè)要與I\O總線匹配,而大部分流行的 I/O 總線是基于個人計算機(jī)模型(主要是 x86 家族:它為讀和寫 I/O 端口提供了獨立的線路和特殊的 CPU 指令),所以即便那些沒有單獨I/O 端口地址空間的處理器,在訪問外設(shè)時也要模擬成讀寫I\O端口。

I/O 端口和 I/O 內(nèi)存

每種外設(shè)都是通過讀寫寄存器來進(jìn)行控制。

在硬件層,內(nèi)存區(qū)和 I/O 區(qū)域沒有概念上的區(qū)別: 它們都是通過向在地址總線和控制總線發(fā)出電平信號來進(jìn)行訪問,再通過數(shù)據(jù)總線讀寫數(shù)據(jù)。

因為外設(shè)要與I\O總線匹配,而大部分流行的 I/O 總線是基于個人計算機(jī)模型(主要是 x86 家族:它為讀和寫 I/O 端口提供了獨立的線路和特殊的 CPU 指令),所以即便那些沒有單獨I/O 端口地址空間的處理器,在訪問外設(shè)時也要模擬成讀寫I\O端口。這一功能通常由外圍芯片組(PC 中的南北橋)或 CPU 中的附加電路實現(xiàn)(嵌入式中的方法) 。

Linux 在所有的計算機(jī)平臺上實現(xiàn)了 I/O 端口。但不是所有的設(shè)備都將寄存器映射到

I/O 端口。雖然ISA設(shè)備普遍使用 I/O 端口,但大部分 PCI 設(shè)備則把寄存器映射到某個內(nèi)存地址區(qū),這種 I/O

內(nèi)存方法通常是首選的。因為它無需使用特殊的處理器指令,CPU

核訪問內(nèi)存更有效率,且編譯器在訪問內(nèi)存時在寄存器分配和尋址模式的選擇上有更多自由。

I/O 寄存器和常規(guī)內(nèi)存

在進(jìn)入這部分學(xué)習(xí)的時候,首先要理解一個概念:side

effect,書中譯為邊際效應(yīng),第二版譯為副作用。我覺得不管它是怎么被翻譯的,都不可能精準(zhǔn)表達(dá)原作者的意思,所以我個人認(rèn)為記住side

effect就好。下面來講講side effect的含義。我先貼出兩個網(wǎng)上已有的兩種說法(在這里謝謝兩位高人的分享):

第一種說法:

3. side effect(譯為邊際效應(yīng)或副作用):是指讀取某個地址時可能導(dǎo)致該地址內(nèi)容發(fā)生變化,比如,有些設(shè)備的中斷狀態(tài)寄存器只要一讀取,便自動清零。I/O寄存器的操作具有side effect,因此,不能對其操作不能使用cpu緩存。

原文網(wǎng)址:

http://qinbh.blog.sohu.com/62733495.html

第二種說法:

說一下我的理解:I/O端口與實際外部設(shè)備相關(guān)聯(lián),通過訪問I/O端口控制外部設(shè)備,“邊際效應(yīng)”是指控制設(shè)備(讀取或?qū)懭耄┥?,訪問I/O口的

主要目的就是邊際效應(yīng),不像訪問普通的內(nèi)存,只是在一個位置存儲或讀取一個數(shù)值,沒有別的含義了。我是基于arm平臺理解的,在《linux設(shè)備驅(qū)動程

序》第二版中的說法是“副作用”,不是“邊際效應(yīng)”。

原文網(wǎng)址:

linux.chinaunix.net/bbs/viewthread.php?tid=890636&page=1#pid6312646">http://linux.chinaunix.net/bbs/viewthread.php?tid=890636&page=1#pid6312646

結(jié)合以上兩種說法和自己看《Linux設(shè)備驅(qū)動程序(第3版)》的理解,我個人認(rèn)為可以這樣解釋:

side effect

是指:訪問I/O寄存器時,不僅僅會像訪問普通內(nèi)存一樣影響存儲單元的值,更重要的是它可能改變CPU的I/O端口電平、輸出時序或CPU對I/O端口電

平的反應(yīng)等等,從而實現(xiàn)CPU的控制功能。CPU在電路中的意義就是實現(xiàn)其side effect 。

I/O 寄存器和 RAM 的主要不同就是 I/O 寄存器操作有side effect, 而內(nèi)存操作沒有。

因為存儲單元的訪問速度對 CPU 性能至關(guān)重要,編譯器會對源代碼進(jìn)行優(yōu)化,主要是: 使用高速緩存保存數(shù)值 和 重新編排讀/寫指令順序。但對I/O 寄存器操作來說,這些優(yōu)化可能造成致命錯誤。因此,驅(qū)動程序必須確保在操作I/O 寄存器時,不使用高速緩存,且不能重新編排讀/寫指令順序。

解決方法:

硬件緩存問題:只要把底層硬件配置(自動地或者通過 Linux 初始化代碼)成當(dāng)訪問 I/O 區(qū)域時(不管內(nèi)存還是端口)禁止硬件緩存即可。

硬件指令重新排序問題:在硬件(或其他處理器)必須以一個特定順序執(zhí)行的操作之間設(shè)置內(nèi)存屏障(memory barrier)。

#p#

Linux 提供以下宏來解決所有可能的排序問題:

#include linux/kernel.h>

void barrier(void) /*告知編譯器插入一個內(nèi)存屏障但是對硬件沒有影響。編譯后的代碼會將當(dāng)前CPU 寄存器中所有修改過的數(shù)值保存到內(nèi)存中, 并當(dāng)需要時重新讀取它們??勺柚乖谄琳锨昂蟮木幾g器優(yōu)化,但硬件能完成自己的重新排序。其實linux/kernel.h> 中并沒有這個函數(shù),因為它是在kernel.h包含的頭文件compiler.h中定義的*/

#include linux/compiler.h>

# define barrier() __memory_barrier()

#include asm/system.h>

void rmb(void); /*保證任何出現(xiàn)于屏障前的讀在執(zhí)行任何后續(xù)的讀之前完成*/

void wmb(void); /*保證任何出現(xiàn)于屏障前的寫在執(zhí)行任何后續(xù)的寫之前完成*/

void mb(void); /*保證任何出現(xiàn)于屏障前的讀寫操作在執(zhí)行任何后續(xù)的讀寫操作之前完成*/

void read_barrier_depends(void); /*

一種特殊的、弱些的讀屏障形式。rmb 阻止屏障前后的所有讀指令的重新排序,read_barrier_depends

只阻止依賴于其他讀指令返回的數(shù)據(jù)的讀指令的重新排序。區(qū)別微小, 且不在所有體系中存在。除非你確切地理解它們的差別,

并確信完整的讀屏障會增加系統(tǒng)開銷,否則應(yīng)當(dāng)始終使用 rmb。*/

/*以上指令是barrier的超集*/

void smp_rmb(void);

void smp_read_barrier_depends(void);

void smp_wmb(void);

void smp_mb(void);

/*僅當(dāng)內(nèi)核為 SMP 系統(tǒng)編譯時插入硬件屏障; 否則, 它們都擴(kuò)展為一個簡單的屏障調(diào)用。*/

典型的應(yīng)用:

writel(dev->registers.addr, io_destination_address);

writel(dev->registers.size, io_size);

writel(dev->registers.operation, DEV_READ);

wmb();/*類似一條分界線,上面的寫操作必然會在下面的寫操作前完成,但是上面的三個寫操作的排序無法保證*/

writel(dev->registers.control, DEV_GO);

內(nèi)存屏障影響性能,所以應(yīng)當(dāng)只在確實需要它們的地方使用。不同的類型對性能的影響也不同,因此要盡可能地使用需要的特定類型。值得注意的是大部分處理同步的內(nèi)核原語,例如自旋鎖和atomic_t,也可作為內(nèi)存屏障使用。

某些體系允許賦值和內(nèi)存屏障組合,以提高效率。它們定義如下:

#define set_mb(var, value) do {var = value; mb();} while 0

/*以下宏定義在arm體系中不存在*/

#define set_wmb(var, value) do {var = value; wmb();} while 0

#define set_rmb(var, value) do {var = value; rmb();} while 0

使用do...while 結(jié)構(gòu)來構(gòu)造宏是標(biāo)準(zhǔn) C 的慣用方法,它保證了擴(kuò)展后的宏可在所有上下文環(huán)境中被作為一個正常的 C 語句執(zhí)行。

使用 I/O 端口

I/O 端口是驅(qū)動用來和許多設(shè)備之間的通訊方式。

I/O 端口分配

在尚未取得端口的獨占訪問前,不應(yīng)對端口進(jìn)行操作。內(nèi)核提供了一個注冊用的接口,允許驅(qū)動程序聲明它需要的端口:

#include linux/ioport.h>

struct resource *request_region(unsigned long first, unsigned long n, const char *name);/*告訴內(nèi)核:要使用從 first 開始的 n 個端口,name 參數(shù)為設(shè)備名。若分配成功返回非 NULL,否則將無法使用需要的端口。*/

/*所有的的端口分配顯示在 /proc/ioports 中。若不能分配到需要的端口,則可以到這里看看誰先用了。*/

/*當(dāng)用完 I/O 端口集(可能在模塊卸載時), 應(yīng)當(dāng)將它們返回給系統(tǒng)*/

void release_region(unsigned long start, unsigned long n);

int check_region(unsigned long first, unsigned long n);

/*檢查一個給定的 I/O 端口集是否可用,若不可用, 返回值是一個負(fù)錯誤碼。不推薦使用*/

操作 I/O 端口

在驅(qū)動程序注冊I/O 端口后,就可以讀/寫這些端口。大部分硬件會把8、16和32位端口區(qū)分開,不能像訪問系統(tǒng)內(nèi)存那樣混淆使用。驅(qū)動必須調(diào)用不同的函數(shù)來存取不同大小的端口。

只支持內(nèi)存映射的 I/O 寄存器的計算機(jī)體系通過重新映射I/O端口到內(nèi)存地址來偽裝端口I/O。為了提高移植性,內(nèi)核向驅(qū)動隱藏了這些細(xì)節(jié)。Linux 內(nèi)核頭文件(體系依賴的頭文件 ) 定義了下列內(nèi)聯(lián)函數(shù)(有的體系是宏,有的不存在)來訪問 I/O 端口:

unsigned inb(unsigned port);

void outb(unsigned char byte, unsigned port);

/*讀/寫字節(jié)端口( 8 位寬 )。port 參數(shù)某些平臺定義為 unsigned long ,有些為 unsigned short 。 inb 的返回類型也體系而不同。*/

unsigned inw(unsigned port);

void outw(unsigned short word, unsigned port);

/*訪問 16位 端口( 一個字寬 )*/

unsigned inl(unsigned port);

void outl(unsigned longword, unsigned port);

/*訪問 32位 端口。 longword 聲明有的平臺為 unsigned long ,有的為 unsigned int。*/

在用戶空間訪問 I/O 端口

以上函數(shù)主要提供給設(shè)備驅(qū)動使用,但它們也可在用戶空間使用,至少在 PC上可以。 GNU C 庫在  中定義了它們。如果在用戶空間代碼中使用必須滿足以下條件:

(1)程序必須使用 -O 選項編譯來強(qiáng)制擴(kuò)展內(nèi)聯(lián)函數(shù)。

(2)必須用ioperm 和 iopl 系統(tǒng)調(diào)用(#include ) 來獲得對端口 I/O 操作的權(quán)限。ioperm 為獲取單獨端口操作權(quán)限,而 iopl 為整個 I/O 空間的操作權(quán)限。 (x86 特有的)

(3)程序以 root 來調(diào)用 ioperm 和 iopl,或是其父進(jìn)程必須以 root 獲得端口操作權(quán)限。(x86 特有的)

若平臺沒有 ioperm 和 iopl 系統(tǒng)調(diào)用,用戶空間可以仍然通過使用 /dev/prot 設(shè)備文件訪問 I/O 端口。注意:這個文件的定義是體系相關(guān)的,并且I/O 端口必須先被注冊。

串操作

除了一次傳輸一個數(shù)據(jù)的I/O操作,一些處理器實現(xiàn)了一次傳輸一個數(shù)據(jù)序列的特殊指令,序列中的數(shù)據(jù)單位可以是字節(jié)、字或雙字,這是所謂的串操作指

令。它們完成任務(wù)比一個 C 語言循環(huán)更快。下列宏定義實現(xiàn)了串I/O,它們有的通過單個機(jī)器指令實現(xiàn);但如果目標(biāo)處理器沒有進(jìn)行串 I/O

的指令,則通過執(zhí)行一個緊湊的循環(huán)實現(xiàn)。 有的體系的原型如下:

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

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

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);

使用時注意: 它們直接將字節(jié)流從端口中讀取或?qū)懭搿.?dāng)端口和主機(jī)系統(tǒng)有不同的字節(jié)序時,會導(dǎo)致不可預(yù)期的結(jié)果。 使用 inw 讀取端口應(yīng)在必要時自行轉(zhuǎn)換字節(jié)序,以匹配主機(jī)字節(jié)序。

暫停式 I/O

為了匹配低速外設(shè)的速度,有時若 I/O 指令后面還緊跟著另一個類似的I/O指令,就必須在 I/O 指令后面插入一個小延時。在

這種情況下,可以使用暫停式的I/O函數(shù)代替通常的I/O函數(shù),它們的名字以 _p 結(jié)尾,如 inb_p、outb_p等等。

這些函數(shù)定義被大部分體系支持,盡管它們常常被擴(kuò)展為與非暫停式I/O

同樣的代碼。因為如果體系使用一個合理的現(xiàn)代外設(shè)總線,就沒有必要額外暫停。細(xì)節(jié)可參考平臺的 asm 子目錄的 io.h

文件。以下是include\asm-arm\io.h中的宏定義:

#define outb_p(val,port)    outb((val),(port))

#define outw_p(val,port)    outw((val),(port))

#define outl_p(val,port)    outl((val),(port))

#define inb_p(port)        inb((port))

#define inw_p(port)        inw((port))

#define inl_p(port)        inl((port))

#define outsb_p(port,from,len)    outsb(port,from,len)

#define outsw_p(port,from,len)    outsw(port,from,len)

#define outsl_p(port,from,len)    outsl(port,from,len)

#define insb_p(port,to,len)    insb(port,to,len)

#define insw_p(port,to,len)    insw(port,to,len)

#define insl_p(port,to,len)    insl(port,to,len)

由此可見,由于arm使用內(nèi)部總線,就沒有必要額外暫停,所以暫停式的I/O函數(shù)被擴(kuò)展為與非暫停式I/O 同樣的代碼。

#p#

平臺相關(guān)性

由于自身的特性,I/O 指令與處理器密切相關(guān)的,非常難以隱藏系統(tǒng)間的不同。所以大部分的關(guān)于端口 I/O 的源碼是平臺依賴的。以下是x86和arm所使用函數(shù)的總結(jié):

IA-32 (x86)

x86_64

這個體系支持所有的以上描述的函數(shù),端口號是 unsigned short 類型。

arm

端口映射到內(nèi)存,支持所有函數(shù)。串操作 用C語言實現(xiàn)。端口是 unsigned int 類型。

使用 I/O 內(nèi)存

除了 x86上普遍使用的I/O

端口外,和設(shè)備通訊另一種主要機(jī)制是通過使用映射到內(nèi)存的寄存器或設(shè)備內(nèi)存,統(tǒng)稱為 I/O 內(nèi)存。因為寄存器和內(nèi)存之間的區(qū)別對軟件是透明的。I/O

內(nèi)存僅僅是類似 RAM 的一個區(qū)域,處理器通過總線訪問這個區(qū)域,以實現(xiàn)設(shè)備的訪問。

根據(jù)平臺和總線的不同,I/O

內(nèi)存可以就是否通過頁表訪問分類。若通過頁表訪問,內(nèi)核必須首先安排物理地址使其對設(shè)備驅(qū)動程序可見,在進(jìn)行任何 I/O 之前必須調(diào)用

ioremap。若不通過頁表,I/O 內(nèi)存區(qū)域就類似I/O 端口,可以使用適當(dāng)形式的函數(shù)訪問它們。因為“side effect”的影響,不管是否需要 ioremap ,都不鼓勵直接使用 I/O 內(nèi)存的指針。而使用專用的 I/O 內(nèi)存操作函數(shù),不僅在所有平臺上是安全,而且對直接使用指針操作 I/O 內(nèi)存的情況進(jìn)行了優(yōu)化。

I/O 內(nèi)存分配和映射

I/O 內(nèi)存區(qū)域使用前必須先分配,函數(shù)接口在 定義:

struct resource *request_mem_region(unsigned long start, unsigned long len, char *name);/* 從 start 開始,分配一個 len 字節(jié)的內(nèi)存區(qū)域。成功返回一個非NULL指針,否則返回NULL。所有的 I/O 內(nèi)存分配情況都 /proc/iomem 中列出。*/

/*I/O內(nèi)存區(qū)域在不再需要時應(yīng)當(dāng)釋放*/

void release_mem_region(unsigned long start, unsigned long len);

/*一個舊的檢查 I/O 內(nèi)存區(qū)可用性的函數(shù),不推薦使用*/

int check_mem_region(unsigned long start, unsigned long len);

然后必須設(shè)置一個映射,由 ioremap 函數(shù)實現(xiàn),此函數(shù)專門用來為I/O

內(nèi)存區(qū)域分配虛擬地址。經(jīng)過ioremap 之后,設(shè)備驅(qū)動即可訪問任意的 I/O 內(nèi)存地址。注意:ioremap

返回的地址不應(yīng)當(dāng)直接引用;應(yīng)使用內(nèi)核提供的 accessor 函數(shù)。以下為函數(shù)定義:

#include asm/io.h>

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

void *ioremap_nocache(unsigned long phys_addr, unsigned long size);/*如果控制寄存器也在該區(qū)域,應(yīng)使用的非緩存版本,以實現(xiàn)side effect。*/

void iounmap(void * addr);

訪問I/O 內(nèi)存

訪問I/O 內(nèi)存的正確方式是通過一系列專用于此目的的函數(shù)(在 中定義的):

/*I/O 內(nèi)存讀函數(shù)*/

unsigned int ioread8(void *addr);

unsigned int ioread16(void *addr);

unsigned int ioread32(void *addr);

/*addr 是從 ioremap 獲得的地址(可能包含一個整型偏移量), 返回值是從給定 I/O 內(nèi)存讀取的值*/

/*對應(yīng)的I/O 內(nèi)存寫函數(shù)*/

void iowrite8(u8 value, void *addr);

void iowrite16(u16 value, void *addr);

void iowrite32(u32 value, void *addr);

/*讀和寫一系列值到一個給定的 I/O 內(nèi)存地址,從給定的 buf 讀或?qū)?count 個值到給定的 addr */

void ioread8_rep(void *addr, void *buf, unsigned long count);

void ioread16_rep(void *addr, void *buf, unsigned long count);

void ioread32_rep(void *addr, void *buf, unsigned long count);

void iowrite8_rep(void *addr, const void *buf, unsigned long count);

void iowrite16_rep(void *addr, const void *buf, unsigned long count);

void iowrite32_rep(void *addr, const void *buf, unsigned long count);

/*需要操作一塊 I/O 地址,使用一下函數(shù)*/

void memset_io(void *addr, u8 value, unsigned int count);

void memcpy_fromio(void *dest, void *source, unsigned int count);

void memcpy_toio(void *dest, void *source, unsigned int count);

/*舊函數(shù)接口,仍可工作, 但不推薦。*/

unsigned readb(address);

unsigned readw(address);

unsigned readl(address);

void writeb(unsigned value, address);

void writew(unsigned value, address);

void writel(unsigned value, address);

像 I/O 內(nèi)存一樣使用端口

一些硬件有一個有趣的特性:一些版本使用 I/O 端口,而其他的使用 I/O 內(nèi)存。為了統(tǒng)一編程接口,使驅(qū)動程序易于編寫,2.6 內(nèi)核提供了一個ioport_map函數(shù):

void *ioport_map(unsigned long port, unsigned int count);/*重映射 count 個I/O 端口,使其看起來像 I/O 內(nèi)存。,此后,驅(qū)動程序可以在返回的地址上使用 ioread8 和同類函數(shù)。其在編程時消除了I/O 端口和I/O 內(nèi)存的區(qū)別。

/*這個映射應(yīng)當(dāng)在它不再被使用時撤銷:*/

void ioport_unmap(void *addr);

/*注意:I/O 端口仍然必須在重映射前使用 request_region 分配I/O 端口。arm9不支持這兩個函數(shù)!*/

上面是基于《Linux設(shè)備驅(qū)動程序(第3版)》的介紹,以下分析 arm9的s3c2440A的linux驅(qū)動接口。

arm9的linux驅(qū)動接口

s3c24x0處理器是使用I/O內(nèi)存的,也就是說:他們的外設(shè)接口是通過讀寫相應(yīng)的寄存器實現(xiàn)的,這些寄存器和內(nèi)存是使用單一的地址空間,并使用和讀寫內(nèi)存一樣的指令。所以推薦使用I/O內(nèi)存的相關(guān)指令。

但這并不表示I/O端口的指令在s3c24x0中不可用。但是只要你注意其源碼,你就會發(fā)現(xiàn):其實I/O端口的指令只是一個外殼,內(nèi)部還是使用和I/O內(nèi)存一樣的代碼。以下列出一些:

I/O端口

#define outb(v,p)        __raw_writeb(v,__io(p))

#define outw(v,p)        __raw_writew((__force __u16) \

cpu_to_le16(v),__io(p))

#define outl(v,p)        __raw_writel((__force __u32) \

cpu_to_le32(v),__io(p))

#define inb(p)    ({ __u8 __v = __raw_readb(__io(p)); __v; })

#define inw(p)    ({ __u16 __v = le16_to_cpu((__force __le16) \

__raw_readw(__io(p))); __v; })

#define inl(p)    ({ __u32 __v = le32_to_cpu((__force __le32) \

__raw_readl(__io(p))); __v; })

I/O內(nèi)存

#define ioread8(p)    ({ unsigned int __v = __raw_readb(p); __v; })

#define ioread16(p)    ({ unsigned int __v = le16_to_cpu(__raw_readw(p)); __v; })

#define ioread32(p)    ({ unsigned int __v = le32_to_cpu(__raw_readl(p)); __v; })

#define iowrite8(v,p)    __raw_writeb(v, p)

#define iowrite16(v,p)    __raw_writew(cpu_to_le16(v), p)

#define iowrite32(v,p)    __raw_writel(cpu_to_le32(v), p)

我對I/O端口的指令和I/O內(nèi)存的指令都寫了相應(yīng)的驅(qū)動程序,都通過了測試。在這里值得注意的有4點:

(1)所有的讀寫指令所賦的地址必須都是虛擬地址,你有兩種選擇:使用內(nèi)核已經(jīng)定

義好的地址,如

S3C2440_GPJCON等等,這些都是內(nèi)核定義好的虛擬地址,有興趣的可以看源碼。還有一種方法就是使用自己用ioremap映射的虛擬地址。絕對

不能使用實際的物理地址,否則會因為內(nèi)核無法處理地址而出現(xiàn)oops。

(2)在使用I/O指令時,可以不使用request_region和request_mem_region,而直接使用outb、ioread等指令。因為request的功能只是告訴內(nèi)核端口被誰占用了,如再次request,內(nèi)核會制止。

(3)在使用I/O指令時,所賦的地址數(shù)據(jù)有時必須通過強(qiáng)制類型轉(zhuǎn)換為 unsigned long ,不然會有警告(具體原因請看

Linux設(shè)備驅(qū)動程序?qū)W習(xí)(7)-內(nèi)核的數(shù)據(jù)類型

) 。雖然你的程序可能也可以使用,但是最好還是不要有警告為妙。

(4)在include\asm-arm\arch-s3c2410\hardware.h中定義了很多io口的操作函數(shù),有需要可以在驅(qū)動中直接使用,很方便。

實驗源碼:

IO_port.tar.gz

IO_port_test.tar.gz

IO_mem.tar.gz

IO_mem_test.tar.gz

兩個模塊都實現(xiàn)了阻塞型獨享設(shè)備的訪問控制,并通知內(nèi)核不支持llseek。具體的測試在IO_port中。

測試現(xiàn)象如下:

[Tekkaman2440@SBC2440V4]#cd /lib/modules/

[Tekkaman2440@SBC2440V4]#insmod IO_port.ko

[Tekkaman2440@SBC2440V4]#insmod IO_mem.ko

[Tekkaman2440@SBC2440V4]#cat /proc/devices

Character devices:

1 mem

2 pty

3 ttyp

4 /dev/vc/0

4 tty

4 ttyS

5 /dev/tty

5 /dev/console

5 /dev/ptmx

7 vcs

10 misc

13 input

14 sound

81 video4linux

89 i2c

90 mtd

116 alsa

128 ptm

136 pts

153 spi

180 usb

189 usb_device

204 s3c2410_serial

251 IO_mem

252 IO_port

253 usb_endpoint

254 rtc

Block devices:

1 ramdisk

【編輯推薦】

  1. 介紹Linux操作系統(tǒng)下的USB硬件設(shè)備驅(qū)動
  2. Linux網(wǎng)絡(luò)設(shè)備驅(qū)動指南
  3. Linux內(nèi)核可裝載模塊對設(shè)備驅(qū)動的影響
責(zé)任編輯:趙寧寧 來源: chinaitlab
相關(guān)推薦

2011-01-10 18:21:38

linux編寫程序

2021-11-29 07:55:45

Linux GPIO Linux 系統(tǒng)

2018-11-26 08:45:29

Linux驅(qū)動程序命令

2022-06-22 10:13:05

開源驅(qū)動程序

2024-03-22 09:54:04

Docker網(wǎng)絡(luò)驅(qū)動容器網(wǎng)絡(luò)

2011-09-08 18:34:33

WindowsXP驅(qū)動程序

2010-01-07 13:27:22

Linux驅(qū)動程序

2010-04-19 10:28:43

Unix操作系統(tǒng)

2013-10-31 16:29:10

Linux內(nèi)核

2010-05-10 15:53:24

Unix系統(tǒng)

2021-11-16 06:55:36

Linux字符設(shè)備

2021-11-22 08:14:23

Linux Linux驅(qū)動Linux 系統(tǒng)

2011-01-06 16:29:08

linuxtasklet機(jī)制

2021-12-06 07:47:36

Linux 驅(qū)動程序Linux 系統(tǒng)

2009-07-06 18:17:46

JDBC驅(qū)動程序

2009-10-23 10:25:27

驅(qū)動程序技巧

2010-04-19 10:18:30

Unix操作系統(tǒng)

2009-11-30 14:51:00

Linux設(shè)置無線網(wǎng)卡

2023-02-23 14:20:36

Linux

2011-08-16 16:32:13

Linux驅(qū)動程序
點贊
收藏

51CTO技術(shù)棧公眾號