tty_ldisc线路规程简述

一: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;
                 }
            }
        }
        ...
    }

猜你喜欢

转载自blog.csdn.net/linuxarmbiggod/article/details/78879944
tty