國嵌驅(qū)動筆記)_第1頁
國嵌驅(qū)動筆記)_第2頁
國嵌驅(qū)動筆記)_第3頁
國嵌驅(qū)動筆記)_第4頁
國嵌驅(qū)動筆記)_第5頁
已閱讀5頁,還剩7頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、知識結(jié)構(gòu):Linux驅(qū)動程序設(shè)計(jì)模式(40%) 2.內(nèi)核相關(guān)知識(30%) 3,硬件相關(guān)知識(30%) 驅(qū)動分類:字符,網(wǎng)絡(luò),塊字符設(shè)備:以字節(jié)為最小單位塊設(shè)備,一次傳送一個(gè)整體數(shù)據(jù)(512字節(jié)),Linux可以以字節(jié)訪問塊設(shè)備(僅僅是驅(qū)動與 內(nèi)核的接口不同,訪問的順序的不同(字符只可順序訪問,塊驅(qū)動可隨機(jī)訪問) 網(wǎng)絡(luò)接口:硬件(eth0),純軟件(lo)驅(qū)動的安裝:模塊,編譯進(jìn)內(nèi)核(Linux啟動的時(shí)候會自動加載init段)使用驅(qū)動程序:字符設(shè)備文件一字符設(shè)備驅(qū)動一字符設(shè)備文件系統(tǒng)一塊設(shè)備文件一塊設(shè)備驅(qū)動一塊設(shè)備套接字一協(xié)議棧一網(wǎng)絡(luò)設(shè)備驅(qū)動一網(wǎng)絡(luò)接口設(shè)備主設(shè)備號用來標(biāo)示與設(shè)備文件相連的驅(qū)動程

2、序,次編號被驅(qū)動程序用來辨別操作哪個(gè)設(shè)備 主設(shè)備號反映設(shè)備類型,此設(shè)備號區(qū)分同類型的設(shè)備dev_t高12位為主設(shè)備號,低20位為次設(shè)備號MAJOR( dev_t dev)從dev_t分解出主設(shè)備號MINOR( dev_t dev)從dev_t分解出此設(shè)備號MKDEV(major,minor)構(gòu)造設(shè)備號;靜態(tài)申請:1.根據(jù)Documentation/devices.txt驅(qū)動沒有使用的主設(shè)備號2,使用 register_chrdev_region (dev_t form, unsigned count ,const char *name)函數(shù)注冊(容易沖突) From希望使用的設(shè)備號,count

3、希望申請使用設(shè)備號的數(shù) 目,name設(shè)備名(體現(xiàn)在 /proc/devices)動態(tài)分配alloc_chardev_region (安裝驅(qū)動前無法創(chuàng)建設(shè)備文件)創(chuàng)建設(shè)備文件后,通過/proc/devices 察看alloc_chardev_region ( dev_t *dev,unsigned baseminor, unsigned count, const char *name)dev分配的設(shè)配號,baseminor起始的此設(shè)備號,count要分配的設(shè)備數(shù)目,name設(shè)備名主要設(shè)備號:unregister_chrdev_region(dev_t dev, unsigned basemino

4、r)Mknod filename type major minor type 是字符或塊 mknod serial0 c 1000Linux字符設(shè)備驅(qū)動3個(gè)重要數(shù)據(jù)結(jié)構(gòu)Struct file每打開一次都有一個(gè)關(guān)聯(lián)的struct file重要結(jié)構(gòu)loff_t f_pos文件讀寫位置struct file_operations *f_opStruct inode記錄文件的物理上的信息(設(shè)備號等),一個(gè)文件可以有多個(gè)file,但只有一個(gè) inodeStruct file_operation *f_op 函數(shù)指針的集合struct file_operations mem_fops = (.owner

5、= THIS_MODULE,.llseek = mem_seek,.read = mem_read 讀內(nèi)核代碼應(yīng)用程序怎樣訪問驅(qū)動程序(read_write,c)系統(tǒng)條用read找到vfs_read根據(jù)file結(jié)構(gòu)中找到file_operations中的read 字符設(shè)備使用struct cdev來描述字符設(shè)備注冊可分為如下3個(gè)部分:分配 cdev struct cdev *cdev_alloc(void)初始化 cdev cdev_init(struct cedev *p, const struct file_operations *fops)添加 cdev cdev_add(struct

6、cdev *p ,dev_t dev ,unsigned count ) dev 設(shè)備號 設(shè)備號的數(shù)目字符設(shè)備的注銷:cdev_dev(struct cdev *p)設(shè)備操作int (*open)(struct *inode , struct file *)如果該項(xiàng)為NULL,設(shè)備打開永遠(yuǎn)成功void( *release)(struct *inode , struct file *)ssize_t (*read)(struct file *, char _user *buff , size_t , loff_t *)ssize_t (*write)(struct file *, char _u

7、ser *, size_t , loff_t *)file是文件指針(來與內(nèi)核),*buff是數(shù)據(jù)緩沖(用戶空間),count傳輸?shù)臄?shù)據(jù)量(用戶空間),offp訪問位置(來與內(nèi)核)*buff是用戶空間的,不能直接使用int copy_from_user(void *to , const void _user *from, int n)int copy_to_user(void _user *to ,const void *to , int n)loff_t llseek( struct *file ,loff_t offset , int whence)open方法主要完成如下工作:1.初始化

