接上一篇,我们已经注册了一个tty设备驱动并且在/dev生成相应的设备节点,我们对这个节点的操作open,read,write等对应的就是
static const struct file_operations tty_fops = {
.llseek = no_llseek,
.read = tty_read,
.write = tty_write,
.poll = tty_poll,
.unlocked_ioctl = tty_ioctl,
.compat_ioctl = tty_compat_ioctl,
.open = tty_open,
.release = tty_release,
.fasync = tty_fasync,
};
下面我们来一个个的分析:
tty_open
static int tty_open(struct inode *inode, struct file *filp)
{
dev_t device = inode->i_rdev;
noctty = filp->f_flags & O_NOCTTY;
/* This is protected by the tty_mutex */
tty = tty_open_current_tty(device, filp);
if (IS_ERR(tty)) {
goto err_unlock;
} else if (!tty) {
driver = tty_lookup_driver(device, filp, &noctty, &index);
/* check whether we're reopening an existing tty */
tty = tty_driver_lookup_tty(driver, inode, index);
}
if (tty) {
retval = tty_reopen(tty);
} else /* Returns with the tty_lock held for now */
tty = tty_init_dev(driver, index);
if (tty->ops->open)
retval = tty->ops->open(tty, filp);
else
retval = -ENODEV;
filp->f_flags = saved_flags;
return 0;
}
删除很多不太重要的代码,剩下主干代码。这里最重要的功能是tty->ops->open(tty, filp); 调用tty的ops。我们要想办法知道这个ops的实现。同时tty = tty_init_dev(driver, index);这一句也是十分的重要,这里面对tty的初始化,启用线路规划功能,里面包含的信息十分的多。
static struct tty_struct *tty_open_current_tty(dev_t device, struct file *filp)
{
struct tty_struct *tty;
if (device != MKDEV(TTYAUX_MAJOR, 0))
return NULL;
tty = get_current_tty();
if (!tty)