Linux驱动程序架构#

int open(const char *pathname, int flags, mode_t mode);

/* On success, open(), return the new file
descriptor (a nonnegative integer).  On error, -1 is returned and errno is set to indicate the error. */

在Linux应用程序中,使用open()函数成功打开一个“文件”后,将会返回一个文件描述符(相当于指针):一个file结构体变量如下所示:

/include/linux/fs.h

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, f_flags.
     * Must not be taken from IRQ context.
     */
    spinlock_t      f_lock;
    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 hlist_head   *f_ep;
#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 */

struct file_handle {
    __u32 handle_bytes;
    int handle_type;
    /* file identifier */
    unsigned char f_handle[];
};

同时open()函数的形参 int flags, mode_t mode 将会被赋值给file结构体的f_flags,f_mode变量。

另一方面,在内核启动时(或者加载驱动时),驱动程序会根据主次设备号,将自己注册到内核,然后内核根据设备号就能找到该驱动程序了。

同时被打开的这个“文件”是具有主次设备号的,内核根据主设备号找到相应驱动的file_operations结构体(包含read(),write()等操作函数),并将其赋值给file结构的f_op成员。

所以,应用程序拿到了open()函数返回的file结构,就可以对相应的文件(驱动设备)进行访问了。