8、設(shè)備2.標(biāo)明此設(shè)備號在 open(struct inode *inode, struct fil)2 *函數(shù)可使用 MINOR(inode-i_rdev;獲取此 設(shè)備號filp-private_data = dev;將設(shè)備描述指針賦值給私有文件指針,區(qū)分出了那種設(shè)備在read()函數(shù)使用struct mem_dev *dev = filp-private_data可根據(jù)私有文件指針指定找到 具體的設(shè)備,read函數(shù)參數(shù)沒有inode,無法獲取此設(shè)備號。kmalloc分配內(nèi)存,返回地址,根據(jù)其返回的地址就可操作內(nèi)存中的數(shù)據(jù)copy_to_user(buf,(void*)(dev-data+p),

9、count)這里的(dev-data+p)為什么要用(void *)強(qiáng) 制轉(zhuǎn)換呢? copy_to_user 是這么定義的 int copy_to_user(void _user *to ,const void *to , int n), 但還是不理解。驅(qū)動程序調(diào)試分類:打印調(diào)試,調(diào)試器調(diào)試(kgdb),查詢調(diào)試(proc文件系統(tǒng))合理的使用printk可以全局的打開或關(guān)閉它們。并發(fā):多個(gè)執(zhí)行單元同時(shí)被執(zhí)行竟態(tài):并發(fā)的執(zhí)行單元對共享資源(硬件資源或全局變量等)的共享訪問通過semaphore機(jī)制和spin_lock機(jī)制實(shí)現(xiàn)獲取信號量不成功該阻塞或者睡眠定義信號量 struct semaphor

10、e sem;初始化信號量 void sema_init(struct semaphore *sem ,int val)初始化信號量的初值為valvoid init_MUTEX(struct semaphore *sem)初始化一個(gè)互斥鎖,把 sem 的值設(shè)為 1void init_MUTEX_LOCKED(struct semaphore *sem)初始化一個(gè)互斥鎖,把 sem 的值設(shè) 為0定義與初始化工作可由如下宏一步完成DECLARE_MUTEX(name )定義一個(gè)信號量,并初始化為1DECLARE_MUTEX_LOCK(name)定義一個(gè)信號量,并初始化為0,為已鎖狀態(tài)獲取信號量voi

11、d down(struct semaphore *sem)可能會導(dǎo)致進(jìn)程睡眠,故不能在中斷上下文 中使用,如果sem非負(fù)直接返回,否則掛起(TASK_UNINTERRUPTIBLE)不建議使用void down_interrruptible(struct semaphore *sem)信 號量不 可用 , 置為 TASK_INTERRUPTIBLEvoid down_killable(struct semaphore *sem)信號量不可用,置為 TASK_KILLABLEvoid up(struct semaphore *sem) 釋放信號量自旋鎖不會引起調(diào)用者的睡眠,線程會移植忙循環(huán),移植

12、等待下去spin_lock_init(x)初始化自旋鎖spin_lock(lock)獲取自旋鎖,不成功自旋在那spin_trylock(lock)不會一直等待spin_unlock信號量可以有多個(gè)持有者(1個(gè)互斥信號量),自旋鎖只有一個(gè)持有者信號量適合保持時(shí)間較長,自旋鎖適合保持時(shí)間較短Ioctl對硬件進(jìn)行控制(改變波特率,報(bào)告錯(cuò)誤信息)用戶使用方法:int ioctl(int fd, unsigned long cmd,)點(diǎn)表示可選參數(shù)int(*ioctl)(struct inode *inode, struct file *filp, unsigned int cmd, unsigned

13、long arg)cmd用戶空間傳下來的,arg用戶傳下來的參數(shù)ioctl命令實(shí)現(xiàn)方法:1.定義命令2.實(shí)現(xiàn)命令Documentation/ioctl-number.txt 定義了使用的幻數(shù)ioctl被劃分為幾個(gè)位段,include/asm/ioctl.h定義了這些字段:類型(幻數(shù)):8位寬,屬于哪一類設(shè)備序號:表明設(shè)備命令的第幾個(gè)傳送方向:可能的值是_IOC_NONE , _IOC_READ, _IOC_WRITE是從應(yīng)用程序的觀點(diǎn) 來看的4 .參數(shù)的大小(數(shù)據(jù)的類型)內(nèi)核提供下列宏來幫助定義命令_IO(type,nr)沒有參數(shù)傳遞_IOR(type, nr, datatype)從驅(qū)動中讀數(shù)

14、據(jù)_I0W(type, nr, datatype)從數(shù)據(jù)到驅(qū)動_IOWR(type, nr, datatype)type 和 number 成員作為參數(shù)被傳遞Ioctl函數(shù)的實(shí)現(xiàn)1.返回值2.參數(shù)使用3.命令操作 通常是個(gè)switch語句,不支持的返回-EINVAL使用ioctl中的參數(shù):整數(shù)可以直接使用,指針則使用前需進(jìn)行正確的檢查 參數(shù)檢查不需要檢測的函數(shù):copy_from_ user, copy_to_user, get_user, put_user需要檢測的函數(shù):get_user, _put_userint access_ok(int type, const void *addr,

15、unsingned long size)第一參數(shù)是VERIFY_READ或者VERIFY_WRITE, addr是要操作的用戶內(nèi)存的地址,size 是操作的長度。access_ok返回一個(gè)布爾值:1.存取沒問題0.失敗,如果返回失敗, 則ioctl應(yīng)當(dāng)返回-EFAULT.等待隊(duì)列:實(shí)現(xiàn)進(jìn)程的阻塞,保存進(jìn)程的容器,阻塞時(shí)放入等待隊(duì)列,喚醒時(shí),取出進(jìn)程 定義等待隊(duì)歹 Uwait_queue_head_t my_queue 初始化等待隊(duì)列wait_waitqueue_head(&my_queue) 定義并初始化等待隊(duì)列DECLARE_WAIT_QUEUE_HEAD(my_queue)有條件睡眠wai

16、t_event(queue, condition)當(dāng) condition 為真, 返 回。當(dāng) condition 為假,進(jìn) 入TASK_UNINTERRUTIBLE睡眠,并掛在queue指定的等待隊(duì)列上wait_event_interruptible(queue, condition)wait_event_killable(queue, conditon)無條件睡眠(老版本,不建議使用)sleep_on(wait_queue_head_t *q) interruptible_sleep_on(wait_queue_head_t *q)等待隊(duì)列中喚醒進(jìn)程Wake_up(wait_queue_t

17、*q)喚醒等待隊(duì)列中的所有進(jìn)程都喚醒Wake_up_interruptible(wait_queue_t *q)喚醒為 TASK_INTERRUPTIBLE進(jìn)程阻塞方式是文件讀寫的默認(rèn)方式,應(yīng)用程序可以使用O_NONBLOCK標(biāo)志非阻塞的設(shè)置了 O_NONBLOCK,系統(tǒng)只是簡單的返回-EAGAINSelect系統(tǒng)調(diào)用對應(yīng)于pollSelect用于多路監(jiān)控,如沒有一個(gè)文件滿足要求,select將阻塞進(jìn)程Int select(int maxfd, fd_set *reedfds, fd_set *writefds, fd_set *exceptfds, const struct timeval

18、*timeout)maxfd:文件描述符的范圍,比檢測的最大文件描述符大1Readfds:被讀監(jiān)控的文件描述符Writefds:被寫監(jiān)控的Exceptfds:被異常監(jiān)控的Timeout:定時(shí)器Timeout為0時(shí)不管有沒有文件滿足要求,立即返回,無文件滿足,返回0為NULL時(shí),select將阻塞進(jìn)程,直到文件滿足要求為止為正整數(shù)的時(shí)候,等待的最長時(shí)間,即select在timeout時(shí)間內(nèi)阻塞進(jìn)程Select返回值正常返回滿足要求的文件描述符個(gè)數(shù)沒有滿足的返回0select被某個(gè)信號打斷,返回-1 , errno為EINTRSelect系統(tǒng)調(diào)用: 1.將要監(jiān)控的文件添加到文件描述符集調(diào)用sele

19、ct開始監(jiān)控判斷文件是否滿足要求將fd添加到fdset中在fdset中清楚fd清空fdset檢測文件描述集中的需判斷的fd發(fā)生變化VOid FD_SET(int fd, fd_set *fdset)VOid FD_CLR(int fd, fd_set *fdset)VOid FD_ZERO(fd_set *fdset)VOid FD_ISSET(int fd, fd_set *fdset)驅(qū)動通常由poll實(shí)現(xiàn)Unsigned int(*poll)(struct file *filp, poll_table *wait)負(fù)責(zé)完成:使用poll_wait將等待隊(duì)列添加到poll_table中返回

20、描述設(shè)備是否可讀可寫的掩碼 位掩碼:POLLIN設(shè)備可讀,POLLRDNORM數(shù)據(jù)可讀,POLLOUT設(shè)備可寫,POLLWRNORM數(shù)據(jù) 可寫設(shè)備可讀通常返回(POLLIN I POLLRDNORM)設(shè)備可寫通常返回(POLLOUT I POLLWRNORM)Poll方法只是做一個(gè)登記,真正的阻塞發(fā)生在select.c中的do_select函數(shù)(分析了 do_select 函數(shù))自動創(chuàng)建設(shè)備文件2.4 內(nèi)核使用 devfs_register(devfs_handle_t dir, const char *name, unsigned int flags, unsigned int major

21、unsigned int minor, umode_t mode, void *ops, void *info)Dir:目錄名,name:文件名;flags:創(chuàng)建標(biāo)志;major:主設(shè)備號;minor此設(shè)備號;mode:創(chuàng)建模式;ops:操作函數(shù)集;info:通常為空從2.6.13開始,devfs不復(fù)存在,udev成為替代使用class_create 為設(shè)備創(chuàng)建一個(gè) class,使用device_create創(chuàng)建對應(yīng)的設(shè)備例:struct class *myclass = class_create(THIS_MODULE, “my_device_driver”);Device_create(m

22、yclass, NULL, MKDEV(major_num, 0), NULL, “my_device”) void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset)負(fù)責(zé)把文件內(nèi)容映射到進(jìn)程的虛擬內(nèi)存空間,通過對這段內(nèi)存的讀取和修改,來實(shí)現(xiàn)對文件 的讀取和修改,而不需要再調(diào)用read,write等操作。addr:映射的起始地址,通常為NULL,由系統(tǒng)指定length:映射文件的長度prot:映射區(qū)的保護(hù)方式PROT_EXEC:映射區(qū)可被執(zhí)行,PROT_READ:映射區(qū)可被讀取, PROT_WRITE

