Samsung_tiny4412(驱动笔记04)----volatile,container_of,file_operations,file,inode

/***********************************************************************************
 *                    
 *                volatile,container_of,file_operations,file,inode
 *
 *  声明:
 *      1. 本系列文档是在vim下编辑,请尽量是用vim来阅读,在其它编辑器下可能会
 *         不对齐,从而影响阅读.
 *      2. 本文的结构体的注释主要是参考网络上的解释,几乎无任何个人理解,主要是为后续
 *         代码编辑提供参考.
 *
 *                                          2015-3-8 阴 深圳 尚观 Etc 曾剑锋
 **********************************************************************************/

                        \\\\\\\--*目录*--//////////////
                        |  一. volatile修饰字段:             
                        |  二. container_of:                 
                        |  三. 驱动错误返回值:               
                        |  四. struct file_operations注释:   
                        |  五. struct file注释:              
                        |  六. struct inode注释:             
                        \\\\\\\\\///////////////////

一. volatile修饰字段:
    告诉gcc不要对该类型的数据做优化处理,对它的访问都是对内存的访问,而不是对寄存器的访问.

二. container_of:
    1. container_of定义:
        #define __offset(type, mem) 
            ((unsigned long)&(((type *)0)->mem))
        #define container_of(addr, type, mem)   
            ((type *)((void *)addr - __offset(type, mem)))
    2. container_of使用:
        static int test_open(struct inode *inode, struct file *file)
        {
            test_t *p;
            p = container_of(file->f_op, test_t, fops);
            file->private_data = p;

            return 0;
        }

三. 驱动错误返回值:
    #ifnder _ASM_GENERIC_ERRNO_BASE_H
        #define _ASM_GENERIC_ERRNO_BASE_H
        
        #define EPERM       1   /* Operation not permitted      --> 操作不允许                  */
        #define ENOENT      2   /* No such file or directory    --> 找不到对应文件或文件夹      */
        #define ESRCH       3   /* No such process              --> 找不到对应的进程            */
        #define EINTR       4   /* Interrupted system call      --> 被系统调用中断              */
        #define EIO         5   /* I/O error                    --> IO错误                      */
        #define ENXIO       6   /* No such device or address    --> 找不到对应的设备或者地址    */
        #define E2BIG       7   /* Argument list too long       --> 参数列表太长                */
        #define ENOEXEC     8   /* Exec format error            --> 执行格式错误                */
        #define EBADF       9   /* Bad file number              --> 错误的文件数                */
        #define ECHILD      10  /* No child processes           --> 没有子进程                  */
        #define EAGAIN      11  /* Try again                    --> 重新调用该函数调用          */
        #define ENOMEM      12  /* Out of memory                --> 内存溢出                    */
        #define EACCES      13  /* Permission denied            --> 权限被拒绝                  */
        #define EFAULT      14  /* Bad address                  --> 错误地址                    */
        #define ENOTBLK     15  /* Block device required        --> 需要块设备                  */
        #define EBUSY       16  /* Device or resource busy      --> 设备或者资源正在被使用      */
        #define EEXIST      17  /* File exists                  --> 文件已经存在                */
        #define EXDEV       18  /* Cross-device link            --> 交叉设备链接                */
        #define ENODEV      19  /* No such device               --> 找不到设备                  */
        #define ENOTDIR     20  /* Not a directory              --> 不是一个目录                */
        #define EISDIR      21  /* Is a directory               --> 是一个目录                  */
        #define EINVAL      22  /* Invalid argument             --> 非法的参数                  */
        #define ENFILE      23  /* File table overflow          --> 文件表溢出                  */
        #define EMFILE      24  /* Too many open files          --> 打开太多的文件              */
        #define ENOTTY      25  /* Not a typewriter             --> 不是设备命令                */
        #define ETXTBSY     26  /* Text file busy               --> 文本文件忙                  */
        #define EFBIG       27  /* File too large               --> 文件太大                    */
        #define ENOSPC      28  /* No space left on device      --> 设备空间不足                */
        #define ESPIPE      29  /* Illegal seek                 --> 非法的偏移                  */
        #define EROFS       30  /* Read-only file system        --> 只读文件系统                */
        #define EMLINK      31  /* Too many links               --> 链接太多                    */
        #define EPIPE       32  /* Broken pipe                  --> 损坏的管道                  */
        #define EDOM        33  /* Math argument out of domain of func  --> 数字参数超出函数域  */
        #define ERANGE      34  /* Math result not representable        --> 数字结果不能表示    */
    #endif

