嵌入式Linux設備驅動(dòng)開(kāi)發(fā)之:字符設備驅動(dòng)編程
(5)釋放設備。
釋放設備的函數接口是release()。要注意釋放設備和關(guān)閉設備是完全不同的。當一個(gè)進(jìn)程釋放設備時(shí),其他進(jìn)程還能繼續使用該設備,只是該進(jìn)程暫時(shí)停止對該設備的使用;而當一個(gè)進(jìn)程關(guān)閉設備時(shí),其他進(jìn)程必須重新打開(kāi)此設備才能使用它。
釋放設備時(shí)要完成的工作如下。
n 遞減計數器MOD_DEC_USE_COUNT(最新版本已經(jīng)不再使用)。
n 釋放打開(kāi)設備時(shí)系統所分配的內存空間(包括filp->private_data指向的內存空間)。
n 在最后一次釋放設備操作時(shí)關(guān)閉設備。
(6)讀寫(xiě)設備。
讀寫(xiě)設備的主要任務(wù)就是把內核空間的數據復制到用戶(hù)空間,或者從用戶(hù)空間復制到內核空間,也就是將內核空間緩沖區里的數據復制到用戶(hù)空間的緩沖區中或者相反。這里首先解釋一個(gè)read()和write()函數的入口函數,如表11.5所示。
表11.5 read、write函數接口語(yǔ)法要點(diǎn)
所需頭文件 | #includelinux/fs.h> |
函數原型 | ssize_t(*read)(structfile*filp,char*buff,size_tcount,loff_t*offp) |
函數傳入值 | filp:文件指針 |
buff:指向用戶(hù)緩沖區 | |
count:傳入的數據長(cháng)度 | |
offp:用戶(hù)在文件中的位置 | |
函數返回值 | 成功:寫(xiě)入的數據長(cháng)度 |
雖然這個(gè)過(guò)程看起來(lái)很簡(jiǎn)單,但是內核空間地址和應用空間地址是有很大區別的,其中一個(gè)區別是用戶(hù)空間的內存是可以被換出的,因此可能會(huì )出現頁(yè)面失效等情況。所以不能使用諸如memcpy()之類(lèi)的函數來(lái)完成這樣的操作。在這里要使用copy_to_user()或copy_from_user()等函數,它們是用來(lái)實(shí)現用戶(hù)空間和內核空間的數據交換的。
copy_to_user()和copy_from_user()的格式如表11.6所示。
表11.6 copy_to_user()/copy_from_user()函數語(yǔ)法要點(diǎn)
所需頭文件 | #includeasm/uaccess.h> |
函數原型 | unsignedlongcopy_to_user(void*to,constvoid*from,unsignedlongcount) |
函數傳入值 | to:數據目的緩沖區 |
from:數據源緩沖區 | |
count:數據長(cháng)度 | |
函數返回值 | 成功:寫(xiě)入的數據長(cháng)度 |
要注意,這兩個(gè)函數不僅實(shí)現了用戶(hù)空間和內核空間的數據轉換,而且還會(huì )檢查用戶(hù)空間指針的有效性。如果指針無(wú)效,那么就不進(jìn)行復制。
(7)ioctl。
大部分設備除了讀寫(xiě)操作,還需要硬件配置和控制(例如,設置串口設備的波特率)等很多其他操作。在字符設備驅動(dòng)中ioctl函數接口給用戶(hù)提供對設備的非讀寫(xiě)操作機制。
ioctl函數接口的具體格式如表11.7所示。
表11.7 ioctl函數接口語(yǔ)法要點(diǎn)
所需頭文件 | #includelinux/fs.h> |
函數原型 | int(*ioctl)(structinode*inode,structfile*filp,unsignedintcmd,unsignedlongarg) |
函數傳入值 | inode:文件的內核內部結構指針 |
filp:被打開(kāi)的文件描述符 | |
cmd:命令類(lèi)型 | |
arg:命令相關(guān)參數 |
下面列出其他在驅動(dòng)程序中常用的內核函數。
(8)獲取內存。
在應用程序中獲取內存通常使用函數malloc(),但在設備驅動(dòng)程序中動(dòng)態(tài)開(kāi)辟內存可以以字節或頁(yè)面為單位。其中,以字節為單位分配內存的函數有kmalloc(),注意的是,kmalloc()函數返回的是物理地址,而malloc()等返回的是線(xiàn)性虛擬地址,因此在驅動(dòng)程序中不能使用malloc()函數。與malloc()不同,kmalloc()申請空間有大小限制。長(cháng)度是2的整次方,并且不會(huì )對所獲取的內存空間清零。
以頁(yè)為單位分配內存的函數如下所示。
n get_zeroed_page():獲得一個(gè)已清零頁(yè)面。
n get_free_page():獲得一個(gè)或幾個(gè)連續頁(yè)面。
n get_dma_pages():獲得用于DMA傳輸的頁(yè)面。
與之相對應的釋放內存用也有kfree()或free_page函數族。
表11.8給出了kmalloc()函數的語(yǔ)法格式。
表11.8 kmalloc()函數語(yǔ)法要點(diǎn)
所需頭文件 | #includelinux/malloc.h> | |
函數原型 | void*kmalloc(unsignedintlen,intflags) | |
函數傳入值 | len:希望申請的字節數 | |
flags | GFP_KERNEL:內核內存的通常分配方法,可能引起睡眠 | |
GFP_BUFFER:用于管理緩沖區高速緩存 | ||
GFP_ATOMIC:為中斷處理程序或其他運行于進(jìn)程上下文之外的代碼分配內存,且不會(huì )引起睡眠 | ||
GFP_USER:用戶(hù)分配內存,可能引起睡眠 | ||
GFP_HIGHUSER:優(yōu)先高端內存分配 | ||
__GFP_DMA:DMA數據傳輸請求內存 | ||
__GFP_HIGHMEN:請求高端內存 | ||
函數返回值 | 成功:寫(xiě)入的數據長(cháng)度 |
linux相關(guān)文章:linux教程
評論