23、 :映射區(qū)可被寫入flags:映射區(qū)的特性MAP_SHARED:寫入映射區(qū)的數(shù)據(jù)會復(fù)制回文件,且允許其他映射該 文件的進(jìn)程共享。MAP_PRIVATE:對映射區(qū)的寫入操作會產(chǎn)生一個(gè)映射區(qū)的復(fù)制 (copy-on-write),對此區(qū)域的修改不會寫回源文件。fd:由open返回的文件描述符,代表要映射的文件offset:以文件開始處的偏移量,必須是分頁大小的整數(shù)倍,通常為0,表示從文件頭開始映 射。注意mmap不能映像原有文件的長度int munmap(void *start, size_t length)成功返回0,失敗返回-1. start的取值一般是mmap返回的地址虛擬內(nèi)存區(qū)域:是虛擬地

24、址空間的一個(gè)同質(zhì)區(qū)間,即有同樣特性的連續(xù)地址范圍。一個(gè)進(jìn)程 的內(nèi)存映像由以下幾部分組成:程序代碼,數(shù)據(jù),BSS和棧區(qū)域,以及內(nèi)存映射區(qū)域一個(gè)進(jìn)程的內(nèi)存區(qū)域可以通過查看/proc/pid/maps每一行的域?yàn)椋簊tart_end perm offset major:minor inodelinux內(nèi)核使用結(jié)構(gòu)vm_area_struct來描述虛擬內(nèi)存區(qū)域,其中主要成員如下:unsigned long vm_start虛擬內(nèi)存區(qū)域起始地址unsigned long vm_end虛擬內(nèi)存區(qū)域結(jié)束地址unsigned long vm_flags映射一個(gè)設(shè)備是指把用戶空間的一段地址關(guān)聯(lián)到設(shè)備內(nèi)存上。mm

