驅(qū)動程序就是向下控制硬件,向上提供接口,這里的向上提供的接口最終對應(yīng)到應(yīng)用層有三種方式:設(shè)備文件,/proc,/sys,其中最常用的就是使用設(shè)備文件,而Linux設(shè)備中用的最多的就是字符設(shè)備,本文就以字符設(shè)備為例來分析創(chuàng)建并打開一個字符設(shè)備的文件內(nèi)部機(jī)制。
struct inode
Linux中一切皆文件,當(dāng)我們在Linux中創(chuàng)建一個文件時,就會在相應(yīng)的文件系統(tǒng)創(chuàng)建一個inode與之對應(yīng),文件實體和文件的inode是一一對應(yīng)的,創(chuàng)建好一個inode會存在存儲器中,第一次open就會將inode在內(nèi)存中有一個備份,同一個文件被多次打開并不會產(chǎn)生多個inode,當(dāng)所有被打開的文件都被close之后,inode在內(nèi)存中的實例才會被釋放。既然如此,當(dāng)我們使用mknod(或其他方法)創(chuàng)建一個設(shè)備文件時,也會在文件系統(tǒng)中創(chuàng)建一個inode,這個inode和其他的inode一樣,用來存儲關(guān)于這個文件的靜態(tài)信息(不變的信息),包括這個設(shè)備文件對應(yīng)的設(shè)備號,文件的路徑以及對應(yīng)的驅(qū)動對象etc。inode作為VFS四大對象之一,在驅(qū)動開發(fā)中很少需要自己進(jìn)行填充,更多的是在open()方法中進(jìn)行查看并根據(jù)需要填充我們的file結(jié)構(gòu)。
對于不同的文件類型,inode被填充的成員內(nèi)容也會有所不同,以創(chuàng)建字符設(shè)備為例,我們知道,add_chrdev_region其實是把一個驅(qū)動對象和一個(一組)設(shè)備號聯(lián)系到一起。而創(chuàng)建設(shè)備文件,其實是把設(shè)備文件和設(shè)備號聯(lián)系到一起。至此,這三者就被綁定在一起了。這樣,內(nèi)核就有能力創(chuàng)建一個struct inode實例了,下面是4.8.5內(nèi)核中的inode。這個inode是VFS的inode,是最具體文件系統(tǒng)的inode的進(jìn)一步封裝,也是驅(qū)動開發(fā)中關(guān)心的inode,針對具體的文件系統(tǒng),還有struct ext2_inode_info 等結(jié)構(gòu)。
//include/linux/fs.h 596 /* 597 * Keep mostly read-only and often accessed (especially for 598 * the RCU path lookup and 'stat' data) fields at the beginning 599 * of the 'struct inode' 600 */ 601 struct inode { 602 umode_t i_mode; 603 unsigned short i_opflags; 604 kuid_t i_uid; 605