tty驱动详解

/dev/tty代表当前tty设备,在当前的终端中输入 echo hello” > /dev/tty ,都会直接显示在当前的终端中。/dev/ttyS*是串行终端设备。

/dev/pty*即伪终端,所谓伪终端是逻辑上的终端设备,多用于模拟终端程序。例如,我们在X Window下打开的终端,以及我们在Windows使用telnet  ssh等方式登录Linux主机,此时均在使用pty设备(准确的说应该pty从设备)

/dev/tty0代表当前虚拟控制台,而/dev/tty1等代表第一个虚拟控制台,例如当使用ALT+F2进行切换时,系统的虚拟控制台为/dev/tty2 ,当前的控制台则指向/dev/tty2

使用tty命令可以确定当前的终端或者控制台。

2.1.71之前,/dev/console根据不同系统的设定可以链接到/dev/tty0或者其他tty*上,在2.1.71版本之后则完全由内核控制。目前,只有在单用户模式下可以登录/dev/console(可以在单用户模式下输入tty命令进行确认)。

只有24102.6才叫ttySAC09200等的还是叫ttyS0 




在驱动起来的时候调用了uart_register_driver(&serial8250_reg);函数将参数serial8250_reg注册进了tty层。

int uart_register_driver(struct uart_driver *drv)  

{  

    struct tty_driver *normal = NULL;  

    int i, retval;  

  

    drv->state = kzalloc(sizeof(struct uart_state) * drv->nr, GFP_KERNEL); 

    normal  = alloc_tty_driver(drv->nr);  

    drv->tty_driver = normal;  

normal->driver_state    = drv;  

tty_set_operations(normal, &uart_ops);  

  

    for (i = 0; i < drv->nr; i++) {  

        struct uart_state *state = drv->state + i;  

        state->close_delay     = 500;    /* .5 seconds */  

        state->closing_wait    = 30000;  /* 30 seconds */  

        mutex_init(&state->mutex);  

  

        tty_port_init(&state->info.port);  

        init_waitqueue_head(&state->info.delta_msr_wait);  

        tasklet_init(&state->info.tlet, uart_tasklet_action,  

                 (unsigned long)state);  

    }  

    retval = tty_register_driver(normal);  

}  

uart_driver中很多数据结构其实就是tty_driver中的,将数据转换为tty_driver之后,注册tty_driver。然后初始化uart_driver->state的存储空间。

normal->driver_state    = drv; 这一句将参数的ops关系都赋给了serial_core层。也就是说在后面serial_core会根据uart_ops关系找到我们的8250.c中所对应的操作,而我们参数中的ops是在哪被赋值的呢?定位到了8250.c中的serial8250_ops结构体,初始化如下:

static struct uart_ops serial8250_pops = {  

    .tx_empty   = serial8250_tx_empty,  

    .set_mctrl  = serial8250_set_mctrl,  

    .get_mctrl  = serial8250_get_mctrl,  

    .stop_tx    = serial8250_stop_tx,  

    .start_tx   = serial8250_start_tx,  

    .stop_rx    = serial8250_stop_rx,  

    .enable_ms  = serial8250_enable_ms,  

    .break_ctl  = serial8250_break_ctl,  

    .set_termios    = serial8250_set_termios,  

    .pm     = serial8250_pm,  

    .request_port   = serial8250_request_port,  

    .config_port    = serial8250_config_port,  

};  
uart_add_one_port()函数中,从serial8250_init->serial8250_register_ports()->uart_add_

one_port()逐步调用过来的,这一步就将portuart_driver联系起来了。

tty_set_operations(normal, &uart_ops);  tty_driver的操作集统一设为了uart_ops.这样就使得从用户空间下来的操作可以找到正确的serial_core的操作函数,uart_ops是在serial_core.c中的:

static const struct tty_operations uart_ops = {  

    .open       = uart_open,   

    .write      = uart_write,  

    .put_char   = uart_put_char,  

    .flush_chars    = uart_flush_chars,  

    .write_room = uart_write_room,  

    .flush_buffer   = uart_flush_buffer,  

    .ioctl      = uart_ioctl,  

    .send_xchar = uart_send_xchar,  

    .set_termios    = uart_set_termios,  

    .set_ldisc  = uart_set_ldisc,  

    .start      = uart_start,  

    .break_ctl  = uart_break_ctl,  

    .wait_until_sent= uart_wait_until_sent,  

    .tiocmget   = uart_tiocmget,  

    .tiocmset   = uart_tiocmset,  

};  

这样就保证了调用关系的通畅。

自顶向下

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值