Linux裝置驅動開發入門--裝置驅動程式框架
一、Linux裝置分類
Linux將裝置主要分為三類:字元裝置、塊裝置、網路裝置。
1. 字元裝置:必須以序列順序依次訪問的裝置,不能讓隨機訪問裝置記憶體中某一組資料;
2. 塊裝置:可以按照任意順序進行訪問,以塊為單位,例如硬碟、eMMc等;
3. 網路裝置:面向資料包的接收和傳送而設計,不傾向於對應檔案系統的節點。
二、Linux裝置驅動程式與外界的介面
1. 驅動程式於作業系統核心的介面
2. 驅動程式與系統引導的介面
3. 驅動程式與裝置的介面
三、根據功能劃分
1. 驅動程式的註冊和登出。
裝置驅動程式可以再系統啟動的時候初始化,也可以在需要的時候動態載入。
字元裝置的初始化由chr_dev_init()完成。
塊裝置初始化由blk_dev_init()完成。
每個字元裝置或是塊裝置的初始化都是通過devfs_register_chrdev() 或是devfs_register_blkdev()向核心註冊,在關閉字元裝置或是塊裝置時,需要通過devfs_unregister_chrdev() 或是 devfs_register_blkdev() 從核心中登出裝置。
2. 裝置的開啟與釋放
裝置開啟:
開啟裝置是由open()來完成的,例如印表機lp_open()
裝置開啟要經過一下幾個步驟:
(1)增加裝置使用計數
(2)檢查裝置相關錯誤,如裝置尚未準備好類似的硬體問題
(3)檢查是首次開啟,則初始化裝置
(4)識別裝置號,如有必要則更新f_op指標
(5)如果需要,分配且設定要放在filp->private_data裡的資料結構
裝置釋放:
關閉釋放裝置由release()來完成,例如釋放印表機是用lp_release(),而釋放終端裝置是用tty_release ().
釋放裝置步驟如下:
(1)釋放在filp->private_data中的open分配的記憶體。
(2)如果是最後一次釋放,則關閉裝置。
(3)遞減裝置使用計數。
3. 裝置的讀寫操作
字元裝置使用各自的read()和write()來進行資料讀寫。
塊裝置使用 generic_file_read() 和genertc_file_write()來進行資料讀寫。
這兩個通用函式向請求表新增讀寫請求,核心可以通過ll_rw_block()優化請求順序。由於是對記憶體緩衝區而不是設
備進行操作的,因而可以加快讀寫請求。如果記憶體緩衝區內沒有要讀入的資料或是要將寫請求寫入裝置,那麼就要真正
的執行資料傳輸。這是通過資料結構request_queue和request_fn()來完成(include/linux/blkdev.h)。
4. 裝置的控制操作
除了讀寫操作,有時還要控制裝置。這可以通過裝置驅動程式中的ioctl()來完成。例如IDE硬碟的控制可以通過hd_ioctl(),對光碟機的控制可以通過cdrom_ioctl()。
與讀寫操作不同,ioctl()的用法與具體裝置密切相關。以軟碟機的floppy_ioctl()為例(drivers/block/floppy。c):
staticintfd_ioctl(structinode*inode,
structfile*filp,
unsignedintcmd,
unsignedlongparam);
其中,cmd的取值及含義都是與軟碟機有關的,比如,FDEJECT表示彈出軟盤。
除了ioctl(),裝置驅動程式還可能有其他控制函式,比如llseek()等。
5. 裝置的中斷和輪詢處理
對於不支援中斷的裝置,讀寫時需要輪詢裝置狀態,以及是否需要繼續進行資料傳輸。例如,印表機。如果裝置支援中斷,則可按照中斷方式進行。
本文摘自:https://tech.hqew.com/news_589150