在看tty_io.c文件中的tty_open()函数时,发现有这么一行代码:
if (tty->ops->open)
retval = tty->ops->open(tty, filp);
else
return -ENODEV;
这说明,在打开tty设备时,tty内核层的open()函数调用了tty驱动层的open()函数。那么,线路规程层的open()函数又是在哪里调用的呢?
其实线路规程层的open()函数也是在tty内核层的open()函数中被调用,而且还是在tty驱动层open()函数调用之前被调用。
tty内核层open()函数中调用了函数tty_init_dev,代码如下:
tty = tty_init_dev(driver, index, 0);
tty_init_dev()是个很重要的函数,做了很多事情。
整理一下,调用路径如下:
用户层open -> tty_open -> tty_init_cdev -> tty_ldisc_setup -> tty_ldisc_open -> 线路规程层open函数。
综上所述,tty内核层的open函数调用了tty线路规程层的open函数和tty驱动层的open函数。
下面我们列举一个tty线路规程层的open函数:
STATIC int32 ps_tty_open(struct tty_struct *tty)
{
int32 err = 0;
struct ps_core_s *ps_core_d == NULL;
ps_get_core_reference(&ps_core_d);
if (unlikely(NULL == ps_core_d))
{
return -EINVAL;
}
ps_core_d->tty = tty;
tty->disc_data = ps_core_d;
/* don't do an wakeup for now */
clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
/* mem already allocated */
tty->receive_room = 65536;
/* Flush any pending characters in the driver and discipline. */
tty_ldisc_flush(tty);
tty_driver_flush_buffer(tty);
/* signal to octty that installation of N_HW_BFG ldisc is complete */
ps_tty_complete(ps_core_d->pm_data);
ps_change_baud_rate_complete(ps_core_d->pm_data);
return err;
}
STATIC void ps_tty_close(struct tty_struct *tty)
{
struct ps_core_s *ps_core_d = NULL;
if ((NULL == tty)||(NULL == tty->disc_data))
{
return;
}
ps_core_d = tty->disc_data;
/* Flush any pending characters in the driver and discipline. */
tty_ldisc_flush(tty);
tty_driver_flush_buffer(tty);
ps_core_d->tty = NULL;
/* signal to complate that N_HW_BFG ldisc is un-installed */
ps_tty_complete(ps_core_d->pm_data);
ps_kfree_skb(ps_core_d, TX_HIGH_QUEUE);
ps_kfree_skb(ps_core_d, TX_LOW_QUEUE);
}
PS_PRINT_FUNCTION_NAME; if ((NULL == tty)||(NULL == tty->disc_data)) { PS_PRINT_ERR("tty or tty->disc_data is NULL"); return; } ps_core_d = tty->disc_data;
/* Flush any pending characters in the driver and discipline. */ tty_ldisc_flush(tty); tty_driver_flush_buffer(tty); ps_core_d->tty = NULL;
/* signal to complate that N_HW_BFG ldisc is un-installed */ ps_tty_complete(ps_core_d->pm_data);
ps_kfree_skb(ps_core_d, TX_HIGH_QUEUE); ps_kfree_skb(ps_core_d, TX_LOW_QUEUE);
PS_PRINT_INFO("%s: have done!!!", __func__); }