linux character device - a drive frame (b)

Character device driver framework

(Preface)

I write a simple front linux character device driver . Then simply look at the character device driver framework.

First, important data structure

In linux character device, there are three important data structures, namely: struct the file_operations , struct File and struct inode
below to explain in simple

1、struct file_operations

This structure is equivalent to a device driver, to achieve a correlation function operating device characters

/* 只介绍部分struct file_operations结构体的成员 */
struct file_operations {
    /* struct module 这个成员不是一个操作; 它是一个指向拥有这个结构体的模块指针。
     * 这个成员用来在它还被使用时阻止模块被卸载。一般初始化为 THIS_MODULE,
     */
    struct module *owner;
        
    /* llseek 函数用来改变文件中当前的读/写的位置,如果这个函数指针是NULL,内核中
     * 缺省的实现通过修改filp->f_pos进行移位
     */
    loff_t (*llseek) (struct file *, loff_t, int);

    /* read函数用来从设备中获取数据。如果这个函数指针是NULL,以 -EINVAL 失败返回给
     *  read 系统调用,一个非负返回值代表了成功读取的字节数。
     */
    ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);

    /* write函数用来发送数据给设备。如果这个函数指针是NULL,以 -EINVAL 失败返回给
     *  write 系统调用,一个非负返回值代表了成功读取的字节数。
     */
    ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);

    /* poll 函数是: poll, epoll 和 select 这三个系统调用的后端。这三个系统调用都用作查询对一个
     * 或者多个文件描述符的读或写是否会阻塞。poll函数应返回一个位掩码指示是否非阻塞的读或
     * 者写是可能的。并且给内核提供信息,用来使调用的的进程睡眠,直到读写操作变为可能。
     * 如果一个驱动的 poll 指针为 NULL, 设备假定为不阻塞地可读可写。
     */
    unsigned int (*poll) (struct file *, struct poll_table_struct *);

     /* ioctl 函数 为 ioctl() 系统调用提供了发出设备特定命令的方法
      * 如果一个驱动的 ioctl 指针为 NULL, 对于任何未事先定义的请
      * 求返回 -ENOTTY, 系统调用返回一个错误
      */
    int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);

     /* mmap 用来请求将设备内存映射到进程的地址空间, 
      * 如果这个指针是 NULL, mmap 系统调用返回 -ENODEV.
      */
    int (*mmap) (struct file *, struct vm_area_struct *);
     
     /* open成员是 open 系统调用的后端,通常是对设备文件进行的第一个操作
      * 如果这个指针是 NULL, 设备打开一直成功, 但是你的驱动不会得到通知.
      */
    int (*open) (struct inode *, struct file *);

     /* release成员是 close系统调用的后端,在文件结构被释放时引用这个操作。
      * 如同open,release成员也可以为NULL。
      */
    int (*release) (struct inode *, struct file *);

     /* fasync这个操作用来通知设备它的 FASYNC 标志的改变(异步通知)
      * 如果这个成员是 NULL, 驱动不支持异步通知。
      */
    int (*fasync) (int, struct file *, int);
};

2、struct file

This structure is described open a file, open a file each will have a struct file structure to manage

/* 只介绍部分struct file结构体的成员 */
struct file {

    /* 文件模式确定文件是可读的或者是可写的(或者都是),
     *  通过位 FMODE_READ 和FMODE_WRITE 描述
     */
    mode_t          f_mode;

    /*  文件当前的读写位置. 如果驱动需要知到文件中的当前位置,可以读这个值,但是不应该改变它。
     *  在fops 的 read 和 write 以最后的一个参数传入,来代替直接使用f_pos成员,在fops的llseek方法中
     *  通过改变f_pos 成员来改变,文件的读写位置
     */
    loff_t          f_pos;

    /*  文件的标志。例如 O_REONLY, O_NONBLOCK, 和 O_SYNC。驱动通过检查O_NONBLOCK标志
     *  来查看是否请求非阻塞操作,其他标志一般比较少用。
     */
    unsigned int        f_flags;

    /* 和文件关联的操作*/
    const struct file_operations    *f_op;

    /* 这个成员通常用来指向分配的数据,通常在fops->open 成员函数里面指定。
     * 如果使用了这个成员必须在fops->release 成员中释放。
     */
    void            *private_data;
};

3、struct inode

used to describe a struct inode file on disk. inode structure contains a wealth of information about the files, but only two members of this structure is useful codes for writing drivers

/* 只介绍部分struct inode结构体的成员 */
struct inode {
    /* 对于代表设备文件的节点, 这个成员包含实际的设备编号. */
    dev_t    i_rdev;
    union {
        struct pipe_inode_info  *i_pipe;
        /* 当节点指的是一个块设备文件时,代表块设备。*/
        struct block_device     *i_bdev;
        /* 当节点指的是一个字符设备文件时,代表字符设备。*/
        struct cdev             *i_cdev;
    };
}

Two, linux source code analysis frame

System call to the kernel driver calls as follows (in the open system call, for example, another similar system calls)
(entry function system call kernel calls.S in which this document /)
  SYS_OPEN
     do_sys_open
       FD = get_unused_fd (); // this process does not find a file descriptor used
       struct file * F = do_filp_open (DFD, tmp, the flags, MODE); // constructed and arranged struct file structure
         nameidata_to_filp (& Nd, the flags);
           __dentry_open (the ND-> dentry, Nd -> mnt, the flags, the filp, NULL);
             ! IF (Open && F-> the f_op) // Open a function pointer as a parameter __dentry_open fifth
               Open = F-> f_op-> Open; // Get fops the open member
             IF (open) {
               error = open (the inode, F); // call the function open the function
             }

Third, the frame of FIG.

< Obsessed with more than > the bloggers have a more detailed view of the frame, so a direct quote coming

Guess you like

Origin www.cnblogs.com/gulan-zmc/p/11519066.html