四. struct file_operations注释:
    struct file_operations {
        /* 指向拥有这个结构模块的指针,当模块被使用时,阻止模块被卸载,它被简单初始化为THIS_MODULE */
        struct module *owner;

        /* 用作改变文件当前读/写位置,并返回更改后新的位置 */
        loff_t (*llseek) (struct file *, loff_t, int);

        /* 用于从设备中获取数据,返回成功读取的字节数 */
        ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);

        /* 用于发送数据给设备,返回成功写入的字节数 */
        ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);

        /* 初始化一个异步读--可能在函数返回前不结束读操作 */
        ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);

        /* 初始化一个异步写--可能在函数返回前不结束写操作 */
        ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);

        /* 对于设备文件这个成员应当为NULL,它用来读取目录,并且仅对文件系统有用 */
        int (*readdir) (struct file *, void *, filldir_t);

        /* poll,epoll,select系统调用的后端,都用作查询对一个或多个文件描述符的读写是否阻塞 */
        unsigned int (*poll) (struct file *, struct poll_table_struct *);

        /* 提供了发出设备特定命令的方法 */
        long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
        long (*compat_ioctl) (struct file *, unsigned int, unsigned long);

        /* 用来请求将设备内存映射到进程的地址空间 */
        int (*mmap) (struct file *, struct vm_area_struct *);

        /* 对设备文件进行的第一个操作 */
        int (*open) (struct inode *, struct file *);

        /* 在进程关闭它的设备文件描述符的拷贝时调用,它应当执行设备的任何未完成的操作 */
        int (*flush) (struct file *, fl_owner_t id);

        /* 在文件结构被释放时引用这个操作 */
        int (*release) (struct inode *, struct file *);

        /* fsync系统调用的后端,用户调用来刷新任何挂着的数据 */
        int (*fsync) (struct file *, loff_t, loff_t, int datasync);

        /* 这是fsync方法的异步版本 */
        int (*aio_fsync) (struct kiocb *, int datasync);

        /* 这个操作用来通知设备的FASYNC标志的改变 */
        int (*fasync) (int, struct file *, int);

        /* 用来实现文件加锁,加锁对常规文件是必不可少的特性,但设备驱动几乎从不是先它 */
        int (*lock) (struct file *, int, struct file_lock *);

        /* sendpage是sendfile的另一半,它由内核调用来发送数据,一次一页到对应的文件,设备驱动实际上不实现sendpage */
        ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);

        /* 这个方法的目的是在进程空间找一个合适的位置来映射在底层设备上的内存段中,大部分驱动不实现 */
        unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);

        /* 该方法允许模块检查传递给fcntl(F_SETFL...)调用的标志 */
        int (*check_flags)(int);

        /* 应用程序使用fcntl来请求目录改变通知时,调用该方法,仅对文件系统有效,驱动程序不实现 */
        int (*flock) (struct file *, int, struct file_lock *);

        ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
        ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
        int (*setlease)(struct file *, long, struct file_lock **);
        long (*fallocate)(struct file *file, int mode, loff_t offset, loff_t len);
    };

