萬盛學電腦網

 萬盛學電腦網 >> Linux教程 >> Linux--Linux內核模塊編程之字符設備文件在線閱讀

Linux--Linux內核模塊編程之字符設備文件在線閱讀

 字符設備文件
  因此現在我們是大膽的內核程序員而且我們知道如何寫什麼也不做的內核模塊。我們為自己而自豪並且可以高高的仰起我們的頭。但是不知何故我們感到遺失了什麼。令人緊張的模塊並不是很有趣的。
  內核模塊有兩種主要的途徑和進程對話。一種是通過設備文件 (像 /dev 目錄中的文件), 另一種是使用 proc 文件系統。因為寫內核中的某些東西的一個主要的原因是去支持某種硬件,所以我們從設備文件開始。
  設備文件的原始目的是允許進程和內核中的設備驅動程序通信以通過它們和物理設備通信 (調制解調器, 終端, 等等)。 這個辦法的實現是像下面這樣的。
  每個設備驅動程序負責某種硬件,它被分配一個主設備號。驅動程序的列表和它們的主設備號可以在 /proc/devices找到。每一個物理設備由設備驅動程序控制且被分配一個次設備號。 /dev 目錄被假設包含每一個這樣的設備的被稱之為設備文件的特殊文件,無論它是否被真正的安裝在系統上。
  例如,如果你 ls -l /dev/hd[ab]*,你將看到所有的可能被連接到系統上的IDE硬盤的分區。注意它們都使用相同的主設備號,3。但是次設備號彼此都不相同。
否認申明: 這是假設你正字使用 PC 架構的系統。我不知道基於其他架構的Linux設備的情況。.
  當系統被安裝,所有的那些設備文件被 mknod 命令創建。從技術上說沒有必須將它們放在 /dev目錄的原因,這只是一個有用的慣例。像練習所示的那樣,當為了測試的目的而創建一個設備文件,將它放在你編譯內核模塊的那個目錄也許更有意義。
  設備分為兩種:字符設備和塊設備。不同之處在於塊設備對於請求有緩沖區,因此它們可以選擇以什麼順序進行響應。對於存儲設備而言這一點是很重要的,因為在讀寫連續的扇區時比遠遠的分離的扇區更快。另一個不同就是塊設備只能以塊為單位接受輸入和返回輸出(塊的大小根據設備的不同而不同),而字符設備只能使用它們可能使用的或多或少的字節大小。大多數設備是字符設備,因為它們不需要這種緩沖而且不以固定塊大小進行操作。你可以用ls -l區分一個設備文件是塊設備還是字符設備.如果開頭是“b”,那麼它就是塊設備;如果是“c”,那麼就是字符設備。
  這個模塊分為兩部分:登記設備模塊部分和設備驅動部分。 init_module 調用 module_register_chrdev 而將設備驅動程序加入內核的字符設備驅動程序表。它也返回該設備將使用的主設備號。 cleanup_module 注銷該設備。
  這(登記什麼和注銷它)是那兩種功能的常規功能。內核中的東西不想普通進程那樣主動運行自己,而是由進程通過系統調用,或者由硬件通過中斷,或者由內核的其他部分(簡單的講,由特殊的函數調用)進行調用。結果,當你向內核中加入代碼,你被假設將之登記為某種事件句柄,而當你移除它時,你被假設出注銷它。
  嚴格意義上講,設備驅動程序由四個device_函數組成,當某人試圖用我們的主設備號的設備文件做什麼事時它被調用。內核是通過 file_operations結構知道要調用它們的,Fops, 在設備被登記時被給出,它包含那四個函數的指針。
  另一點我們在這必須記住的是我們不能允許內核模塊在任何根感覺需要的時候被rmmod。原因是如果設備文件正被一個進程打開然後我們移除那個內核模塊,這將使用那個文件,而這又將導致對那個適當的讀寫函數所在的內存區域的調用。如果幸運的話,沒有其他的代碼被加載到那兒,我們得到一個難看的錯誤消息。如果不幸運的話,另一個內核模塊被加載到同一區域,這就意味著跳到內核中的另一個函數的中間,結果是不可預見的,但肯定不是什麼好事。
  通常,當你不允許什麼事情發生,你會從被假設做這件事的函數返回一個用負數表示的錯誤代碼。使用cleanup_module 是不可能的,因為它不返回任何值。一旦cleanup_module 被調用,模塊即死亡了。然而,這兒有一個被稱為引用計數器(在/proc/modules中的相應行的最後一個數字)的計數器計算有多少其他的內核模塊正在使用該模塊。如果該數字非零 rmmod 調用將失敗。模塊的引用計數器在變量mod_use_count_中. 因為有處理這個變量的宏定義 (MOD_INC_USE_COUNT and MOD_DEC_USE_COUNT),我們最好使用它們而不直接使用 mod_use_count_ ,這樣,如果將來實現方法改變了我們會更安全。


copyright © 萬盛學電腦網 all rights reserved