專注電子技術(shù)學(xué)習(xí)與研究
當(dāng)前位置:單片機(jī)教程網(wǎng) >> MCU設(shè)計(jì)實(shí)例 >> 瀏覽文章

Linux-2.6.38驅(qū)動(dòng)的幾個(gè)結(jié)構(gòu)體關(guān)系總結(jié)

作者:公平   來(lái)源:本站原創(chuàng)   點(diǎn)擊數(shù):  更新時(shí)間:2014年03月14日   【字體:

Linux驅(qū)動(dòng)程序剛接觸,雖然不是很清楚,但是總歸是慢慢學(xué)習(xí)的過(guò)程。我的環(huán)境是Fedora14虛擬機(jī)。內(nèi)核版本是2.6.38.1,其中的實(shí)現(xiàn)過(guò)程存在很多的問(wèn)題,主要是因?yàn)楹芏嗟膬?nèi)核函數(shù)發(fā)生了較大的差別.其中最大的可能是ioctl以及互信息量的實(shí)現(xiàn)。這兩個(gè)的問(wèn)題也使得我們?cè)隍?qū)動(dòng)設(shè)計(jì)過(guò)程中出現(xiàn)很多的疑惑和問(wèn)題。
 
接上一部分,繼續(xù)總結(jié):
主要包括幾個(gè)重要的結(jié)構(gòu)體、并發(fā)控制、以及ioctl的實(shí)現(xiàn)。在驅(qū)動(dòng)的設(shè)計(jì)過(guò)程主要涉及3個(gè)重要的結(jié)構(gòu)體。struct file_operations,struct inode,struct file.
struct file_operations主要是涉及一些文件操作的函數(shù),其本質(zhì)上就是一個(gè)函數(shù)指針的集合,包含了文件操作的各種函數(shù)聲明,可能與應(yīng)用程序設(shè)計(jì)中的相應(yīng)函數(shù)只在參數(shù)上存在一定的差別。但是在2.6.36版本以后,其中的內(nèi)容發(fā)生了較大的變化,主要設(shè)計(jì)了ioctl的相關(guān)操作。

    struct file_operations {
        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);
        int (*readdir) (struct file *, void *, filldir_t);
        unsigned int (*poll) (struct file *, struct poll_table_struct *);
        /*新添加的函數(shù),同時(shí)去掉了ioctl的函數(shù),同時(shí)返回值也發(fā)生了變化*/
        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 *);
        int (*fsync) (struct file *, int datasync);
        int (*aio_fsync) (struct kiocb *, int datasync);
        int (*fasync) (int, struct file *, int);
        int (*lock) (struct file *, int, struct file_lock *);
        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);
        int (*check_flags)(int);
        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);
    };

long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
是最近添加進(jìn)來(lái)的函數(shù),為了實(shí)現(xiàn)原來(lái)的ioctl函數(shù),同時(shí)參數(shù)以及返回值都發(fā)生了較大的變化,這也是為什么在2.6.36版本以后的內(nèi)核中使用ioctl函數(shù)會(huì)報(bào)錯(cuò)的原因。unlocked_ioctl函數(shù)通常用來(lái)實(shí)現(xiàn)原來(lái)的ioctl函數(shù),而compat_ioctl函數(shù)則用來(lái)實(shí)現(xiàn)一些兼容版本的ioctl問(wèn)題。返回值由原來(lái)的int變?yōu)閘ong型,也是需要注意的。在ioctl中,第一個(gè)參數(shù)是struct inode,2.6.36以后的版本將不能直接訪問(wèn)到inode參數(shù),只能間接的訪問(wèn),具體的訪問(wèn)方法后面在總結(jié)。
在驅(qū)動(dòng)實(shí)現(xiàn)過(guò)程中主要包括對(duì)各個(gè)需要實(shí)現(xiàn)函數(shù)的賦值,但是open函數(shù)不能賦值與否,都會(huì)默認(rèn)打開(kāi),如果不賦值,則默認(rèn)該設(shè)備一直打開(kāi)。其他的函數(shù)不賦值,即表示不實(shí)現(xiàn)該方法。常用的復(fù)制方法如下:

    /*添加該模塊的基本文件操作支持*/
    static const struct file_operations mem_fops =
    {
            /*結(jié)尾不是分號(hào),注意其中的差別*/
            .owner = THIS_MODULE,
            .llseek = mem_llseek,
            .read = mem_read,
            .write = mem_write,
            .open = mem_open,
            .release = mem_release,
            /*添加新的操作支持*/
            .unlocked_ioctl = mem_ioctl,
    };

需要注意的是后面不再是分號(hào),而是逗號(hào)。其中的mem_read、mem_write等是函數(shù)的具體實(shí)現(xiàn)過(guò)程。.owner表示該結(jié)構(gòu)體屬于那個(gè),當(dāng)然就是THIS_MODULE,表示這個(gè)模塊。
 