五. struct file注释:
    struct file {
        /**
         * 1. 其中struct list_head是内核链表;
         * 2. RCU(Read-Copy Update)是Linux 2.6内核中新的锁机制;
         */
        union {
            struct list_head fu_list;
            struct rcu_head  fu_rcuhead;
        } f_u;
        /**
         * 在早些版本内核中没有此结构,而是直接将path的两个数据成员作为struct file的数据成员
         * 1. struct vfsmount *mnt的作用是指出该文件的已安装的文件系统;
         * 2. struct dentry *dentry是与文件相关的目录项对象;
         */
        struct path  f_path;
    #define f_dentry f_path.dentry
    #define f_vfsmnt f_path.mnt
        /* 包含着与文件相关的操作 */
        const struct file_operations *f_op;

        /**
         * Protects f_ep_links, f_flags, f_pos vs i_size in lseek SEEK_CUR.
         * Must not be taken from IRQ context.
         */
        spinlock_t  f_lock;
    #ifdef CONFIG_SMP
        int   f_sb_list_cpu;
    #endif
        /* 记录对文件对象的引用计数,也就是当前有多少个进程在使用该文件 */ 
        atomic_long_t  f_count;
        /**
         * 打开文件时指定的标志,对应系统调用open的int flags参数,
         * 驱动程序为了支持非阻塞型操作需要检查该标志 
         */
        unsigned int   f_flags;
        /* 打开文件的读写模式,对应系统调用的open的mod_t mode参数 */
        fmode_t   f_mode;
        /* 当前的文件指针位置,即文件的读写位置 */
        loff_t   f_pos;
        /* 该结构的作用是通过信号进行I/O时间通知的数据 */
        struct fown_struct f_owner;
        /* 保存进程的GID,UID等信息 */
        const struct cred *f_cred;
        /* 文件预读算法使用的主要数据结构 */
        struct file_ra_state f_ra;

        /* 记录文件的版本号,每次使用后都自动递增 */
        u64   f_version;
    #ifdef CONFIG_SECURITY
        /**
         * 如果在编译内核时配置了安全措施,那么struct file结构中就会有
         * void *f_security数据项,用来描述安全措施或者是记录与安全有关的信息
         */
        void   *f_security;
    #endif
        /* needed for tty driver, and maybe others */
        /**
         * 系统在调用驱动程序的open()前将这个指针置为NULL,驱动程序可以将这个字段用于任何目的,
         * 也可以用这个字段指向已分配的数据,但一定要在内核释放file结构之前release()中清楚它.
         */
        void   *private_data;

    #ifdef CONFIG_EPOLL
        /* Used by fs/eventpoll.c to link all the hooks to this file */
        /**
         * 被用在fs/eventpoll.c来链接所有钩到这个文件上,其中f_ep_links是文件的时间轮询等待者链表的头,
         * f_ep_lock是保护f_ep_links链表的自旋锁.
         */
        struct list_head f_ep_links;
        struct list_head f_tfile_llink;
    #endif /* #ifdef CONFIG_EPOLL */
        /* 指向文件地址空间的指针 */
        struct address_space *f_mapping;
    #ifdef CONFIG_DEBUG_WRITECOUNT
        unsigned long f_mnt_write_state;
    #endif
    };

六. struct inode注释:
    struct inode {
        /* 访问权限控制 */
        umode_t   i_mode;
        unsigned short  i_opflags;
        /* 使用者id */
        kuid_t   i_uid;
        /* 使用者id组 */
        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;
        /* 以字节为单位的文件大小 */
        loff_t   i_size;
        /* 最后访问时间 */
        struct timespec  i_atime;
        /* 最后修改时间 */
        struct timespec  i_mtime;
        /* 最后改变时间 */
        struct timespec  i_ctime;
        /* 自旋锁 */
        spinlock_t  i_lock; /* i_blocks, i_bytes, maybe i_size */
        /* 使用的字节数 */
        unsigned short          i_bytes;
        /* 以位为单位的块的大小 */
        unsigned int  i_blkbits;
        /* 文件的块数 */
        blkcnt_t  i_blocks;

    #ifdef __NEED_I_SIZE_ORDERED
        seqcount_t  i_size_seqcount;
    #endif

        /* Misc */
        /* 状态标志 */
        unsigned long  i_state;
        struct mutex  i_mutex;

        /* 首次修改时间 */
        unsigned long  dirtied_when; /* jiffies of first dirtying */

        /* 哈希表 */
        struct hlist_node i_hash;
        struct list_head i_wb_list; /* backing dev IO list */
        struct list_head i_lru;  /* inode LRU list */
        struct list_head i_sb_list;
        union {
            struct list_head i_dentry;
            struct rcu_head  i_rcu;
        };
        u64   i_version;
        /* 引用计数 */
        atomic_t  i_count;
        atomic_t  i_dio_count;
        atomic_t  i_writecount;
        /* 默认的索引节点操作 */
        const struct file_operations *i_fop; /* former ->i_op->default_file_ops */
        /* 文件锁链表 */
        struct file_lock *i_flock;
        /* 设备地址映射 */
        struct address_space i_data;
    #ifdef CONFIG_QUOTA
        /* 节点的磁盘限额 */
        struct dquot *i_dquot[MAXQUOTAS];
    #endif
        /* 块设备链表 */
        struct list_head i_devices;
        union {
            struct pipe_inode_info *i_pipe;
            struct block_device *i_bdev;
            struct cdev  *i_cdev;
        };

        /* 索引节点版本号 */
        __u32   i_generation;

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

    #ifdef CONFIG_IMA
        /* 读数据计数 */
        atomic_t i_readcount; /* struct files open RO */
    #endif
        /* 私有数据指针 */
        void *i_private; /* fs or device private pointer */
    };
原文地址:https://www.cnblogs.com/zengjfgit/p/4322021.html