25、ap做了三件事:1.找到用戶空間地址(內(nèi)核完成)2.找到設(shè)備的物理地址(原理圖)3. 關(guān)聯(lián)(通過頁式管理)mmap設(shè)備方法需要做的就是建立虛擬地址到物理地址的頁表。int( *mmap)( struct file *, struct vm_area_struct *)建立頁表有兩種方法:使用remap_pfn_range 一次建立所有頁表;使用nopage VMA方法每次建立一個(gè)也表。int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn, unsigned long size,

26、 pgprot_t prot)vma:虛擬內(nèi)存區(qū)域指針virt_addr:虛擬地址的起始值pfn:要映射的物理地址所在的物理頁 禎號,可將物理地址PAGE_SHIFT得到(PAGE_SHIFT為12,相當(dāng)于除以4KB) size:要映射的區(qū)域的大小prot: VMA的保護(hù)屬性硬件訪問寄存器和內(nèi)存的區(qū)別:寄存器和RAM主要不同在于寄存器操作由副作用(sideeffect或邊際效果):讀取某刻地址可能導(dǎo)致該地址內(nèi)容變化,讀中斷狀態(tài)寄存器,便自動清 零內(nèi)存與IO在X86存在IO空間(串口并口等),在32為x86IO空間是64K,內(nèi)存空間是4G, ARM, PowerPC只有內(nèi)存地址空間的IO端口:一