struct inode表示的是一個(gè)文件的索引,該結(jié)構(gòu)是每一個(gè)具體的物理文件(保存在存儲(chǔ)器中的實(shí)體文件)的索引,一個(gè)文件對(duì)應(yīng)一個(gè)唯一的struct inode,其中表明了文件的大小,文件的類型,文件的時(shí)間等參數(shù),結(jié)構(gòu)體中每一個(gè)參數(shù)都能表示某一個(gè)文件的特性,通過(guò)inode就能表示文件的所有信息。
 

    struct inode {
        /* RCU path lookup touches following: */
        umode_t            i_mode;
        /*使用者的id*/
        uid_t            i_uid;
        /*使用者的組的id*/       
        gid_t            i_gid;

        const struct inode_operations    *i_op;
        struct super_block    *i_sb;

        spinlock_t        i_lock;    /* i_blocks, i_bytes, maybe i_size */
        unsigned int        i_flags;
        struct mutex        i_mutex;
        /*狀態(tài)標(biāo)志*/
        unsigned long        i_state;
        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;
        };

        unsigned long        i_ino;
      
        /*引用次數(shù),當(dāng)這個(gè)數(shù)為0時(shí),release函數(shù)才能完成*/
        atomic_t        i_count;

        unsigned int        i_nlink;
        /*設(shè)備文件的設(shè)備號(hào)*/
        dev_t            i_rdev;

        unsigned int        i_blkbits;
        u64            i_version;
        /*文件偏移量*/
        loff_t            i_size;

    #ifdef __NEED_I_SIZE_ORDERED
        seqcount_t        i_size_seqcount;
    #endif
        /*文件的時(shí)間參數(shù),包括三種時(shí)間*/
        struct timespec        i_atime;
        struct timespec        i_mtime;
        struct timespec        i_ctime;
        blkcnt_t        i_blocks;
        unsigned short i_bytes;
        struct rw_semaphore    i_alloc_sem;
        const struct file_operations    *i_fop;    /* former ->i_op->default_file_ops */
        struct file_lock    *i_flock;
      
        /*文件的備份地址空間*/
        struct address_space    *i_mapping;
        /*設(shè)備地址空間*/
        struct address_space    i_data;

    #ifdef CONFIG_QUOTA
        struct dquot        *i_dquot[MAXQUOTAS];
    #endif
        struct list_head    i_devices;
      
        /*說(shuō)明了三種不同的驅(qū)動(dòng)類型*/
        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
        /* protected by i_lock */
        unsigned int        i_readcount; /* struct files open RO */
    #endif
       /*寫(xiě)者使用次數(shù)*/
        atomic_t        i_writecount;
    #ifdef CONFIG_SECURITY
        void            *i_security;
    #endif
    #ifdef CONFIG_FS_POSIX_ACL
        struct posix_acl    *i_acl;
        struct posix_acl    *i_default_acl;
    #endif
        void            *i_private; /* fs or device private pointer */
    };

驅(qū)動(dòng)程序設(shè)計(jì)過(guò)程中通常采用i_rdev判斷設(shè)備文件的設(shè)備號(hào)。
 
struct file是指文件對(duì)象,表示進(jìn)程中打開(kāi)的文件,一個(gè)物理文件只有一個(gè)inode,但是可以被打開(kāi)很多次,因此可以存在很多struct file結(jié)構(gòu)體。

    struct file {
        /*
         * fu_list becomes invalid after file_free is called and queued via
         * fu_rcuhead for RCU freeing
         */
        union {
            struct list_head    fu_list;
            struct rcu_head     fu_rcuhead;
        } f_u;
      
        /*文件的路徑*/
        struct path        f_path;
    #define f_dentry    f_path.dentry
    #define f_vfsmnt    f_path.mnt
        /*該文件支持的操作集合*/
        const struct file_operations    *f_op;
        spinlock_t        f_lock; /* f_ep_links, f_flags, no IRQ */
    #ifdef CONFIG_SMP
        int            f_sb_list_cpu;
    #endif
        /*文件對(duì)象的使用次數(shù)*/
        atomic_long_t        f_count;

        unsigned int         f_flags;
        fmode_t            f_mode;
        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 */
        /*通常用來(lái)指向具體的數(shù)據(jù)或者設(shè)備文件,實(shí)現(xiàn)操作*/
        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;
    #endif /* #ifdef CONFIG_EPOLL */
        struct address_space    *f_mapping;
    #ifdef CONFIG_DEBUG_WRITECOUNT
        unsigned long f_mnt_write_state;
    #endif
    };

     訪問(wèn)inode主要是通過(guò)這兩個(gè)機(jī)構(gòu)體之間的管理型。
    struct path {
     struct vfsmount *mnt;
     struct dentry *dentry;
    };
    struct dentry {
        /* RCU lookup touched fields */
        unsigned int d_flags;        /* protected by d_lock */
        seqcount_t d_seq;        /* per dentry seqlock */
        struct hlist_bl_node d_hash;    /* lookup hash list */
        struct dentry *d_parent;    /* parent directory */
        struct qstr d_name;
        struct inode *d_inode;        /* Where the name belongs to - NULL is
                         * negative */
        unsigned char d_iname[DNAME_INLINE_LEN];    /* small names */

        /* Ref lookup also touches following */
        unsigned int d_count;        /* protected by d_lock */
        spinlock_t d_lock;        /* per dentry lock */
        const struct dentry_operations *d_op;
        struct super_block *d_sb;    /* The root of the dentry tree */
        unsigned long d_time;        /* used by d_revalidate */
        void *d_fsdata;            /* fs-specific data */

        struct list_head d_lru;        /* LRU list */
        /*
         * d_child and d_rcu can share memory
         */
        union {
            struct list_head d_child;    /* child of parent list */
             struct rcu_head d_rcu;
        } d_u;
        struct list_head d_subdirs;    /* our children */
        struct list_head d_alias;    /* inode alias list */
    };

其中的可以通過(guò)struct file間接的訪問(wèn)物理文件的struct inode,具體的實(shí)現(xiàn)是filp->f_path.entry->d_inode,這個(gè)過(guò)程也就實(shí)現(xiàn)了將inode和file結(jié)構(gòu)體之間的聯(lián)系。
上面的幾個(gè)主要的結(jié)構(gòu)體是驅(qū)動(dòng)實(shí)現(xiàn)過(guò)程中最重要的幾個(gè)。具體的意義還要聯(lián)系起來(lái)分析。

關(guān)閉窗口

相關(guān)文章