首先,我们需要明确以下,外设都是放在/dev/目录下的,存储其的文件系统是基于内存的,初始化具体文件系统的inode是通过init_special_inode这个函数来实现的:
-
void init_special_inode(struct inode *inode, umode_t mode, dev_t rdev)
-
{
-
inode->i_mode = mode;
-
if (S_ISCHR(mode)) {
-
inode->i_fop = &def_chr_fops;
-
inode->i_rdev = rdev;
-
} else if (S_ISBLK(mode)) {
-
inode->i_fop = &def_blk_fops;
-
inode->i_rdev = rdev;
-
} else if (S_ISFIFO(mode))
-
inode->i_fop = &pipefifo_fops;
-
else if (S_ISSOCK(mode))
-
; /* leave it no_open_fops */
-
else
-
printk(KERN_DEBUG "init_special_inode: bogus i_mode (%o) for"
-
" inode %s:%lu\n", mode, inode->i_sb->s_id,
-
inode->i_ino);
-
}
-
const struct file_operations def_chr_fops = {
-
.open = chrdev_open,
-
.llseek = noop_llseek,
-
};
这样,当我们想要打开一个字符设备的时候,实际上调用的就是chrdev_open函数了,内核会先找到inode对应的设备号,然后根据之前介绍的cdev_map这个哈希表,找到对应的kobject, 根据kobject可以找到字符设备的描述cdev,同时,它会把这个cdev设置到inode对应的结构里面(下次open就不用再去走kobject->cdev这条线了),并且,会把inode放进字符设备列表里面,然后就是设置file_operations那一套了(这个才是写字符驱动的时候自己写的那部分)
-
/*
-
* Called every time a character special file is opened
-
*/
-
static int chrdev_open(struct inode *inode, struct file *filp)
-
{
-
const struct file_operations *fops;
-
struct cdev *p;
-
struct cdev *new = NULL;
-
int ret = 0;
-
-
spin_lock(&cdev_lock);
-
p = inode->i_cdev;
-
if (!p) {
-
struct kobject *kobj;
-
int idx;
-
spin_unlock(&cdev_lock);
-
kobj = kobj_lookup(cdev_map, inode->i_rdev, &idx);
-
if (!kobj)
-
return -ENXIO;
-
new = container_of(kobj, struct cdev, kobj);
-
spin_lock(&cdev_lock);
-
/* Check i_cdev again in case somebody beat us to it while
-
we dropped the lock. */
-
p = inode->i_cdev;
-
if (!p) {
-
inode->i_cdev = p = new;
-
list_add(&inode->i_devices, &p->list);
-
new = NULL;
-
} else if (!cdev_get(p))
-
ret = -ENXIO;
-
} else if (!cdev_get(p))
-
ret = -ENXIO;
-
spin_unlock(&cdev_lock);
-
cdev_put(new);
-
if (ret)
-
return ret;
-
-
ret = -ENXIO;
-
fops = fops_get(p->ops);
-
if (!fops)
-
goto out_cdev_put;
-
-
replace_fops(filp, fops);
-
if (filp->f_op->open) {
-
ret = filp->f_op->open(inode, filp);
-
if (ret)
-
goto out_cdev_put;
-
}
-
-
return 0;
-
-
out_cdev_put:
-
cdev_put(p);
-
return ret;
-
}
其中,inode里面关于这部分的结构代码如下:
-
struct inode {
-
umode_t i_mode;
-
unsigned short i_opflags;
-
kuid_t i_uid;
-
kgid_t i_gid;
-
unsigned int i_flags;
-
...
-
dev_t i_rdev;
-
loff_t i_size;
-
struct timespec64 i_atime;
-
struct timespec64 i_mtime;
-
struct timespec64 i_ctime;
-
spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */
-
...
-
struct list_head i_devices;
-
union {
-
struct pipe_inode_info *i_pipe;
-
struct block_device *i_bdev;
-
struct cdev *i_cdev;
-
char *i_link;
-
unsigned i_dir_seq;
-
};
-
...
-
void *i_private; /* fs or device private pointer */
-
} __randomize_layout;
阅读(1397) | 评论(0) | 转发(0) |