Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1848777
  • 博文数量: 184
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 2388
  • 用 户 组: 普通用户
  • 注册时间: 2016-12-21 22:26
个人简介

90后空巢老码农

文章分类

全部博文(184)

文章存档

2021年(26)

2020年(56)

2019年(54)

2018年(47)

2017年(1)

我的朋友

分类: LINUX

2020-10-19 18:47:53

首先,我们需要明确以下,外设都是放在/dev/目录下的,存储其的文件系统是基于内存的,初始化具体文件系统的inode是通过init_special_inode这个函数来实现的:

点击(此处)折叠或打开

  1. void init_special_inode(struct inode *inode, umode_t mode, dev_t rdev)
  2. {
  3.     inode->i_mode = mode;
  4.     if (S_ISCHR(mode)) {
  5.         inode->i_fop = &def_chr_fops;
  6.         inode->i_rdev = rdev;
  7.     } else if (S_ISBLK(mode)) {
  8.         inode->i_fop = &def_blk_fops;
  9.         inode->i_rdev = rdev;
  10.     } else if (S_ISFIFO(mode))
  11.         inode->i_fop = &pipefifo_fops;
  12.     else if (S_ISSOCK(mode))
  13.         ;    /* leave it no_open_fops */
  14.     else
  15.         printk(KERN_DEBUG "init_special_inode: bogus i_mode (%o) for"
  16.                  " inode %s:%lu\n", mode, inode->i_sb->s_id,
  17.                  inode->i_ino);
  18. }

点击(此处)折叠或打开

  1. const struct file_operations def_chr_fops = {
  2.     .open = chrdev_open,
  3.     .llseek = noop_llseek,
  4. };
这样,当我们想要打开一个字符设备的时候,实际上调用的就是chrdev_open函数了,内核会先找到inode对应的设备号,然后根据之前介绍的cdev_map这个哈希表,找到对应的kobject, 根据kobject可以找到字符设备的描述cdev,同时,它会把这个cdev设置到inode对应的结构里面(下次open就不用再去走kobject->cdev这条线了),并且,会把inode放进字符设备列表里面,然后就是设置file_operations那一套了(这个才是写字符驱动的时候自己写的那部分)

点击(此处)折叠或打开

  1. /*
  2.  * Called every time a character special file is opened
  3.  */
  4. static int chrdev_open(struct inode *inode, struct file *filp)
  5. {
  6.     const struct file_operations *fops;
  7.     struct cdev *p;
  8.     struct cdev *new = NULL;
  9.     int ret = 0;

  10.     spin_lock(&cdev_lock);
  11.     p = inode->i_cdev;
  12.     if (!p) {
  13.         struct kobject *kobj;
  14.         int idx;
  15.         spin_unlock(&cdev_lock);
  16.         kobj = kobj_lookup(cdev_map, inode->i_rdev, &idx);
  17.         if (!kobj)
  18.             return -ENXIO;
  19.         new = container_of(kobj, struct cdev, kobj);
  20.         spin_lock(&cdev_lock);
  21.         /* Check i_cdev again in case somebody beat us to it while
  22.          we dropped the lock. */
  23.         p = inode->i_cdev;
  24.         if (!p) {
  25.             inode->i_cdev = p = new;
  26.             list_add(&inode->i_devices, &p->list);
  27.             new = NULL;
  28.         } else if (!cdev_get(p))
  29.             ret = -ENXIO;
  30.     } else if (!cdev_get(p))
  31.         ret = -ENXIO;
  32.     spin_unlock(&cdev_lock);
  33.     cdev_put(new);
  34.     if (ret)
  35.         return ret;

  36.     ret = -ENXIO;
  37.     fops = fops_get(p->ops);
  38.     if (!fops)
  39.         goto out_cdev_put;

  40.     replace_fops(filp, fops);
  41.     if (filp->f_op->open) {
  42.         ret = filp->f_op->open(inode, filp);
  43.         if (ret)
  44.             goto out_cdev_put;
  45.     }

  46.     return 0;

  47.  out_cdev_put:
  48.     cdev_put(p);
  49.     return ret;
  50. }

其中,inode里面关于这部分的结构代码如下:

点击(此处)折叠或打开

  1. struct inode {
  2.     umode_t            i_mode;
  3.     unsigned short        i_opflags;
  4.     kuid_t            i_uid;
  5.     kgid_t            i_gid;
  6.     unsigned int        i_flags;
  7. ...
  8.     dev_t            i_rdev;
  9.     loff_t            i_size;
  10.     struct timespec64    i_atime;
  11.     struct timespec64    i_mtime;
  12.     struct timespec64    i_ctime;
  13.     spinlock_t        i_lock;    /* i_blocks, i_bytes, maybe i_size */
  14. ...
  15.     struct list_head    i_devices;
  16.     union {
  17.         struct pipe_inode_info    *i_pipe;
  18.         struct block_device    *i_bdev;
  19.         struct cdev        *i_cdev;
  20.         char            *i_link;
  21.         unsigned        i_dir_seq;
  22.     };
  23. ...
  24.     void            *i_private; /* fs or device private pointer */
  25. } __randomize_layout;




阅读(1322) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~