驱动程序就是向下控制硬件,向上提供接口,这里的向上提供的接口最终对应到应用层有三种方式:设备文件,/proc,/sys,其中最常用的就是使用设备文件,而Linux设备中用的最多的就是字符设备,本文就以字符设备为例来分析创建并打开一个字符设备的文件内部机制。
struct
inode
Linux中一切皆文件,当我们在Linux中创建一个文件时,就会在相应的文件系统创建一个inode与之对应,文件实体和文件的inode是一一对应的,创建好一个inode会存在存储器中,第一次open就会将inode在内存中有一个备份,同一个文件被多次打开并不会产生多个inode,当所有被打开的文件都被close之后,inode在内存中的实例才会被释放。既然如此,当我们使用mknod(或其他方法)创建一个设备文件时,也会在文件系统中创建一个inode,这个inode和其他的inode一样,用来存储关于这个文件的静态信息(不变的信息),包括这个设备文件对应的设备号,文件的路径以及对应的驱动对象etc。inode作为VFS四大对象之一,在驱动开发中很少需要自己进行填充,更多的是在open()方法中进行查看并根据需要填充我们的file结构。
对于不同的文件类型,inode被填充的成员内容也会有所不同,以创建字符设备为例,我们知道,add_chrdev_region其实是把一个驱动对象和一个(一组)设备号联系到一起。而创建设备文件,其实是把设备文件和设备号联系到一起。至此,这三者就被绑定在一起了。这样,内核就有能力创建一个struct inode实例了,下面是4.8.5内核中的inode。这个inode是VFS的inode,是最具体文件系统的inode的进一步封装,也是驱动开发中关心的inode,针对具体的文件系统,还有struct ext2_inode_info 等结构。
//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
kgid_t
i_gid;
606
unsigned int
i_flags;
607
608 #ifdef CONFIG_FS_POSIX_ACL
609
struct posix_acl
*i_acl;
610
struct posix_acl
*i_default_acl;
611 #endif
612
613
const struct inode_operations *i_op;
614
struct super_block
*i_sb;
615
struct address_space *i_mapping;
616
617 #ifdef CONFIG_SECURITY
618
void
*i_security;
619 #endif
620
621
/* Stat data, not accessed from path walking */
622
unsigned long
i_ino;
623
/*
624
* Filesystems may only read i_nlink directly. They shall use the
625
* following functions for modification:
626
*
627
* (set|clear|inc|drop)_nlink
628
* inode_(inc|dec)_link_count
629
*/
630
union {
631
const unsigned int i_nlink;
632
unsigned int __i_nlink;
633
};
634
dev_t
i_rdev;
635
loff_t
i_size;
636
struct timespec
i_atime;
637
struct timespec
i_mtime;
638
struct timespec
i_ctime;
639
spinlock_t
i_lock;
/* i_blocks, i_bytes, maybe i_size */
640
unsigned short
i_bytes;
641
unsigned int
i_blkbits;
642
blkcnt_t
i_blocks;
643
644 #ifdef __NEED_I_SIZE_ORDERED
645
seqcount_t
i_size_seqcount;
646 #endif
647
648
/* Misc */
649
unsigned long
i_state;
650
struct rw_semaphore
i_rwsem;
651
652
unsigned long
dirtied_when;
/* jiffies of first dirtying */
653
unsigned long
dirtied_time_when;
654
655
struct hlist_node
i_hash;
656
struct list_head
i_io_list;
/* backing dev IO list */
657 #ifdef CONFIG_CGROUP_WRITEBACK
658
struct bdi_writeback *i_wb;
/* the associated cgroup wb */
659
660
/* foreign inode detection, see wbc_detach_inode() */
661
int
i_wb_frn_winner;
662
u16
i_wb_frn_avg_time;
663
u16
i_wb_frn_history;
664 #endif
665
struct list_head
i_lru;
/* inode LRU list */
666
struct list_head
i_sb_list;
667
struct list_head
i_wb_list;
/* backing dev writeback list */
668
union {
669
struct hlist_head
i_dentry;
670
struct rcu_head
i_rcu;
671
};
672
u64
i_version;
673
atomic_t
i_count;
674
atomic_t
i_dio_count;
675
atomic_t
i_writecount;
676 #ifdef CONFIG_IMA
677
atomic_t
i_readcount;
/* struct files open RO */
678 #endif
679
const struct file_operations *i_fop;
/* former ->i_op->default_file_ops */
680
struct file_lock_context
*i_flctx;
681
struct address_space i_data;
682
struct list_head
i_devices;
683
union {
684
struct pipe_inode_info *i_pipe;
685
struct block_device
*i_bdev;
686
struct cdev
*i_cdev;
687
char
*i_link;
688
unsigned
i_dir_seq;
689
};
690
691
__u32
i_generation;
692
693 #ifdef CONFIG_FSNOTIFY
694
__u32
i_fsnotify_mask;
/* all events this inode cares about */
695
struct hlist_head
i_fsnotify_marks;
696 #endif
697
698 #if IS_ENABLED(CONFIG_FS_ENCRYPTION)
699
struct fscrypt_info
*i_crypt_info;
700 #endif
701
702
void
*i_private;
/* fs or device private pointer */
703 };
这里面与本文相关的成员主要有: