一:tty线路规程概念:
tty : 作为 tty 系统通讯转换层,负责格式化 底层 uart_driver 与 核心层 tty_driver 之间的
通讯协议的转换
二:线路规程启动位置:
在Linux 初始化的过程中,在调用 console_init 之前是没有任何输出的,直到 控制台console 串口
初始化之后才会有输出
/kernel/init/main.c
start_kernel{
...
console_init();
...
}
/kernel/driver/tty/tty_io.c
void __init console_init(void)
{
initcall_t *call;
//创建默认的 tty 线路规程
tty_ldisc_begin();
//创建 控制台设备,用来打印内核信息
call = __con_initcall_start;
while (call < __con_initcall_end) {
(*call)();
call++;
}
}
三:线路规程创建过程:
/kernel/include/uapi/linux/tty.h
//线路规程 协议标号
#define NR_LDISCS 30
#define N_TTY 0
#define N_SLIP 1
#define N_MOUSE 2
....
/kernel/drivers/tty/n_tty.c
//线路规程函数操作集
struct tty_ldisc_ops tty_ldisc_N_TTY = {
.magic = TTY_LDISC_MAGIC,
.name = "n_tty",
.open = n_tty_open,
.close = n_tty_close,
.flush_buffer = n_tty_flush_buffer,
.chars_in_buffer = n_tty_chars_in_buffer,
.read = n_tty_read,
.write = n_tty_write,
.ioctl = n_tty_ioctl,
.set_termios = n_tty_set_termios,
.poll = n_tty_poll,
.receive_buf = n_tty_receive_buf,
.write_wakeup = n_tty_write_wakeup,
.fasync = n_tty_fasync,
.receive_buf2 = n_tty_receive_buf2,
};
/kernel/tty/tty_ldisc.c
//该数组有内核定义 存放协议标号以及各个线路规程操作集
1 static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS];
2 void tty_ldisc_begin(void)
{
//注册线路规程,这里只是注册了一个线路规程,tty并没有调用该线路规程,
(void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY);
}
//根据数组下标 N_TTY(代表协议) 存放对应的线路规程的操作集 tty_ldisc_N_TTY
3 int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc)
{
unsigned long flags;
int ret = 0;
//判断编号是否符合
if (disc < N_TTY || disc >= NR_LDISCS)
return -EINVAL;
raw_spin_lock_irqsave(&tty_ldiscs_lock, flags);
tty_ldiscs[disc] = new_ldisc;
new_ldisc->num = disc;
new_ldisc->refcount = 0;
raw_spin_unlock_irqrestore(&tty_ldiscs_lock, flags);
return ret;
}
EXPORT_SYMBOL(tty_register_ldisc);
四 tty线路规程 小结:
start_kernel{
...
console_init()
{
tty_ldisc_begin()
{
tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY);
{
unsigned long flags;
int ret = 0;
//判断编号是否符合
if (disc < N_TTY || disc >= NR_LDISCS)
return -EINVAL;
raw_spin_lock_irqsave(&tty_ldiscs_lock, flags);
tty_ldiscs[disc] = new_ldisc;
new_ldisc->num = disc;
new_ldisc->refcount = 0;
raw_spin_unlock_irqrestore(&tty_ldiscs_lock, flags);
return ret;
}
}
}
...
}