一、 什麼是ioctl
ioctl是裝置驅動程式中對裝置的i/o通道進行管理的函式。所謂對i/o通道進行管理,就是對裝置的一些特性進行控制,例如串列埠的傳輸波特率、馬達的轉速等等。它的呼叫個數如下:
int ioctl(int fd, ind cmd, …);
其中fd就是使用者程式開啟裝置時使用open函式返回的檔案標示符,cmd就是使用者程式對裝置的控制命令,至於後面的省略號,那是一些補充引數,一般最多乙個,有或沒有是和cmd的意義相關的,如果有的話,第三個引數總是乙個指標,但指標的型別依賴於request引數。
ioctl函式是檔案結構中的乙個屬性分量,就是說如果你的驅動程式提供了對ioctl的支援,使用者就可以在使用者程式中使用ioctl函式控制裝置的i/o通道。
二、 ioctl的必要性
如果不用ioctl的話,也可以實現對裝置i/o通道的控制,但那是蠻擰了。例如,我們可以在驅動程式中實現write的時候檢查一下是否有特殊約定的數 據流通過,如果有的話,那麼後面就跟著控制命令(一般在socket程式設計中常常這樣做)。但是如果這樣做的話,會導致**分工不明,程式結構混亂,程式設計師 自己也會頭昏眼花的。所以,我們就使用ioctl來實現控制的功能。要記住,使用者程式所作的只是通過命令碼(cmd)告訴驅動程式它想做什麼,至於怎麼解釋這些命令和怎麼實現這些命令,這都是驅動程式要做的事情。
三、 ioctl如何實現
這是乙個很麻煩的問題,我是能省則省。要說清楚它,沒有四五千字是不行的,所以我這裡是不可能把它說得非常清楚了,不過如果讀者對使用者程式是怎麼和驅動程 序聯絡起來感興趣的話,可以看我前一陣子寫的《write的奧秘》。讀者只要把write換成ioctl,就知道使用者程式的ioctl是怎麼和驅動程式中 的ioctl實現聯絡在一起的了。我這裡說乙個大概思路,因為我覺得《linux裝置驅動程式》這本書已經說的非常清楚了,但是得花一些時間來看。
在驅動程式中實現的ioctl函式體內,實際上是有乙個switch結構,每乙個case對應乙個命令碼,做出一些相應的操作。怎麼實現這些操作,這是每乙個程式設計師自己的事情。因為裝置都是特定的,這裡也沒法說。關鍵在於怎樣組織命令碼,因為在ioctl中命令碼是唯一聯絡使用者程式命令和驅動程式支援的途徑。 命令碼的組織是有一些講究的,因為我們一定要做到命令和裝置是一一對應的,這樣才不會將正確的命令發給錯誤的裝置,或者是把錯誤的命令發給正確的裝置,或 者是把錯誤的命令發給錯誤的裝置。這些錯誤都會導致不可預料的事情發生,而當程式設計師發現了這些奇怪的事情的時候,再來除錯程式查詢錯誤,那將是非常困難的 事情。所以在linux核心中是這樣定義乙個命令碼的:
____________________________________
| 裝置型別 | 序列號 | 方向 |資料尺寸|
|----------|--------|-------|-----------|
| 8 bit | 8 bit |2 bit |8~14 bit|
|----------|--------|-------|-----------|
這樣一來,乙個命令就變成了乙個整數形式的命令碼;但是命令碼非常的不直觀,所以linux kernel中提供了一些巨集。這些巨集可根據便於理解的字串生成命令碼,或者是從命令碼得到一些使用者可以理解的字串以標明這個命令對應的裝置型別、裝置序列號、資料傳送方向和資料傳輸尺寸。
這些巨集我就不在這裡解釋了,具體的形式請讀者察看linux核心源**中的巨集,檔案裡給這些巨集做了完整的定義。這裡我只多說乙個地方,那就是"幻數"。 "幻數"是乙個字母,資料長度也是8,用乙個特定的字母來標明裝置型別,這和用乙個數字是一樣的,只是更加利於記憶和理解。就是這樣,再沒有更複雜的了。 更多的說了也沒用,讀者還是看一看源**吧,推薦各位閱讀《linux 裝置驅動程式》所帶源**中的short一例,因為它比較短小,功能比較簡單,可以看明白ioctl的功能和細節。
四、 cmd引數如何得出
這裡確實要說一說,cmd引數在使用者程式端由一些巨集根據裝置型別、序列號、傳送方向、資料尺寸等生成,這個整數通過系統呼叫傳遞到核心中的驅動程式,再由驅動程式使用解碼巨集從這個整數中得到裝置的型別、序列號、傳送方向、資料尺寸等資訊,然後通過switch結構進行相應的操作。要透徹理解,只能是通過閱讀源**,我這篇文章實際上只是乙個引子。cmd引數的組織還是比較複雜的,我認為要搞熟它還是得花不少時間的,但是這是值得的,因為驅動程式中最難的是對中斷的理解。
五、 小結
ioctl其實沒有什麼很難的東西需要理解,關鍵是理解cmd命令碼是怎麼在使用者程式裡生成並在驅動程式裡解析的,程式設計師最主要的工作量在switch結構中,因為對裝置的i/o控制都是通過這一部分的**實現的。
SetBkMode函式理解
輸出的字串時,發現存在背景色,這樣的輸出是破壞背景的。那需要使用什麼方法來保持背景不變,而又能輸出紅色的字串呢?比如按鈕的文字顏色是黑色的,而背景是灰色的。這就需要使用setbkmode函式來設定drawtext函式的輸出方式,顯示裝置共有兩種輸出方式 opaque和transparent。opaq...
OpenGl glenable 函式理解
glenable 用於啟用各種功能。功能由引數決定。與gldisable相對應。gldisable是用來關閉的。兩個函式引數取值是一至的。引數說明 void glenable glenum cap glenum 是unsigned int 型別 cap 是乙個取值。由值決定啟用的功能鍵。各種功能請看...
get函式理解
include include include includeusing namespace std int main char next do cin.get next cout 輸入 to be or not to be 輸出 to be or not to be 其實剛開始我很不理解為什麼輸出...