/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命令进行确认)。
只有2410的2.6才叫ttySAC0,9200等的还是叫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()逐步调用过来的,这一步就将port和uart_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,
};
这样就保证了调用关系的通畅。
2 自顶向下