5.1 API和libc规范
        linux:create/open/close/write/read/lseek/
        libc fopen/fgetc/fputc/fgets/fputs/fread/fwrite/fgetpos/fsetpos/fseek/fclose/
    5.2 文件系统目录结构
                1./bin 2./sbin 3./dev 4./etc 5./lib 6./mnt
                7./opt 8./proc 9./tmp 10./usr 11./var 12./sys
        5.2.1 文件系统与驱动
              VFS、FS、Devices接口是file_operations结构体成员函数:包含打开、关闭、读写、控制等一些列函数
            *********文件系统与驱动之间关系***********

             

第五章  Linux文件系统与设备文件


            **********APP与VFS与Dev_drivers关系*******************

           

第五章  Linux文件系统与设备文件


            一般只关注file和inode两个结构体
            1.file结构体
            
                struct file {
                    union {
                        struct llist_node    fu_llist;
                        struct rcu_head     fu_rcuhead;
                    } f_u;
                    struct path        f_path;
                    struct inode        *f_inode;    /* cached value */
                    const struct file_operations    *f_op;

                    /*
                     * Protects f_ep_links, f_flags.
                     * Must not be taken from IRQ context.
                     */
                    spinlock_t        f_lock;
                    enum rw_hint        f_write_hint;
                    atomic_long_t        f_count;
                    unsigned int         f_flags;
                    fmode_t            f_mode;
                    struct mutex        f_pos_lock;
                    loff_t            f_pos;
                    struct fown_struct    f_owner;
                    const struct cred    *f_cred;
                    struct file_ra_state    f_ra;

                    u64            f_version;
                #ifdef CONFIG_SECURITY
                    void            *f_security;
                #endif
                    /* needed for tty driver, and maybe others */
                    void            *private_data;

                #ifdef CONFIG_EPOLL
                    /* Used by fs/eventpoll.c to link all the hooks to this file */
                    struct list_head    f_ep_links;
                    struct list_head    f_tfile_llink;
                #endif /* #ifdef CONFIG_EPOLL */
                    struct address_space    *f_mapping;
                    errseq_t        f_wb_err;
                    errseq_t        f_sb_err; /* for syncfs */
                } __randomize_layout
                  __attribute__((aligned(4)));    /* lest something weird decides that 2 is OK */

            2.inode结构体
                VFS inode包含访问权限/属主/组/大小/生成时间/访问时间等.是linux管理fs的基本单元,也是fs连接子目录、文件的桥梁、inode定义
                        /*
                         * Keep mostly read-only and often accessed (especially for
                         * the RCU path lookup and 'stat' data) fields at the beginning
                         * of the 'struct inode'
                         */
                        struct inode {
                            umode_t            i_mode;
                            unsigned short        i_opflags;
                            kuid_t            i_uid;
                            kgid_t            i_gid;
                            unsigned int        i_flags;

                        #ifdef CONFIG_FS_POSIX_ACL
                            struct posix_acl    *i_acl;
                            struct posix_acl    *i_default_acl;
                        #endif

                            const struct inode_operations    *i_op;
                            struct super_block    *i_sb;
                            struct address_space    *i_mapping;

                        #ifdef CONFIG_SECURITY
                            void            *i_security;
                        #endif

                            /* Stat data, not accessed from path walking */
                            unsigned long        i_ino;
                            /*
                             * Filesystems may only read i_nlink directly.  They shall use the
                             * following functions for modification:
                             *
                             *    (set|clear|inc|drop)_nlink
                             *    inode_(inc|dec)_link_count
                             */
                            union {
                                const unsigned int i_nlink;
                                unsigned int __i_nlink;
                            };
                            dev_t            i_rdev; //主设备为dev_t高12位、次设备号为dev_t的低20位
                            loff_t            i_size;
                            struct timespec64    i_atime;
                            struct timespec64    i_mtime;
                            struct timespec64    i_ctime;
                            spinlock_t        i_lock;    /* i_blocks, i_bytes, maybe i_size */
                            unsigned short          i_bytes;
                            u8            i_blkbits;
                            u8            i_write_hint;
                            blkcnt_t        i_blocks;

                        #ifdef __NEED_I_SIZE_ORDERED
                            seqcount_t        i_size_seqcount;
                        #endif

                            /* Misc */
                            unsigned long        i_state;
                            struct rw_semaphore    i_rwsem;

                            unsigned long        dirtied_when;    /* jiffies of first dirtying */
                            unsigned long        dirtied_time_when;

                            struct hlist_node    i_hash;
                            struct list_head    i_io_list;    /* backing dev IO list */
                        #ifdef CONFIG_CGROUP_WRITEBACK
                            struct bdi_writeback    *i_wb;        /* the associated cgroup wb */

                            /* foreign inode detection, see wbc_detach_inode() */
                            int            i_wb_frn_winner;
                            u16            i_wb_frn_avg_time;
                            u16            i_wb_frn_history;
                        #endif
                            struct list_head    i_lru;        /* inode LRU list */
                            struct list_head    i_sb_list;
                            struct list_head    i_wb_list;    /* backing dev writeback list */
                            union {
                                struct hlist_head    i_dentry;
                                struct rcu_head        i_rcu;
                            };
                            atomic64_t        i_version;
                            atomic64_t        i_sequence; /* see futex */
                            atomic_t        i_count;
                            atomic_t        i_dio_count;
                            atomic_t        i_writecount;
                        #if defined(CONFIG_IMA) || defined(CONFIG_FILE_LOCKING)
                            atomic_t        i_readcount; /* struct files open RO */
                        #endif
                            union {
                                const struct file_operations    *i_fop;    /* former ->i_op->default_file_ops */
                                void (*free_inode)(struct inode *);
                            };
                            struct file_lock_context    *i_flctx;
                            struct address_space    i_data;
                            struct list_head    i_devices;
                            union {
                                struct pipe_inode_info    *i_pipe;
                                struct block_device    *i_bdev;
                                struct cdev        *i_cdev;
                                char            *i_link;
                                unsigned        i_dir_seq;
                            };

                            __u32            i_generation;

                        #ifdef CONFIG_FSNOTIFY
                            __u32            i_fsnotify_mask; /* all events this inode cares about */
                            struct fsnotify_mark_connector __rcu    *i_fsnotify_marks;
                        #endif

                        #ifdef CONFIG_FS_ENCRYPTION
                            struct fscrypt_info    *i_crypt_info;
                        #endif

                        #ifdef CONFIG_FS_VERITY
                            struct fsverity_info    *i_verity_info;
                        #endif

                            void            *i_private; /* fs or device private pointer */
                        } __randomize_layout;
                        
                        --/proc/devices可获知文件系统注册的设备号,第一列为主设备号、第二列为设备名
                        --统一驱动可支持多个同类设备、故用次设备号描述使用该驱动的设备的序号,一般从0开始
    5.3 devfs(2.4)和udev(2.6)
        5.3.1 devfs实现设备驱动程序自主管理自己的设备文件。
        优点如下
            1.可通过程序在设备初始化时在/dev目录下创建设备文件,卸载设备时将它删除
            2.驱动可指定设备名称、所有者、权限位、用户空间程序仍可修改所有者和权限位
            3.不再需要为驱动分配主设备号以及处理次设备号,在程序中可直接给register_chrdev()传递0主设备以及获得可用主设备号,并在devfs_register()中指定次设备号
              devfs_handle_t devfs_mk_dir(devfs_handle_t dir,const char* name, void *info);
              devfs_handle_t devfs_register(devfs_handle_t dir,...);
              void devfs_unregister(devfs_handle_t de);
            4. static devfs_handle_t devfs_handle;
               static int __init xxx_init(void){
                int ret;
                int i;
                ret = register_chrdev(xxx_MAJOR,DEVICE_MAME,&xxx_fops);
                if(ret<0){
                
                }
                //创建设备文件
                devfs_handle = devfs_register(NULL,DEVICE_NAME,DEVFS_FL_DEVFAULT,XXX_MAJOR,0,S_IFCHR|S_IRUSR|S_IWUSR,&xxx_fops,NULL);
                ...
                printk(DEVICE_NAME"initialized\n);
                return 0;
               }
               static void __exit xxx_exit(void){
                devfs_unregister(devfs_handle);
                unregister_chrdev(XXX_MAJOR,DEVICE_NAME);
               }
               
               module_init(xxx_init);
               module_exit(xxx_exit);
            
            udev取代devfs的原因
                1.devfs所做工作在用户态可完成
                2.devfs被加入内核时大家期望其质量可赶上
                3.devfs存在无法修复的bug
                devfs作者停止维护
    5.4 设备驱动模型、sysfs、udev规则
            linux设计强调的基本观点是机制和策略分离。机制是做某件事的固定步骤、方法
            策略是没一个步骤所采取的不同方式。
            机制相对固定、稳定
            策略不固定、也不稳定
            采用devfs,当一个并不存在的/dev节点被打开时,devfs能自动加载对应的驱动,而udev则不这么做.因为udev认为linux应该在设备被发现时加载驱动模块,而不是被访问时。udev认为devfs是多余的。系统中所有设备都应该差生热插拔事件并加载恰当的驱动。而udev能够为创建对应的设备结点。
        5.4.2 sysfs与linux设备模型
            1. 2.6以后引入,同级别proc/devfs/devpty等,是虚拟fs
            2. 可产生一个包括所有系统硬件的层级视图,与提供进程和状态信息的proc文件系统十分类似.
            3.展示设备驱动模型中各组件的层次关系,顶级目录block/bus/dev/devices/class/fs/kernel/power/firmware等
            4.驱动和设备必然依赖于总线,故都包含struct bus_type指针.内核中设备和驱动是分开注册,注册1个设备时,并不需要驱动已经工作,而却用被注册时,也不需要设备已经注册,各自涌向内核,每个设备和驱动涌入内核时,都会寻找另一半,这里正是bus_type的match()成员函数将两者捆绑在一起.
            5.总线、驱动和设备最终都会落实为sysfs中的1个目录,追踪发现都是kobject派生的.故kobject可看做总线/设备/驱动的抽象基类,1个kobject对应1个sysfs的1个目录.
            *****attribute_bus_attribute_driver_attribute_device_attribute结构体****************

             
        5.4.3 udev的组成
            1.udev和systemd合并,在用户空间执行,动态建立/删除设备文件,允许用户不必关心主次设备号而提供LSB名称,可根据需要固定名称
            2.udev工作过程。
                1.内核检测到设备通过netlink套接字发送uevent
                2.udev获取信息,匹配规则(Subsystem/action/attribute/内核提供的名称-KERNEL=)以及其他环境变量
                3.根据netlink检测信息创建命名规则,
                    #Kingston USB mass storage
                    SUBSYSTEM=="block",ACTION="add",KERNEL=="sd",ENV(ID_TYPE)=="disk",ENV(ID_VENDOR)=="Kingston",ENV(ID_USB_DRIVER)=="usb-storage",SYMLINK+="kingstonUD"
        
        5.4.4 udev规则文件
        
        5.5 总结
             linux 2.6 通过一些列数据结构定义了设备模型,设备模型与sysfs文件系统中的目录和文件存在一种对应关系.设备和驱动分离,并通过总线进行匹配
             2.udev可利用内核通过netlink发出的uevent信息动态创建设备文件节点。
                

相关文章: