Linux下的驅動程式設計 入門篇

2021-04-02 21:09:16 字數 2979 閱讀 7493

開啟的裝置在核心內部由裝置檔案結構標識,核心使用

file_operations

(檔案操作)結構訪問驅動程式的函式。每個檔案都與自己的函式集相關聯(通過包含在裝置中指向

file_operations

結構的指標實現),這些操作主要負責系統呼叫的實現。使用者程序利用系統呼叫對裝置檔案進行操作時,系統呼叫通過裝置的主裝置號找到相應的裝置驅動程式,然後讀取這個資料結構相應的函式指標,接著把控制權交給該函式,這就是

linux

的裝置驅動程式工作的基本原理。由此可見,編寫裝置驅動程式的主要工作就是編寫

file_operations

中的子函式,完成對裝置的操作。下面給出

2.4系統核心中

file_operations

結構中所包括的操作以及相關的解釋

[17]

,具體的定義可以參看

檔案。

structfile_operations

loff_t(*llseek)(struct file*, loff_t, int);

方法

llseek

用來修改檔案的當前讀寫位置,並將新位置(正的)作為返回值返回。引數

loff_t

是乙個「長偏移量」,即使在

32位平台上也至少占用

64位的資料寬度。出錯時返回乙個負的返回值。如果驅動程式沒有設定這個函式,那麼相對於檔案末尾的定位操作就會失敗,而其他的定位操作就會修改

file

結構中的位置計數器並正確返回。

ssize_t (*read)(struct file*,char *, size_t, loff_t *);

用來從裝置中讀取資料。當該函式指標被賦為

null

值時,將導致

read

系統呼叫出錯並返回

-einval(「invalid argument,

非法引數

」)。函式返回非負值表示成功讀取的位元組數。

ssize_t (*write)(struct file*,char *, size_t, loff_t *);

向裝置傳送資料,如果沒有這個函式,

write

函式的呼叫會向呼叫程式返回

-einval

,如果返回非負值,則表示成功寫入的位元組數。

int(*readdir)(struct file*,void *,filldir_t);

對於裝置檔案來說,這個字段應該為

null

。它僅用於讀取目錄,並且只對檔案系統有用。

unsigned int(*poll)(struct file *,struct poll_table_struct *);

poll

方法是poll

和select

這兩個系統呼叫的後端實現。這兩個系統呼叫可用來查詢裝置是否可讀或者可寫,或者出於某種特殊狀態。這兩個系統呼叫是可阻塞的,直至系統可讀、可寫或者到某種特殊狀態為止。如果驅動程式沒有定義它的

poll

方法,它所驅動的裝置就會被認為既可讀又可寫,並且不會出於某種特殊狀態,返回值是乙個描述裝置狀態的位掩碼。

int(*ioctl)(struct inode *, struct file *,unsigned int ,unsigned long);

系統呼叫

ioctl

提供了一種執行裝置特定命令的方法(如格式化某個硬碟分割槽)。另外,核心還能識別部分的

ioctl

命令,而不必呼叫

fops

中的ioctl

。如果裝置不提供

ioctl

入口點,則對於任何核心未預先定義的請求,

ioctl

系統呼叫將返回錯誤(

-enotty

,「no such ioctl for device

,該裝置無此

ioctl

命令」)。如果該裝置方法返回乙個非負值,那麼相同的值會被返回給呼叫程式以表示呼叫成功。

int(*mmap)(struct file *,struct vm_area_struct *);

mmap

用於請求將裝置記憶體對映到程序位址空間。如果裝置沒有實現這個方法,那麼

mmap

系統呼叫將返回

-enodev。

int(*open)(struct inode *,struct file *);

儘管這個始終是裝置檔案執行的第乙個操作,但是卻不要求驅動程式一定要宣告這個方法,如果這個入口點為

null

,那麼裝置的開啟操作永遠成功,但是系統不會通知驅動程式。

int(*flush)(struct file *);

flush

操作的呼叫發生在程序關閉裝置檔案描述符副本的時候,它應該執行裝置上尚未完成的操作。目前

flush

僅僅用於網路檔案系統**中,如果

flush

被置為null

,則它只是簡單的不被呼叫。

int(*release)(struct inode *,struct file *);

file

結構被釋放時,將呼叫這個操作。與

open

相仿,也可以沒有

release。

int(

*fsync

)(struct inode *,struct dentry *,int);

該方法是

fsync

系統呼叫的後端實現,使用者呼叫它來重新整理待處理的資料。如果驅動程式沒有實現這一方法,

fsync

系統呼叫就返回

-einval。

int(

*fasync

)(int

,struct file *

,int);

這個操作用來通知裝置,它的非同步標誌發生了變化。如果裝置不支援非同步通知,那麼該欄位可以為

null

Linux驅動程式之入門篇

無論是vc還是vb,還是c 還是jsp php等等語言,在學習他們之前總是先來乙個hello world的例子,這個好像成了我們程式入門的必經之路。所以在驅動程式的學習上,也離不開這個步驟。但是驅動程式的開發是執行在核心空間的,而應用程式是執行在使用者空間的,所以驅動程式的開發盒除錯和應用程式的開發...

socket程式設計入門篇(三)

這篇部落格介紹多執行緒併發伺服器的實現。下面貼 服務端 include include include include include include include include include includeusing namespace std define serverip 127.0.0...

網路程式設計之入門篇(一)

伺服器端操作 socket 套接字 1 在初始化階段呼叫wsastartup 此函式在應用程式中初始化windows sockets dll 只有此函式呼叫成功後,應用程式才可以再呼叫其他windows sockets dll中的api函式。在程式中呼叫該函式的形式如下 wsastartup wor...