驅(qū)動(dòng)程序就是向下控制硬件,向上提供接口,這里的向上提供的接口最終對(duì)應(yīng)到應(yīng)用層有三種方式:設(shè)備文件,/proc,/sys,其中最常用的就是使用設(shè)備文件,而Linux設(shè)備中用的最多的就是字符設(shè)備,本文就以字符設(shè)備為例來分析創(chuàng)建并打開一個(gè)字符設(shè)備的文件內(nèi)部機(jī)制。
struct inode
Linux中一切皆文件,當(dāng)我們?cè)贚inux中創(chuàng)建一個(gè)文件時(shí),就會(huì)在相應(yīng)的文件系統(tǒng)創(chuàng)建一個(gè)inode與之對(duì)應(yīng),文件實(shí)體和文件的inode是一一對(duì)應(yīng)的,創(chuàng)建好一個(gè)inode會(huì)存在存儲(chǔ)器中,第一次open就會(huì)將inode在內(nèi)存中有一個(gè)備份,同一個(gè)文件被多次打開并不會(huì)產(chǎn)生多個(gè)inode,當(dāng)所有被打開的文件都被close之后,inode在內(nèi)存中的實(shí)例才會(huì)被釋放。既然如此,當(dāng)我們使用mknod(或其他方法)創(chuàng)建一個(gè)設(shè)備文件時(shí),也會(huì)在文件系統(tǒng)中創(chuàng)建一個(gè)inode,這個(gè)inode和其他的inode一樣,用來存儲(chǔ)關(guān)于這個(gè)文件的靜態(tài)信息(不變的信息),包括這個(gè)設(shè)備文件對(duì)應(yīng)的設(shè)備號(hào),文件的路徑以及對(duì)應(yīng)的驅(qū)動(dòng)對(duì)象etc。inode作為VFS四大對(duì)象之一,在驅(qū)動(dòng)開發(fā)中很少需要自己進(jìn)行填充,更多的是在open()方法中進(jìn)行查看并根據(jù)需要填充我們的file結(jié)構(gòu)。
對(duì)于不同的文件類型,inode被填充的成員內(nèi)容也會(huì)有所不同,以創(chuàng)建字符設(shè)備為例,我們知道,add_chrdev_region其實(shí)是把一個(gè)驅(qū)動(dòng)對(duì)象和一個(gè)(一組)設(shè)備號(hào)聯(lián)系到一起。而創(chuàng)建設(shè)備文件,其實(shí)是把設(shè)備文件和設(shè)備號(hào)聯(lián)系到一起。至此,這三者就被綁定在一起了。這樣,內(nèi)核就有能力創(chuàng)建一個(gè)struct inode實(shí)例了,下面是4.8.5內(nèi)核中的inode。這個(gè)inode是VFS的inode,是最具體文件系統(tǒng)的inode的進(jìn)一步封裝,也是驅(qū)動(dòng)開發(fā)中關(guān)心的inode,針對(duì)具體的文件系統(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