新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > 嵌入式Linux設(shè)備驅(qū)動開發(fā)之:字符設(shè)備驅(qū)動編程

嵌入式Linux設(shè)備驅(qū)動開發(fā)之:字符設(shè)備驅(qū)動編程

作者: 時間:2013-09-13 來源:網(wǎng)絡(luò) 收藏

本文引用地址:http://butianyuan.cn/article/257111.htm

(5)釋放設(shè)備。

釋放設(shè)備的函數(shù)接口是release()。要注意釋放設(shè)備和關(guān)閉設(shè)備是完全不同的。當一個進程釋放設(shè)備時,其他進程還能繼續(xù)使用該設(shè)備,只是該進程暫時停止對該設(shè)備的使用;而當一個進程關(guān)閉設(shè)備時,其他進程必須重新打開此設(shè)備才能使用它。

釋放設(shè)備時要完成的工作如下。

n 遞減計數(shù)器MOD_DEC_USE_COUNT(最新版本已經(jīng)不再使用)。

n 釋放打開設(shè)備時系統(tǒng)所分配的內(nèi)存空間(包括filp->private_data指向的內(nèi)存空間)。

n 在最后一次釋放設(shè)備操作時關(guān)閉設(shè)備。

(6)讀寫設(shè)備。

讀寫設(shè)備的主要任務(wù)就是把內(nèi)核空間的數(shù)據(jù)復(fù)制到用戶空間,或者從用戶空間復(fù)制到內(nèi)核空間,也就是將內(nèi)核空間緩沖區(qū)里的數(shù)據(jù)復(fù)制到用戶空間的緩沖區(qū)中或者相反。這里首先解釋一個read()和write()函數(shù)的入口函數(shù),如表11.5所示。

表11.5 read、write函數(shù)接口語法要點

所需頭文件

#includelinux/fs.h>

函數(shù)原型

ssize_t(*read)(structfile*filp,char*buff,size_tcount,loff_t*offp)
ssize_t(*write)(structfile*filp,constchar*buff,size_tcount,loff_t*offp)

函數(shù)傳入值

filp:文件指針

buff:指向用戶緩沖區(qū)

count:傳入的數(shù)據(jù)長度

offp:用戶在文件中的位置

函數(shù)返回值

成功:寫入的數(shù)據(jù)長度

雖然這個過程看起來很簡單,但是內(nèi)核空間地址和應(yīng)用空間地址是有很大區(qū)別的,其中一個區(qū)別是用戶空間的內(nèi)存是可以被換出的,因此可能會出現(xiàn)頁面失效等情況。所以不能使用諸如memcpy()之類的函數(shù)來完成這樣的操作。在這里要使用copy_to_user()或copy_from_user()等函數(shù),它們是用來實現(xiàn)用戶空間和內(nèi)核空間的數(shù)據(jù)交換的。

copy_to_user()和copy_from_user()的格式如表11.6所示。

表11.6 copy_to_user()/copy_from_user()函數(shù)語法要點

所需頭文件

#includeasm/uaccess.h>

函數(shù)原型

unsignedlongcopy_to_user(void*to,constvoid*from,unsignedlongcount)
unsignedlongcopy_from_user(void*to,constvoid*from,unsignedlongcount)

函數(shù)傳入值

to:數(shù)據(jù)目的緩沖區(qū)

from:數(shù)據(jù)源緩沖區(qū)

count:數(shù)據(jù)長度

函數(shù)返回值

成功:寫入的數(shù)據(jù)長度
失?。?EFAULT

要注意,這兩個函數(shù)不僅實現(xiàn)了用戶空間和內(nèi)核空間的數(shù)據(jù)轉(zhuǎn)換,而且還會檢查用戶空間指針的有效性。如果指針無效,那么就不進行復(fù)制。

(7)ioctl。

大部分設(shè)備除了讀寫操作,還需要硬件配置和控制(例如,設(shè)置串口設(shè)備的波特率)等很多其他操作。在字符中ioctl函數(shù)接口給用戶提供對設(shè)備的非讀寫操作機制。

ioctl函數(shù)接口的具體格式如表11.7所示。

表11.7 ioctl函數(shù)接口語法要點

所需頭文件

#includelinux/fs.h>

函數(shù)原型

int(*ioctl)(structinode*inode,structfile*filp,unsignedintcmd,unsignedlongarg)

函數(shù)傳入值

inode:文件的內(nèi)核內(nèi)部結(jié)構(gòu)指針

filp:被打開的文件描述符

cmd:命令類型

arg:命令相關(guān)參數(shù)

下面列出其他在驅(qū)動程序中常用的內(nèi)核函數(shù)。

(8)獲取內(nèi)存。

在應(yīng)用程序中獲取內(nèi)存通常使用函數(shù)malloc(),但在程序中動態(tài)開辟內(nèi)存可以以字節(jié)或頁面為單位。其中,以字節(jié)為單位分配內(nèi)存的函數(shù)有kmalloc(),注意的是,kmalloc()函數(shù)返回的是物理地址,而malloc()等返回的是線性虛擬地址,因此在驅(qū)動程序中不能使用malloc()函數(shù)。與malloc()不同,kmalloc()申請空間有大小限制。長度是2的整次方,并且不會對所獲取的內(nèi)存空間清零。

以頁為單位分配內(nèi)存的函數(shù)如下所示。

n get_zeroed_page():獲得一個已清零頁面。

n get_free_page():獲得一個或幾個連續(xù)頁面。

n get_dma_pages():獲得用于DMA傳輸?shù)捻撁妗?/p>

與之相對應(yīng)的釋放內(nèi)存用也有kfree()或free_page函數(shù)族。

表11.8給出了kmalloc()函數(shù)的語法格式。

表11.8 kmalloc()函數(shù)語法要點

所需頭文件

#includelinux/malloc.h>

函數(shù)原型

void*kmalloc(unsignedintlen,intflags)

函數(shù)傳入值

len:希望申請的字節(jié)數(shù)

flags

GFP_KERNEL:內(nèi)核內(nèi)存的通常分配方法,可能引起睡眠

GFP_BUFFER:用于管理緩沖區(qū)高速緩存

GFP_ATOMIC:為中斷處理程序或其他運行于進程上下文之外的代碼分配內(nèi)存,且不會引起睡眠

GFP_USER:用戶分配內(nèi)存,可能引起睡眠

GFP_HIGHUSER:優(yōu)先高端內(nèi)存分配

__GFP_DMA:DMA數(shù)據(jù)傳輸請求內(nèi)存

__GFP_HIGHMEN:請求高端內(nèi)存

函數(shù)返回值

成功:寫入的數(shù)據(jù)長度
失?。?EFAULT

linux操作系統(tǒng)文章專題:linux操作系統(tǒng)詳解(linux不再難懂)

linux相關(guān)文章:linux教程




評論


相關(guān)推薦

技術(shù)專區(qū)

關(guān)閉