27、個(gè)寄存器或內(nèi)存位于IO空間時(shí),稱為IO端口IO內(nèi)存:一個(gè)寄存器或內(nèi)存位于內(nèi)存空間時(shí),稱為IO內(nèi)存對IO端口的操作需要按如下步驟完成:1,申請2,訪問3,釋放 申請:struct resource *request_region(unsigned long first, unsigned long n, const char *name) 從first開始的n個(gè)端口,name設(shè)備名字系統(tǒng)中端口的分配情況記錄在/proc/ioports中訪問:intb outb intw outw intl outl釋放:void release_region(unsigned long start, unsig

28、ned long n)IO內(nèi)存有4步:1.申請2,映射3,訪問4,釋放申請:struct resource *request_mem_region(unsigned long start, unsigned long len,char*name)從 start開始,長度為len字節(jié)的內(nèi)存區(qū)。成功,返回非NULL,否則返回NULL??稍?proc/iomem中列出訪問:在訪問IO內(nèi)存之前,必須進(jìn)行物理地址到虛擬地址的轉(zhuǎn)化,使用下面函數(shù)void *ioremap(unsigned long phys_addr, unsigned long size)訪問:ioread8(void *addr)io

29、write8(u8 value, void *addr) 老版本 使用 readb writeb釋放: 1, void iounmap(void *addr) 2,void release_mem_region(unsigned longstart, unsigned long len)混雜設(shè)備驅(qū)動:共享一個(gè)主設(shè)備號10,成為混雜設(shè)備Linux內(nèi)核使用struct miscdevice描述混雜設(shè)備struct miscdevice(int minor;const char *name;const struct file_operations *fops;struct list_head lis

30、t;struct device *parent;struct device *this_device;使用 misc_register 函數(shù)來注冊一個(gè)混雜設(shè)備驅(qū)動 misc_register(struct miscdevice *misc)使用上拉下拉避免懸浮Linux總線設(shè)備驅(qū)動模型(2.6內(nèi)核難點(diǎn))Sysfs文件系統(tǒng)(基于內(nèi)存,展示內(nèi)核數(shù)據(jù)結(jié)構(gòu)屬性,關(guān)系),與proc同類別的文件系統(tǒng)同 類別的文件系統(tǒng),sysfs把連接在系統(tǒng)上的設(shè)備和總線組織成分級的文件,使其從用戶空間 可以訪問到sysfs 在/sys/目錄下block目錄:塊設(shè)備信息 bus:總線(ide pci scsi sbpcmc

31、ia)里邊還有devices和drivers目錄,devices目錄下都是軟鏈接class目錄:按照功能進(jìn)行分類(網(wǎng)絡(luò))devices:包含系統(tǒng)所有的設(shè)備kernel:內(nèi)核中的配置參數(shù)Module:系統(tǒng)中所有模塊信息 firmware:系統(tǒng)中的固件fs:描述系統(tǒng)中的文件系統(tǒng)power:系統(tǒng)電源選項(xiàng)Kobject實(shí)現(xiàn)了基本的面向?qū)ο蠊芾頇C(jī)制,與sysfs文件系統(tǒng)緊密相連,在內(nèi)核中注冊的每個(gè) kobject對象對應(yīng)sysfs文件系統(tǒng)中的一個(gè)目錄(作用:在sys下創(chuàng)建一個(gè)目錄)類似于C+中 的基類。void kobject_init(struct kobject *kobj)初始化 kobject

