Linux内核register_chrdev挂载驱动详解

  通过内核源码树编译得到的xxx.ko驱动下载到sd卡中,启动内核进入系统用insmod xxx.ko安装驱动,该命令会调用

module_init(chrdev_init)中指定的chrdev_init函数,在该函数里我们调用register_chrdev来进行注册,注册会申请以下三个结构体

char_device_struct,驱动程序描述符cdev,probe结构体来对应一个驱动程序

1  char_device_struct:

     一个驱动程序有一个设备号范围,在该设备号范围的设备文件都会使用该驱动程序,将对应该驱动程序的char_device_struct

     根据主设备号的hash值插入chrdevs数组,这是纵向插入,在其横向链表的插入过程中我们根据其设备号范围的大小将其小

     在前大在后进行插入,结构体中cdev指向驱动程序描述符cdev

2  驱动程序描述符cdev

    cdev中ops指向我们传入的file_operations结构体,

3  probe结构体 (用来根据设备号查找cdev)

    内核中有段内存被cdev_map指向又来存储probe结构体的指针,与char_device_struct的存储方式相同,

    probe中data指向cdev

  通过 /proc/devices目录以及lsmod命令可以查看注册情况。

注册完成后创建设备文件:

    mknod /dev/testchar c 250 0  只要改设备号在该驱动对应的设备号范围就会调用该驱动

下面分析mknod /dev/testchar c 250 0

  系统调用会调用vfs_mknod(nd.path.dentry->d_inode,dentry,mode,new_decode_dev(dev));第一个参数为目录dev的inode

  第二个参数为新建的testchar的目录项,该函数又会调用dev目录的inode的mknod方法找到该方法为ramfs_mknod

  得到设备文件的inode且inode->i_fop = &def_chr_fops; inode->i_rdev = rdev;这样我们就完成了设备文件的创建

下面open("/dev/testchar", O_RDWR)分析打开设备文件的过程:

  SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, int, mode)

  ————do_sys_open(AT_FDCWD, filename, flags, mode);

       ————struct file *f = do_filp_open(dfd, tmp, flags, mode, 0);

          ————do_last

              ————finish_open

                  ————nameidata_to_filp

                      ————__dentry_open

      ————fd_install

__dentry_open中我们将设备文件的节点的 i_fop赋给file结构体的 f_op 并执行其 open方法,我们创建设备文件时知道

设备文件的 inode->i_fop = &def_chr_fops,执行open即chrdev_open,该函数中我们根据inode->i_rdev即设备号在cdev_map

中查找对应的设备驱动程序描述符cdev并赋值给inode->i_cdev,将cdev中的ops赋给filp->f_op并执行其open方法

fd_install将文件描述符与file结构体绑定,此后IO文件操作将会调用驱动程序

使用新接口 register_chrdev_region/alloc_chrdev_region 注册分析:

操作   register_chrdev_region  cdev_init  cdev_add

新接口和老接口注册方式差不多

register_chrdev_region  注册 char_device_struct

cdev_init    初始化驱动程序描述符 cdev

cdev_add    向 cdev_map 注册 probe结构体

原文地址:https://www.cnblogs.com/genshu123/p/11834634.html