開啟的裝置在核心內部由裝置檔案結構標識,核心使用
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...