32、結(jié)構(gòu)int kobject_add(strut kobject *kobj)將 kobject 對象注冊到 Linux 系統(tǒng)int kobject_init_and_add(struct kobject *kobj, struct kobj_type *ktype, structkobject *parent, bonst char *fmt, .)初始化 kobject,并注冊到 Linuxvoid kobject_del(struct kobject *kobj)從 Linux 系統(tǒng)中刪除 kobject 對象struct kobject *kobject_get ( struct kob

33、ject*kobj)將kobject對象引用計(jì)數(shù)加1,同時(shí)返回該對象指針void kobject_put(struct kobject*kobj)將 kobject對象的引用計(jì)數(shù)減1,如果引用計(jì)數(shù)降為0,則調(diào)用release方法釋放該kobject 對象kobject的ktype成員是一個(gè)特指向kobj_type結(jié)構(gòu)的指針,該結(jié)構(gòu)記錄了 kobject對象的一些 屬性struct kobj_type(void(*release)(struct kobject *kobj);struct sysfs_ops *sysfs_ops;struct attribute *default_attrs;r

34、elease:用于釋放kobject占用的資源,當(dāng)kobject的引用為0時(shí)被調(diào)用struct attribute(char *name;struct module *owner;mode_t mode; /*屬性的保護(hù)位*/對應(yīng)于kobject的目錄下的一個(gè)文件,name成員就是文件名struct sysfs_opsssize_t(*show)(struct kobject *, struct attribute*, char *) ssize_t(*store)(struct kobject *, struct attribute *, const char *,size_t)show :

35、當(dāng)用戶讀屬性文件時(shí),該函數(shù)被調(diào)用,該函數(shù)將屬性值存入buffer中返回給用戶態(tài) store :當(dāng)用戶寫屬性文件時(shí),該函數(shù)被調(diào)用,用于存儲用戶傳入的屬性值(學(xué)習(xí)函數(shù)指針三點(diǎn)參數(shù)是怎么樣的(從哪來到哪去)2.這個(gè)函數(shù)指針什么時(shí)候被調(diào)用3.這個(gè)函數(shù)用來做什么) kset是具有相同類型的kobject的結(jié)合,在sysfs中體現(xiàn)一個(gè)目錄,kobject里邊只能是文件不 能是目錄struct ksetstruct list_head list; 鏈接該 kset 中所有 kobject 的鏈表頭spinlock_t list_losk;struct kobject kobj; /內(nèi)嵌的 kobjectst

36、ruct kset_uevent_ops *uevent_ops /處理熱插拔事件的操作集合kset操作:int kset_register(struct kset *kset) 在內(nèi)核中注冊一個(gè) ksetvoid kset_unregister(struct kset *kset) 在內(nèi)核中注銷一個(gè) kset熱插拔事件:當(dāng)系統(tǒng)配置發(fā)生變化時(shí),如:添加kset到系統(tǒng);移動kobject,一個(gè)通知會從 內(nèi)核空間發(fā)送到用戶空間,這就是熱插拔事件。熱插拔事件導(dǎo)致用戶空間相應(yīng)的處理程序(如 udev,mdev)被調(diào)用,這些處理程序會通過加載驅(qū)動程序,創(chuàng)建設(shè)備節(jié)點(diǎn)等來響應(yīng)熱插拔事 件操作集合struct

37、 kset_uevent_opsint(*filter)(struct kset *kset, struct kobject *kobj);const char *(*name)(struct kset *kset, struct kobject *kobj);int(*uevent)(struct kset *kset, struct kobject *kobj, structkobj_uevent_env *env);當(dāng)該kset所管理的kobject和kset狀態(tài)發(fā)生變化時(shí)(如被加入,移動),這三個(gè)函數(shù)將被調(diào) 用。filter函數(shù):決定是否將事件傳遞到用戶空間。如果filter返回0,不

38、傳遞事件name函數(shù):用于將字符串傳遞給用戶空間的熱插拔處理程序uevent函數(shù):將用戶空間需要的參數(shù)添加到環(huán)境變量中l(wèi)inux2.6內(nèi)核提供了全新的內(nèi)核設(shè)備模型設(shè)備模型元素:總線,設(shè)備,驅(qū)動總線:處理器和設(shè)備之間的通道,所有的設(shè)備都通過總線相連,包括platform總線(虛擬平 臺總線),總線由bus_type結(jié)構(gòu)表示總線的注冊使用:bus_register(struct bus_type *bus)若成功,可在sysfs的/sys/bus下看到總線的刪除使用:void bus_unregister(struct bus_type *bus)int(*match)(struct device

39、 *dev, struct device_driver *drv)當(dāng)一個(gè)新設(shè)備或者驅(qū)動添加到這個(gè)總線時(shí),用于判斷指定的驅(qū)動程序是否能處理指定的設(shè) 備??梢苑祷胤橇阒礽nt (*uevent)(struct device *dev, char *envp, int num_envp, char *buffer,int buffer_size)在為用戶空間產(chǎn)生熱插拔事件之前,這個(gè)方法允許總線添加環(huán)境變量總線的屬性由bus_attribute描述,定義如下:struct bus_attribute(struct attribute attr;ssize_t(*show)(struct bus-typ

40、e *, char *buf);ssize_t(*store)(struct bus_type *, const char *buf, size_t count);int bus_create_file(struct bus_type *bus, struct bus_attribute *attr)倉0建屬性void bus_remove_file(struct bus_type *bus, struct bus_attribute *attr) 刪除屬性Linux系統(tǒng)中每個(gè)設(shè)備由一個(gè)struct device描述int device_register(struct device *dev)

41、 注冊設(shè)備void device_unregister(struct device *dev) 注銷設(shè)備一條總線也是個(gè)設(shè)備,也必須按設(shè)備注冊struct device_attributestruct attribute attr;ssize_t(*show)(struct device *dev, struct device_attribute *attr, char*buf);ssize_t(*store)(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);int device_

42、create_file(struct device *device, struct device_attribute *entry)創(chuàng)建屬性void device_remove_file(struct device *dev, struct device_attribute *attr)刪除屬性驅(qū)動程序由struct device_driver描述int driver_register(struct device_driver *drv) 注冊驅(qū)動void driver_unregister(struct device_driver *drv) 注銷驅(qū)動驅(qū)動的屬性使用struct driver

43、_attribute來描述stryct druver_attributestruct attribute attr;ssize_t(*show)(struct device_driver *drv, char *buf);ssize_t(*store)(struct device_driver *drv, const char *buf, size_tcount);int driver_create_file(struct device_driver *drv, struct driver_attribute*attr)創(chuàng)建屬性void driver_remove_file(struct de

44、vice_driver *drv, struct driver_attribute*attr)刪除屬性platform總線:2.6內(nèi)核加入的虛擬總線,由platform_device和platform_driver兩部分組成 platform優(yōu)勢在于platform機(jī)制將設(shè)備本身的資源注冊進(jìn)內(nèi)核,由內(nèi)核同意管理,在驅(qū)動程 序使用這些資源提供統(tǒng)一的接口,提高可以執(zhí)行。通過 platform 流程:1.定義 platform_device 2.注冊 platform_device3,定義 platform_driver 4.注冊 platform_driver平臺設(shè)備使用struct platfo

45、rm_device來描述struct platform_device(const char *name; 設(shè)備名int id;設(shè)備編號,配合設(shè)備名使用struct device dev ;u32 num_resources;struct resource resource;設(shè)備資源(中斷號,基地址)platform_device 的分配使用:struct platform_device *platform_device_alloc(const char *name, int id)name:設(shè)備名id:設(shè)備id,一般為-1注冊平臺設(shè)備,使用函數(shù)int platform_device_add(struct platform_device *pdev)平臺設(shè)備資源使

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論