《字元装置驱动程式》PPT课件.ppt
《《字元装置驱动程式》PPT课件.ppt》由会员分享,可在线阅读,更多相关《《字元装置驱动程式》PPT课件.ppt(53页珍藏版)》请在三一办公上搜索。
1、Chap 3-字元裝置驅動程式,Outline,Introduction3.1 scull的設計藍圖3.2 主編號與次編號3.3 檔案架構3.4 file 結構3.5 open 與 release3.6 Scull 的記憶體用法規劃3.7 相競狀況3.8 read 與 write3.9 try scull3.10 devfs 檔案系統3.11 回溯相容性3.12 速查參考,3-Introduction,本章目標:寫出一個完整的字元裝置驅動程式(char device driver)-簡稱char driver終極目標:寫出一個模組化的char driver範例:scull-(Simple Ch
2、aracter Utility for Loading Localities)Makefile,main.c,access.c,empty.c,pipe.c,scull.h,scull.init,scull_load,scull_unload,alpha.checkthemscull的作用是“讓使用者可把一塊記憶區當成字元裝置來使用”scull所驅動的目標裝置是一塊記憶區不需依賴任何“特殊”硬體只要有linux平台就可以編譯與執行未提供任何實用功能,只展示核心與char driver之間軟體介面,3.1-scull的設計藍圖,定義驅動程式要提供哪些功能給user-sapce的程式可循序存取(字
3、元裝置)or 可隨機存取(區塊裝置)模擬單一裝置(ex:一機多體 or 多個同類裝置)Scull所模擬出的每一種裝置,分別由不同類型的模組予以實現(相同的mechanism差別在於policy的不同)scull0scull3四個由記憶區所構成的裝置,兼具“共通”“持續”scullpipe0scullpipe3四個FIFO裝置(blocking與nonblocking)Scullsingle一次只容許一個被行程存取Scullpriv允許每個終端機都有權開啟一次,分屬不同行程Sculluid允許開始多次,限同一使用者。(回傳錯誤碼)Scullwuid允許開始多次,限同一使用者。(推延,等待),Ch
4、_5.6,3.2-主編號與次編號,主編號(major number)(0255)代表裝置所配合的驅動程式當核心收到open()系統呼叫時,就是依據“主編號”來選擇驅動程式次編號(minor number)(0255)驅動程式以次編號來辨認同類裝置的個體核心本身用不到,只有驅動程式自己才知道次編號的意義當使用者要存取字元裝置時,必須透過檔案系統裡的“代表名稱”特殊檔(special file)、裝置檔(device file)、檔案系統樹的節點(node),集中在/dev/目錄下。裝置類型:“c”代表char driver的特殊檔“b”代表block driver的裝置檔,3.2-主編號與次編號
5、,ls al/dev/|less,brw-rw-1 root disk 66,72 Apr 11 2002 sdak8brw-rw-1 root disk 66,73 Apr 11 2002 sdak9crw-r-r-1 root root 253,1 Mar 1 22:58 scull1crw-r-r-1 root root 253,2 Mar 1 22:58 scull2crw-r-r-1 root root 253,3 Mar 1 22:58 scull3brw-rw-1 root disk 8,0 Apr 11 2002 sdacrw-rw-1 root uucp 154,18 Apr
6、 11 2002 ttySR18,3.2-主編號與次編號,檔案系統製作裝置節點的命令是mknod,必須有特權身分(root)才能使用此工具。至少需要四個引數 mknod/dev/ant c 252 0像任何儲存在磁碟上的普通檔案一樣,mknod所產生的裝置節點會被保存下來,除非刻意刪除它們。用一般的rm命令即可辦到 rm/dev/ant,3.2.1-隨機取得主編號,大部份常見的裝置幾乎都有固定的主編號,可在核心源碼樹的Documentation/devices.txt檔案內找到一份“裝置-主編號”對照表。“實驗性或自家使用”的主編號:6063、120127、240.254“隨機索取主編號”呼叫
7、register_chrdev()定義在,extern int register_chrdev(unsigned int,const char*,struct file_operations*);extern int unregister_chrdev(unsigned int,const char*);,3.2.1-隨機取得主編號,在呼叫register_chrdev()時:major引數給0:=回傳值為0&0&回傳值為0表示核心同意你的要求發生錯誤時:=回傳值為負數如果你的驅動程式會被用於廣大群眾,或者有可能被納入正式核心,則須設法申請專用的主編號。,3.2.1-隨機取得主編號,cat/p
8、roc/devices,Character devices:1 mem 2 pty226 drm253 scull254 pcmciaBlock devices:2 fd 3 ide0,3.2.1-隨機取得主編號,缺點:因為模組分配到的主編號不一定每次都一樣,所以無法事先建立裝置節點。因此,光靠insmod是不夠的,還必須查閱/proc/devices的內容後,找出其隨機取得的主編號,再製作成適當的裝置節點(甚至要刪除上次留下的無用節點)可寫成一個shell script來一次解決範例:scull_load=每次開機時透過/etc/rc.local來執行 scull_unload=卸載模組及清
9、理/dev/下的相關節點 scull.init=由系統開機/關機程序自動載入/卸載 模組。接受傳統命令start,stop,restart,Ch_11,#!/bin/shmodule=scull“device=scullmode=664#Group:since distributions do it differently,look for wheel or use staffif grep staff:/etc/group/dev/null;then group=staffelse group=wheelfi#invoke insmod with all arguments we got#a
10、nd use a pathname,as newer modutils dont look in.by default/sbin/insmod-f./$module.o$*|exit 1major=cat/proc/devices|awk$2=$module print$1#Remove stale nodes and replace them,then give gid and perms#Usually the script is shorter,its scull that has several devices in it.rm-f/dev/$device0-3mknod/dev/$d
11、evice0 c$major 0mknod/dev/$device1 c$major 1mknod/dev/$device2 c$major 2mknod/dev/$device3 c$major 3ln-sf$device0/dev/$devicechgrp$group/dev/$device0-3chmod$mode/dev/$device0-3,#!/bin/shmodule=scull“device=scull#invoke rmmod with all arguments we got/sbin/rmmod$module$*|exit 1#Remove stale nodesrm-f
12、/dev/$device/dev/$device0-3rm-f/dev/$deviceprivrm-f/dev/$devicepipe/dev/$devicepipe0-3rm-f/dev/$devicesinglerm-f/dev/$deviceuidrm-f/dev/$devicewuid,scull_load&scull_unload也適用其他其他驅動程式,只需重新定義變數,並稍微調整mknod那幾行即可。因為指令稿需要特權身分才能執行,而新建出來的特殊檔自然會屬於root。但裝置節點的存取權限通常不是這樣,所以要修改權限的擁有權。,3.2.2移除驅動程式,在模組被卸載之前,他必須先釋放
13、主編號,而這動作可由unregister_chrdev()完成,應該在模組的清理函式理呼叫他:major表示要被釋放的主編號;name是當初註冊的名稱對於動態取得主編號的驅動程式,如果在卸載模組之後沒有順便除掉相關的/dev結點,就可能產生意料外的錯誤。譬如,已經沒有作用的/dev/framegrabber可能在一個月後指向火災警報器,int unregister_chrdev(unsigned int major,const char*name):,3.2.3-副編號(dev_t&kdev_t),每當核心要呼叫驅動程式,都必須讓驅動程式知道,他應該作用在哪一個裝置上;驅動程式以裝置編號來辨認
14、其作用對象。(裝置編號=主編號+次編號)dev_tUnix以dev_t(代表“device type”)作為裝置編號的資料型別定義在更改不易,因太多應用程式“知道”其內部結構kdev_tLinux核心內部採用另一種不同的資料型別定義在黑盒子每個核心函式都不必知道其內部結構,而應用程式可以不知道kdev_t的存在。=核心改版可以放手修正,不會影響任何驅動程式,3.2.3-副編號(dev_t&kdev_t),可操作的kdev_t巨集與函式:MAJOR(kdev_t dev)=從kdev結構取得主編號MINOR(kdev_t dev)=從kdev結構取得次編號MKDEV(int major,int
15、minor)=以指定的主編號與次編號建立一個kdev_t結構kdev_t_to_nr(kdev_t dev)=將一個kdev_t結構轉換成一個數值(dev_t)to_kdev_t(int dev)=將一個數值轉換成kdev_t結構,3.3檔案作業,驅動程式內部以一個file結構來代表一個已開啟的裝置核心透過一個file_operations結構來存取驅動程式內部的作業函式(method)file結構包含一個f_op欄位,他是一個指向file_operations結構的指標file_operation結構本身是由一系列“函式指標”所構成,這些指標分別指向驅動程式的各項作業函式。Ex:核心收到操作
16、檔案的系統戶叫(ex:read(),依據系統呼叫指定的fd找出對應驅動程式的file結構,然後再循線從file_operations結構中找出對應於該系統呼叫的作業函式scull_read(),Read(),Scull_read(),3.3檔案作業,fops變數名稱用來表示file_operation結構(或是指向此結構的指標)在file_operations結構中的每一個欄位,都必須指向驅動程式中負責特定作業方法。對於驅動程式不支援的作業項目(method),其對應欄位就必須指向NULL,當核心遇到NULL時會採取適當的預設行為。欄位的預設行為各不相同。每一種作業方法,其回傳值都有同樣的意義
17、:0代表成功,負值為錯誤碼。,3.3檔案作業,struct module*owner;不同於file_operations結構裡的其它欄位,此欄位不是函式指標,而是一個指向結構所屬模組的指標。驅動程式本身用不到此欄位,因為他是供核心用來維護模組的用量計次(usage count)。loff_t(*llseek)(struct file*,loff_t,int);/seek作業方法的作用,是改變檔案目前的讀寫點位置;如果成功,則傳回新位置(正值),傳回值loff_t是一個至少64-bits“long offset”,即使是在32-bits平台上也是如此。ssize_t(*read)(struct
18、 file*,char*,size_t,loff_t*);用於擷取出裝置上的資料。若將此欄位設定為NULL,則read()系統呼叫發生-EINVAL失敗。(Invalid argument,引數值無效),如果成功,則傳回一個非負數值,代表成功讀取的位元數。,ssize_t(*write)(struct file*,const char*,size_t,loff_t*);將資料寫入裝置。若發生錯誤,則觸發write()系統呼叫的行程會收到-EINVAL。如果成功,write將傳回一個非負值,代表成功寫出的位元數。int(*readdir)(struct file*,void*,filldir_t
19、);對於裝置檔而言,此欄位必須是NULL,因為他是用來讀取目錄,而且只對檔案系統有意義。unsigned int(*poll)(struct file*,struct poll_table_struct*);poll作業方法是兩種系統呼叫的後台:poll()與select()-兩者都是用來探詢裝置在某特殊狀態下是法可讀或可寫,而且兩者都會等到目標裝置呈為可寫或可讀的狀態,才會返回。如果驅動程式沒定義自己poll作業方法,核心會預設目標裝置的性質為同時兼具可讀可寫,沒有特殊狀態。傳回值是一個代表裝置狀態的位元遮罩(bit mask)。int(*mmap)(struct file*,struct
20、vm_area_struct*);mmap用來將I/O memory對應到行程的位址空間。若驅動程式沒提供此方法,則mmap()系統呼叫將傳回-ENODEV,int(*ioctl)(struct inode*,struct file*,unsigned int,unsigned long);每個裝置或多或少都有其特殊功能,標準的作業方法不見得能提供應用程式所需要的一切功能(ex:格式化),對於隨裝置而定的功能,應用程式可透過ioctl()系統呼叫來執行一系列裝置特有命令,而ioctl作業發法的任務,就是實現在類特殊命令。int(*open)(struct inode*,struct file*
21、);開啟,這必定是裝置檔操作程序的第一步,但是驅動程式並非一定要宣告一個對應方法不可。如果將此欄位指向NULL,開啟裝置的動作一定會成功,只不過驅動程式不會收到通知而已。int(*flush)(struct file*);這是行程在關閉其裝置檔之前的必要動作。flush應該執行任何還沒解決的作業程序。請不要將此方法與fsnc()系統呼叫聯想在一起。目前,只有NFS需要用到flush。如果讓flush指向NULL,不會有動作發生。int(*release)(struct inode*,struct file*);在file結構被釋放之前,此方法會被呼叫。(並非,每次呼叫close()都會觸發re
22、lease),int(*fsync)(struct inode*,struct dentry*,int);此為fsync()系統呼叫的實際後台,其作用是出清(flush)任何延滯的資料。如果驅動程式不提供此作業方法,系統呼叫會傳回-EINVALint(*fasync)(struct inode*,struct flie*,int);當裝置的FASYNC旗標出現變化時,核心就會呼叫驅動程式的fasync的作業方法。非同步通知(asynchronous notification)。int(*lock)(struct file*,int,struct file_lock*);Lock的作業方法用來實
23、現檔案所訂的效果。對一般檔案而言,這項功能絕不可避免,但是幾乎沒有任何驅動程式時作此作業方法。ssize_t(*readv)(struct file*,const struct iovec*,unsigned long,loff_t*);ssize_t(*writev)(struct file*,const struct iovec*,unsigned long,loff_t*);以上兩者都是2.3版研發過程中才提出來的新作業發訪,分別用於實現“分散讀取(scatter read)”以及“累積寫出(gather write)”,Ch_5,3.3檔案作業,scull 驅動程式只實作最重要的幾項作
24、業方法,而起GNU的標記語法來宣告初始話他自己的file_operations結構:scull/main.c:Line 551GNU C編譯器的優點:驅動程式的移植性較高程式碼精簡,容易理解在某些情況下,能得到相當程度的效能提升,struct file_operations scull_fops=llseek:scull_llseek,read:scull_read,write:scull_write,ioctl:scull_ioctl,open:scull_open,release:scull_release,;,3.4file 結構,File與一般應用程式常用的FILE毫無關係。File定
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 字元装置驱动程式 字元 装置 驱动 程式 PPT 课件

链接地址:https://www.31ppt.com/p-4871346.html