精华内容
下载资源
问答
  • linux tty
    2021-05-14 15:36:18

    Linux TTY framework(4)_TTY driver

    作者:wowo 发布于:2016-10-25 22:40

    分类:TTY子系统

    1. 前言

    本文将从驱动工程师的角度去看TTY framework:它怎么抽象、管理各个TTY设备?它提供了哪些编程接口以方便TTY driver的开发?怎么利用这些接口编写一个TTY driver?等等。

    注1:话说介绍各个framework的时候,我一直比较喜欢用provider、consumer等概念,因为非常生动、易懂。不过在TTY framework的官方俗语中,压根没有provider、consumer等概念,为了不混淆试听,就算了吧。

    注2:TTY framework在Linux kernel中算得上一个比较繁琐、庞杂的framework了,再加上现在很少有人会直接去写一个TTY driver,因此本文只是介绍一些概念性的东西,以加深对TTY及其driver的理解,为后续学习serial framework打基础。一些细节的东西,大家可参考callme_friend同学写的"TTY驱动分析[2]”,特别是其中的一些图示,很清晰!

    注3:本文所使用的kernel版本为“X Project”初始的“Linux 4.6-rc5”版本。

    2. 关键数据结构

    注4:阅读本章内容时可对照callme_friend画的的TTY个数据结构的关系图[3]以加深理解。

    2.1 TTY device

    Linux TTY framework的核心功能,就是管理TTY设备,以方便应用程序使用。于是,问题来了,Linux kernel是怎么抽象TTY设备的呢?答案很尴尬,kernel并不认为TTY device是一个设备,这很好理解:

    比如,我们熟悉的串口终端,串口控制器(serial controller)是一个实实在在的硬件设备,一个控制器可以支持多个串口(serial port),软件在串口上收发数据,就相当于在驱动“串口终端”。此处的TTY device,就是从串口控制器中抽象出来的一个数据通道;

    再比如,我们常用的网络终端,只有以太网控制器(或者WLAN控制器)是实实在在的设备,sshd等服务进程,会基于网络socket,虚拟出来一个数据通道,软件在这个通道上收发数据,就相当于在驱动“网络终端”。

    因此,从kernel的角度看,TTY device就是指那些“虚拟的数据通道”。

    另外,由于TTY driver在linux kernel中出现的远比设备模型早,所以在TTY framework中,没有特殊的数据结构用于表示TTY设备。当然,为了方便,kernel从设备模型和字符设备两个角度对它进行了抽象:

    1)设备模型的角度

    为每个“数据通道”注册了一个stuct device,以便可以在sysfs中体现出来,例如:

    /sys/class/tty/tty

    /sys/class/tty/console

    /sys/class/tty/ttyS0

    2)字符设备的角度

    为每个“数据通道”注册一个struct cdev,以便在用户空间可以访问,例如:

    /dev/tty

    /dev/console

    /dev/ttyS0

    2.2 TTY driver

    从当前设备模型的角度看,TTY framework有点奇怪,它淡化了device的概念(参考2.1的介绍),却着重突出driver。由struct tty_driver所代表的TTY driver,几乎大包大揽了TTY device有关的所有内容,如下:

    struct tty_driver {

    int     magic;          /* magic number for this structure */

    struct kref kref;       /* Reference management */

    struct cdev **cdevs;

    struct module   *owner;

    const char      *driver_name;

    const char      *name;

    int     name_base;      /* offset of printed name */

    int     major;          /* major device number */

    int     minor_start;    /* start of minor device number */

    unsigned int    num;    /* number of devices allocated */

    short   type;           /* type of tty driver */

    short   subtype;        /* subtype of tty driver */

    struct ktermios init_termios; /* Initial termios */

    unsigned long   flags;          /* tty driver flags */

    struct proc_dir_entry *proc_entry; /* /proc fs entry */

    struct tty_driver *other; /* only used for the PTY driver */

    /*

    * Pointer to the tty data structures

    */

    struct tty_struct **ttys;

    struct tty_port **ports;

    struct ktermios **termios;

    void *driver_state;

    /*

    * Driver methods

    */

    const struct tty_operations *ops;

    struct list_head tty_drivers;

    }

    原则上来说,在编写TTY driver的时候,我们只需要定义一个struct tty_driver变量,并根据实际情况正确填充其中的字段后,注册到TTY core中,即可完成驱动的设计。当然,我们不需要关心struct tty_driver中的所有字段,下面我们捡一些重点的字段一一说明。

    1)需要TTY driver关心的字段

    driver_name,该TTY driver的名称,在软件内部使用;

    name,该TTY driver所驱动的TTY devices的名称,会体现到sysfs以及/dev/等文件系统下;

    major、minor_start,该TTY driver所驱动的TTY devices的在字符设备中的主次设备号。因为一个tty driver可以支持多个tty device,因此次设备号只指定了一个start number;

    num,该driver所驱动的tty device的个数,可以在tty driver注册的时候指定,也可以让TTY core自行维护,具体由TTY_DRIVER_DYNAMIC_DEV flag决定(可参考“”中的介绍);

    type、subtype,TTY driver的类型,具体可参考“include/linux/tty_driver.h”中的定义;

    init_termios,初始的termios,可参考2.5小节的介绍;

    flags,可参考2.6小节的介绍;

    ops,tty driver的操作函数集,可参考2.7小节的介绍;

    driver_state,可存放tty driver的私有数据。

    2)内部使用的字段

    ttys,一个struct tty_struct类型的指针数组,可参考2.3小节的介绍;

    ports,一个struct tty_port类型的指针数组,可参考2.4小节的介绍;

    termios,一个struct ktermios类型的指针数组,可参考2.5小节的介绍。

    2.3 TTY struct(struct tty_struct)

    TTY struct是TTY设备在TTY core中的内部表示。

    从TTY driver的角度看,它和文件句柄的功能类似,用于指代某个TTY设备。

    从TTY core的角度看,它是一个比较复杂的数据结构,保存了TTY设备生命周期中的很多中间变量,如:

    dev,该设备的struct device指针;

    driver,该设备的struct tty_driver指针;

    ops,该设备的tty操作函数集指针;

    index,该设备的编号(如tty0、tty1中的0、1);

    一些用于同步操作的mutex锁、spinlock锁、读写信号量等;

    一些等待队列;

    write buffer有关的信息;

    port,该设备对应的struct tty_port(可参考2.4小节的介绍)

    等等。

    由于编写TTY driver的时候不需要特别关心struct tty_struct的内部细节,这里不再详细介绍。

    2.4 TTY port(struct tty_port)

    在TTY framework中TTY port是一个比较难理解的概念,因为它和TTY struct类似,也是TTY device的一种抽象。那么,既然有了TTY struct,为什么还需要TTY port呢?先看一下kernel代码注释的解释:

    /* include/linux/tty.h */

    /*

    * Port level information. Each device keeps its own port level information

    * so provide a common structure for those ports wanting to use common support

    * routines.

    *

    * The tty port has a different lifetime to the tty so must be kept apart.

    * In addition be careful as tty -> port mappings are valid for the life

    * of the tty object but in many cases port -> tty mappings are valid only

    * until a hangup so don't use the wrong path.

    */

    我的理解是:

    TTY struct是TTY设备的“动态抽象”,保存了TTY设备访问过程中的一些临时信息,这些信息是有生命周期的:从打开TTY设备开始,到关闭TTY设备结束;

    TTY port是TTY设备固有属性的“静态抽象”,保存了该设备的一些固定不变的属性值,例如是否是一个控制台设备(console)、打开关闭时是否需要一些delay操作、等等;

    另外(这一点很重要),TTY core负责的是逻辑上的抽象,并不关心这些固有属性。因此从层次上看,这些属性完全可以由具体的TTY driver自行维护;

    不过,由于不同TTY设备的属性有很多共性,如果每个TTY driver都维护一个私有的数据结构,将带来代码的冗余。所以TTY framework就将这些共同的属性抽象出来,保存在struct tty_port数据结构中,同时提供一些通用的操作接口,供具体的TTY driver使用;

    因此,总结来说:TTY struct是TTY core的一个数据结构,由TTY core提供并使用,必要的时候可以借给具体的TTY driver使用;TTY port是TTY driver的一个数据结构,由TTY core提供,由具体的TTY driver使用,TTY core完全不关心。

    2.5 termios(struct ktermios)

    说实话,在Unix/Linux的世界中,终端(terminal)编程是一个非常繁琐的事情,为了改善这种状态,特意制订了符合POSIX规范的应用程序编程接口,称作POSIX terminal interface[3]。POSIX terminal interface操作的对象,就是名称为termios的数据结构(在用户空间为struct termios,内核空间为struct ktermios)。以kernel中的struct ktermios为例,其定义如下:

    /* include/uapi/asm-generic/termbits.h */

    struct ktermios {

    tcflag_t c_iflag;               /* input mode flags */

    tcflag_t c_oflag;               /* output mode flags */

    tcflag_t c_cflag;               /* control mode flags */

    tcflag_t c_lflag;               /* local mode flags */

    cc_t c_line;                    /* line discipline */

    cc_t c_cc[NCCS];                /* control characters */

    speed_t c_ispeed;               /* input speed */

    speed_t c_ospeed;               /* output speed */

    };

    说实话,要理解上面的数据结构,真的不是一件容易的事情,这里只能简单介绍一些我们常用的内容,更为具体的,如有需要,后面会用单独的文章去分析:

    c_cflag,可以控制TTY设备的一些特性,例如data bits、parity type、stop bit、flow control等(例如串口设备中经常提到的8N1);

    c_ispeed、c_ospeed,可以分别控制TTY设备输入和输出的速度(例如串口设备中的波特率);

    其它,暂不介绍。

    2.6 tty driver flags

    TTY driver在注册struct tty_driver变量的时候,可以提供一些flags,以告知TTY core一些额外的信息,例如(具体可参考include/linux/tty_driver.h中的定义和注释,写的很清楚):

    TTY_DRIVER_DYNAMIC_DEV:如果设置了该flag,则表示TTY driver会在需要的时候,自行调用tty_register_device接口注册TTY设备(相应地回体现在字符设备以及sysfs中);如果没有设置,TTY core会在tty_register_driver时根据driver->num信息,自行创建对应的TTY设备。

    2.7 TTY操作函数集

    TTY core将和硬件有关的操作,抽象、封装出来,形成名称为struct tty_operations的数据结构,具体的TTY driver不需要关心具体的业务逻辑,只需要根据实际的硬件情况,实现这些操作接口即可。

    听着还挺不错啊(framework的中心思想一贯如此,大家牢记即可),不过不能高兴的太早,看过这个数据结构之后,估计心会凉半截:

    struct tty_operations {

    struct tty_struct * (*lookup)(struct tty_driver *driver,

    struct inode *inode, int idx);

    int  (*install)(struct tty_driver *driver, struct tty_struct *tty);

    void (*remove)(struct tty_driver *driver, struct tty_struct *tty);

    int  (*open)(struct tty_struct * tty, struct file * filp);

    void (*close)(struct tty_struct * tty, struct file * filp);

    void (*shutdown)(struct tty_struct *tty);

    void (*cleanup)(struct tty_struct *tty);

    int  (*write)(struct tty_struct * tty,

    const unsigned char *buf, int count);

    int  (*put_char)(struct tty_struct *tty, unsigned char ch);

    void (*flush_chars)(struct tty_struct *tty);

    int  (*write_room)(struct tty_struct *tty);

    int  (*chars_in_buffer)(struct tty_struct *tty);

    int  (*ioctl)(struct tty_struct *tty,

    unsigned int cmd, unsigned long arg);

    long (*compat_ioctl)(struct tty_struct *tty,

    unsigned int cmd, unsigned long arg);

    void (*set_termios)(struct tty_struct *tty, struct ktermios * old);

    void (*throttle)(struct tty_struct * tty);

    void (*unthrottle)(struct tty_struct * tty);

    void (*stop)(struct tty_struct *tty);

    void (*start)(struct tty_struct *tty);

    void (*hangup)(struct tty_struct *tty);

    int (*break_ctl)(struct tty_struct *tty, int state);

    void (*flush_buffer)(struct tty_struct *tty);

    void (*set_ldisc)(struct tty_struct *tty);

    void (*wait_until_sent)(struct tty_struct *tty, int timeout);

    void (*send_xchar)(struct tty_struct *tty, char ch);

    int (*tiocmget)(struct tty_struct *tty);

    int (*tiocmset)(struct tty_struct *tty,

    unsigned int set, unsigned int clear);

    int (*resize)(struct tty_struct *tty, struct winsize *ws);

    int (*set_termiox)(struct tty_struct *tty, struct termiox *tnew);

    int (*get_icount)(struct tty_struct *tty,

    struct serial_icounter_struct *icount);

    #ifdef CONFIG_CONSOLE_POLL

    int (*poll_init)(struct tty_driver *driver, int line, char *options);

    int (*poll_get_char)(struct tty_driver *driver, int line);

    void (*poll_put_char)(struct tty_driver *driver, int line, char ch);

    #endif

    const struct file_operations *proc_fops;

    };

    这也太复杂了吧?确实如此,好在终端设备正在慢慢的退出历史舞台,看这篇文章的同学们,可能这一辈子都不会直接去写一个TTY driver。所以,这里我也不打算详细介绍,仅仅出于理解TTY framework的目的,做如下说明:

    这些操作函数的操作对象,基本上都是struct tty_struct类型的指针,这也印证了我们在2.3中所说的----TTY struct是TTY设备的操作句柄;

    当然,具体的TTY driver,可以从struct tty_struct指针中获取足够多的有关该TTY设备的信息,例如TTY port等;

    TTY core会通过“.write“接口,将输出信息送给终端设备并显示。因此具体的TTY driver需要实现该接口,并通过硬件操作将数据送出;

    你一定会好奇:既然有“.write“接口,为什么没有相应的read接口?TTY设备上的输入信息,怎么经由TTY core送给Application呢?具体可以参考"TTY驱动分析[2]”,本文不再详细介绍了。

    3. 提供的用于编写TTY driver的API

    在提供了一系列的数据结构的同时,TTY framework向下封装了一些API,以方便TTY driver的开发,具体如下。

    3.1 TTY driver有关的API

    用于struct tty_driver数据结构的分配、初始化、注册等:

    /* include/linux/tty_driver.h */

    extern struct tty_driver *__tty_alloc_driver(unsigned int lines,

    struct module *owner, unsigned long flags);

    extern void put_tty_driver(struct tty_driver *driver);

    extern void tty_set_operations(struct tty_driver *driver,

    const struct tty_operations *op);

    extern struct tty_driver *tty_find_polling_driver(char *name, int *line);

    extern void tty_driver_kref_put(struct tty_driver *driver);

    /* Use TTY_DRIVER_* flags below */

    #define tty_alloc_driver(lines, flags) \

    __tty_alloc_driver(lines, THIS_MODULE, flags)

    /* include/linux/tty.h */

    extern int tty_register_driver(struct tty_driver *driver);

    extern int tty_unregister_driver(struct tty_driver *driver);

    tty_alloc_driver,分配一个struct tty_driver指针,并初始化那些不需要driver关心的字段:

    lines,指明该driver最多能支持多少个设备,TTY core会根据该参数,分配相应个数的ttys、ports、termios数组;

    flags,请参考2.6小节的说明。

    tty_set_operations,设置TTY操作函数集。

    tty_register_driver,将TTY driver注册给TTY core。

    3.2 TTY device有关的API

    如果TTY driver设置了TTY_DRIVER_DYNAMIC_DEV flag,就需要自行注册TTY device,相应的API包括:

    /* include/linux/tty.h */

    extern struct device *tty_register_device(struct tty_driver *driver,

    unsigned index, struct device *dev);

    extern struct device *tty_register_device_attr(struct tty_driver *driver,

    unsigned index, struct device *device,

    void *drvdata,

    const struct attribute_group **attr_grp);

    extern void tty_unregister_device(struct tty_driver *driver, unsigned index);

    tty_register_device,分配并注册一个TTY device,最后将新分配的设备指针返回给调用者:

    driver,对应的TTY driver;

    index,该TTY设备的编号,它会决定该设备在字符设备中的设备号,以及相应的设备名称,例如/dev/ttyS0中的‘0’;

    dev,可选的父设备指针。

    tty_register_device_attr,和tty_register_device类似,只不过可以额外指定设备的attribute。

    3.3 数据传输有关的API

    当TTY core有数据需要发送给TTY设备时,会调用TTY driver提供的.write或者.put_char回调函数,TTY driver在这些回调函数中操作硬件即可。

    当TTY driver从TTY设备收到数据并需要转交给TTY core的时候,需要调用TTY buffer有关的接口,将数据保存在缓冲区中,并等待Application读取,相关的API有:

    /* include/linux/tty_flip.h*/

    static inline int tty_insert_flip_char(struct tty_port *port,

    unsigned char ch, char flag)

    {

    ….

    }

    static inline int tty_insert_flip_string(struct tty_port *port,

    const unsigned char *chars, size_t size)

    {

    return tty_insert_flip_string_fixed_flag(port, chars, TTY_NORMAL, size);

    }

    注5:本文没有涉及TTY buffer、TTY flip有关的知识,大家知道有这么回事就行了。

    4. TTY driver的编写步骤

    说实话,TTY driver的编写步骤,就和“把大象放进冰箱”一样“简单”:

    步骤1:实现TTY设备有关的操作函数集,并保存在一个struct tty_operations变量中。

    步骤2:调用tty_alloc_driver分配一个TTY driver,并根据实际情况,设置driver中的字段(包括步骤1中的struct tty_operations变量)。

    步骤3:调用tty_register_driver将driver注册到kernel。

    步骤4:如果需要动态注册TTY设备,在合适的时机,调用tty_register_device或者tty_register_device_attr,向kernel注册TTY设备。

    步骤5:接收到数据时,调用tty_insert_flip_string或者tty_insert_flip_char将数据交给TTY core;TTY core需要发送数据时,会调用driver提供的回调函数,在那里面访问硬件送出数据即可。

    好吧,相信任何人看到上面的步骤之后,都没办法去写一个完整的TTY driver(我也是)。好在这是一个幸福的时代,我们很少需要直接去写这样的一个driver。那么本文的目的又是什么呢?权当是一个科普吧,如果你真的打算去写一个TTY driver,不至于无从下手。

    5. 参考文档

    [2] TTY驱动分析(链接失效,TODO)

    [3] TTY各数据结构关系图,http://www.wowotech.net/content/uploadfile/201505/eb451430746679.gif((链接失效,TODO))

    原创文章,转发请注明出处。蜗窝科技,www.wowotech.net。c6a6308114f401be7df747ae46f2b4db.png

    评论:

    magicse7en

    2017-06-19 13:50

    参考文档 [2][3] 的链接都已经失效

    2017-06-19 17:11

    @magicse7en:多谢提醒,我处理一下。

    hit20j

    2017-09-22 23:30

    @wowo:请问 TTY驱动分析 链接在哪里?

    2017-09-23 10:24

    @hit20j:没有链接了,被原作者删除了:-)

    numbqq

    2017-06-15 16:07

    Hi wowo,

    看了你的系列文章,受益匪浅,非常感谢!我最近调试终端碰到点问题想请教一下。忘不吝赐教。我现在使用HDMI输出,配置framebuffer console使信息输出到显示器,但是输出显示碰到一个问题就是显示器字符刷新慢,我通过键盘输入字符,字符不会马上在屏幕上显示完整,而是慢慢才会显示完整,感觉刷新很慢。通过

    echo kkkkkkk > /dev/tty1,kkkkkkk也是慢慢才显示完整,请问你知道这会是哪方面的问题吗?非常感谢!

    2017-06-15 18:27

    @numbqq:fb console每画一个字符,都是把这个字符,和屏幕上已有的内容一起,转成一副完整的图片,然后写入到buffer中。

    因此,基于当前的分辨率、刷新率、fb的位数,你可以算算显示一个字符的时间(估计快不到哪里去)。

    numbqq

    2017-06-15 18:56

    @wowo:谢谢这么快回复!

    正常来说从键盘输入字符到显示器显示出这个字符,时间应该是一致的,至少肉眼看不出时间差,但是现在我碰到的问题是键盘输入一个字符后,屏幕不会马上显示出这个完整的字符,而是会显示字符其中一部分像素点,在慢慢显示出完整的字符,肉眼明显能感受到显示字符不对。以前没有调过这方面的,不知道问题到底出在哪,能不能给一些建议呢?谢谢!

    2017-06-19 08:43

    @numbqq:出现这种情况,是因为fbcon在一个像素点一个像素点地画这个字符的时候,你的现实硬件还在不停的从ram中刷新到显示屏上,二者没有同步,你可以从这个方面思考一下。

    randy

    2017-04-10 11:50

    问一个问题:如何屏蔽掉tty对tty ldisc线性规程的处理?我现在板子上只有一个uart设备,但是这个设备默认使用line ldisc进行字符串预处理了,比如换行什么的,我现在不希望它做预处理,而是直接把数据从uart->line ldisc->tty->fs透传上来到用户态应用程序。我想到一个方案是自己写一个ldisc的驱动,然后在应用层告诉这个tty文件节点使用我写的ldisc驱动进行透传数据,但是这个比较麻烦,在应用层有可以更简单的方式使用uart接收到的数据么?

    2017-04-10 16:05

    @randy:如果仅仅是去掉线路规程的预处理,在用户空间设置tty设备的termios,将input设置为non-canonical模式,并disable output的OPOST flag,应该可以实现。

    具体你可以查查termios的flag,例如:

    http://man7.org/linux/man-pages/man3/tcsetattr.3.html

    randy

    2017-04-10 17:11

    @wowo:谢谢回复。再请教一个问题:我看你前面的文章有说tty不是一个device,也就是说一个uart设备可以虚拟出多个tty设备吗?如果是这样,假如我单板上一个uart口已经用作了控制台,那再抽象出一个ttyA的话,对于读操作而言,uart怎么知道数据是扔给控制台还是ttyA呢?还是说谁先读就扔给谁?

    2017-04-11 13:25

    @randy:这样的用法有点奇怪。通常情况下,一个串口,对应一个tty设备,不会有两个。

    adrian

    2017-06-11 19:26

    @wowo:我的看法是:

    1, 你可以试试cfmakeraw

    2, 如果真有这重需求的话(serial multiplexing), 需要自己实现,可以考虑自己在driver里实现一个复用协议,但是需要serial两端都遵守,没有通用意义

    发表评论:

    昵称

    邮件地址 (选填)

    个人主页 (选填)

    d4e3789769c8ad44c7e403863bfc3822.png

    更多相关内容
  • 概述Linux TTY/PTS的区别

    2020-09-14 21:42:45
    主要介绍了概述Linux TTY/PTS的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • 一文搞懂 Linux TTY

    千次阅读 2022-04-19 15:34:30
    由于历史原因, Linux保留了TTY,上述的输入和输出两个电缆,可以简单的认为是键盘输入和显卡输出 tty和stty命令 tty命令返回当前的终端名字,1表示可以通过Ctrl+Alt+F3得到 $ tty /dev/pts/1 stty是对tty进行设置...

    TTY的历史

    TTY全称TeleTYpewriter,也即是电传打字机,它通过两根电缆连接计算机,一根用于向计算机发送指令,一根用于接收计算机的输出,输出结果是打印在纸上的

    由于历史原因, Linux保留了TTY,上述的输入和输出两个电缆,可以简单的认为是键盘输入和显卡输出

    在这里插入图片描述

    tty和stty命令

    tty命令返回当前的终端名字,1表示可以通过Ctrl+Alt+F3得到

    $ tty
    /dev/pts/1
    

    stty是对tty进行设置的命令,s表示set

      - Display all settings for the current terminal:
        stty -a
    
      - Set the number of rows:
        stty rows rows
    
      - Set the number of columns:
        stty cols cols
    
      - Get the actual transfer speed of a device:
        stty -F path/to/device_file speed
    
      - Reset all modes to reasonable values for the current terminal:
        stty sane
    
    

    列出当前tty的所有配置信息:

    $ stty -a
    speed 9600 baud; rows 35; columns 129; line = 0;
    intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S;
    susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; discard = ^O; min = 1; time = 0;
    -parenb -parodd -cmspar cs8 -hupcl -cstopb cread -clocal -crtscts
    -ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc -ixany -imaxbel -iutf8
    opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
    isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke -flusho -extproc
    

    切换tty

    Ctrl+Alt+F1可以切换到第一个tty,以此类推

    这里把字符串输入到tty2,由于现在处于pts1,因此终端没有显示,当切换到tty2就会显示字符串

    在这里插入图片描述
    这里切换到了tty4
    在这里插入图片描述

    伪终端:pseudo terminal

    • 终端模拟器(terminal emulator) ,是运行在内核的模块
    • 用户态的终端模拟程序,被称为伪终端(pseudo terminal, PTY)

    可以通过打开文件 /dev/ptmx 创建伪终端,伪终端 pty 具有以下两种用途:

    • 使用 telnet、 ssh 命令支持远程登录
    • 提供窗口系统用以创建命令解释程序窗口的界面

    pty最大配额

    /proc/sys/kernel/pty/max
                  This file defines the maximum number of pseudoterminals.
    
           /proc/sys/kernel/pty/nr
                  This read-only file indicates how many pseudoterminals are
                  currently in use.
    

    在这里插入图片描述

    展开全文
  • linux tty驱动源码分析

    2016-09-05 09:13:07
    linux tty驱动源码进行简要分析,明确tty工作流程,及tty线路规程作用。
  • 如果没有替Linux操作系统安装桌面环境的话,在Linux操作系统开机之后,缺省会进入TTY主控台画面。有时缺省的TTY画面所套用的屏幕分辨率并不是我们想要的,若要修改屏幕分辨率的话可以参考本篇文章。要修改TTY的屏幕...

    如果没有替Linux操作系统安装桌面环境的话,在Linux操作系统开机之后,缺省会进入TTY主控台画面。有时缺省的TTY画面所套用的屏幕分辨率并不是我们想要的,若要修改屏幕分辨率的话可以参考本篇文章。

    要修改TTY的屏幕分辨率,可以去设置GRUB开机引导程序,本篇文章将会以GRUB2来说明。

    修改Linux TTY的屏幕分辨率

    首先要在电脑开机时进入GRUB菜单。如果您的电脑并没有安装两个以上的操作系统,那么在电脑开机时可能不会显示出GRUB菜单,若要调用出GRUB菜单,可以在按下电脑开机键之后,掌握时机按下键盘上的ESC键。

    834c561d32c6b9c25b32973f96618ca7.png

    在GRUB菜单中按下c键,可以进入GRUB的命令行模式。

    2feb021956e2e5ebc9e4b0ee304cb4d6.png

    先运行以下指令:

    set pager=1

    这个指令可以将环境变量pager设置为1,目的在于使之后运行的指令,如果屏幕输出内容太多的话,可以拥有如more或是less等工具的「继续阅读」功能。避免因屏幕塞不下过多的内容,而导致我们无法查看指令完整的输出信息。

    c1375ea17b4d535ad8558f0e371ab3e6.png

    接着运行以下指令:

    vbeinfo

    以上指令可以查看这台电脑的VBE(VESA BIOS Extensions)支持哪些显示模式。

    42964e4abbcb67d00089039ea0d1be47.png

    将我们所需要的分辨率的长和宽,以及色彩的比特深度记下之后,即可在GRUB命令行模式中按下键盘上的ESC键来回到GRUB菜单。

    9e8ff7d944fed091166f4ea834210d15.png

    正常开机之后,使用文本编辑器来编辑GRUB的设置档/etc/default/grub。例如要用Vim来编辑的话,可以直接在终端机运行以下指令:

    sudo vim /etc/default/grub

    884dad2633bfd8ad589f4dc5266e495d.png

    找到GRUB_GFXMODE这个设置项目,缺省应该会被加上井字号#而变成注解,将其解除注解之后,依照以下的方式进行修改:

    GRUB_GFXMODE=长x宽x比特深度

    最后的比特深度可以省略掉。

    理论上这样设置就可以了,但实际上GRUB_GFXMODE这个设置项目常常不能正常工作,建议再加上GRUB_GFXPAYLOAD_LINUX这个项目,并设置为与GRUB_GFXMODE相同的值。网络上有些数据可能会讲说要把GRUB_GFXPAYLOAD_LINUX设置为keep,但这通常无法解决问题。

    所以,假设我们想将TTY的屏幕分辨率和色彩比特深度设为1152x864和32比特,则GRUB设置档可以这样写:

    GRUB_GFXMODE=1152x864x32

    GRUB_GFXPAYLOAD_LINUX=1152x864x32

    8f6326f7e7b0cc51e17f9022a96c0ae4.png

    保存GRUB设置档的变更之后,在终端机运行以下指令来检查并套用新设置:

    sudo update-grub

    f3a6ff0e34874a02c4931e46167dacae.png

    重新开机后,即可看见修改成果。

    展开全文
  • 了解linux tty 1.TTY概述   TTY 是 Teletype 或 Teletypewriter 的缩写,原来是指电传打字机,后来这种设备逐渐键盘和显示器取代。不管是电传打字机还是键盘显示器,都是作为计算机的终端设备存在的,所以 TTY 也...
    • 了解linux tty

    1.TTY概述

      TTY 是 Teletype 或 Teletypewriter 的缩写,原来是指电传打字机,后来这种设备逐渐键盘和显示器取代。不管是电传打字机还是键盘显示器,都是作为计算机的终端设备存在的,所以 TTY 也泛指计算机的终端(terminal)设备。为了支持这些 TTY 设备,Linux 实现了一个叫做 TTY 的子系统。所以 TTY 既指终端,也指 Linux 的 TTY 子系统,当然 TTY 还有更丰富(混乱)的含义。

      硬件终端 terminal(TTY):

      早期的终端(terminal) 是一台独立于计算机的机器(teletype 即, TTY),样子:
    在这里插入图片描述
      它终端通过线缆与计算机连接,并完成计算机的输入输出功能:
    在这里插入图片描述
      现在物理终端实际上已经灭绝了,看到的所有 TTY 都是模拟视频终端,即软件仿真出来的终端。可以通过 toe -a 命令查看系统支持的终端类型。

    2.控制台 console

      提到终端就不能不提控制台 console。控制台的概念与终端含义非常相近,其实现在经常用它们表示相同的东西,但是在计算机的早期时代,它们确实是不同的东西。

      一些数控设备(比如数控机床)的控制箱,通常会被称为控制台,顾名思义,控制台就是一个直接控制设备的面板,上面有很多控制按钮。 在计算机里,把那套直接连接在电脑上的键盘和显示器就叫做控制台。而终端是通过串口连接上的,不是计算机自身的设备,而控制台是计算机本身就有的设备,一个计算机只有一个控制台。计算机启动的时候,所有的信息都会显示到控制台上,而不会显示到终端上。这同样说明,控制台是计算机的基本设备,而终端是附加设备。计算机操作系统中,与终端不相关的信息,比如内核消息,后台服务消息,都可以显示到控制台上,但不会显示到终端上。

      现在终端和控制台都由硬件概念,逐渐演化成了软件的概念。简单的说,能直接显示系统消息的那个终端称为控制台,其他的则称为终端(控制台也是一个终端)。或者我们在平时的使用中压根就不区分 Linux 中的终端与控制台。

    3.TTY 设备

      从历史上看,终端刚开始就是终端机,配有打印机,键盘,带有一个串口,通过串口传送数据到主机端,然后主机处理完交给终端打印出来。电传打字机(teletype)可以被看作是这类设备的统称,因此终端也被简称为 TTY(teletype 的缩写)。
    如下图所示:
    在这里插入图片描述

    • UART 驱动
      如上图所示,物理终端通过电缆连接到计算机上的 UART(通用异步接收器和发射器)。操作系统中有一个 UART 驱动程序用于管理字节的物理传输。

    • 行规范
      上图中内核中的 Line discipline(行规范)用来提供一个编辑缓冲区和一些基本的编辑命令(退格,清除单个单词,清除行,重新打印),主要用来支持用户在输入时的行为(比如输错了,需要退格)。

    • TTY 驱动
      TTY 驱动用来进行会话管理,并且处理各种终端设备。

    • UART 驱动、行规范和 TTY 驱动都位于内核中,它们的一端是终端设备,另一端是用户进程。因为在 Linux 下所有的设备都是文件,所以它们三个加在一起被称为 “TTY 设备”,即常说的 TTY。

    4.从软件仿真终端到伪终端

      后来的终端慢慢演变成了键盘 + 显示器。如果我们要把内容输出到显示器,只要把这些内容写入到显示器对应的 TTY 设备就可以了,然后由 TTY 层负责匹配合适的驱动完成输出,这也是 Linux 控制台的工作原理:
    在这里插入图片描述
      上图中,TTY 驱动和行规范的行为与前面的示例类似,但不再有 UART 或物理终端。相反,软件仿真出视频终端,并最终被渲染到 VGA 显示器。注意,这里出现了软件仿真终端,它们是运行在内核态的。

    refer to

    • https://www.cnblogs.com/sparkdev/p/11460821.html
    • http://www.mysixue.com/?p=127
    展开全文
  • 了解linux tty driver 1.TTY device   kernel从设备模型和字符设备两个角度对它进行了抽象: 设备模型的角度   为每个“数据通道”注册了一个stuct device,以便可以在sysfs中体现出来,例如: /sys/class/...
  • linux tty驱动架构分析

    2021-05-14 04:56:44
    前一阵子移植一个串口驱动,发现linux的驱动构架中,面向对象的思想已经根深蒂固。就比如这串口驱动,代码中经常有一些貌似和串口无关的代码,比如,tty_register_driver等。但我们却删它不得。因为正是这些代码实现...
  • linux tty1-7理解

    2021-05-18 14:18:47
    tty1-6是文本型控制台,7是x-window(图形)控制台.在本地机器上可以通过alt+f1(f1-f7键)切换到对应的登录控制台.比如可以在tty1用root登录,再在tty2登录root,tty1查询的结果跟tty2查询的结果进行对比.因为它不像在xp...
  • linux tty个数修改

    2020-12-21 10:28:09
    自动启用的tty@.service数量,默认为6指tty2-tty7 ReserveVT 不包含在NAutoVTs个数中,启用的tty@.service eg: NAutoVTs=3,ReserveVT=6表示启用tty2,3,7 + tty6 关于默认具体是哪个tty,系统不同可能有差异。 2...
  • Tty这个名称源于电传打字节的简称。在linux表示各种终端。终端通常都跟硬件相对应。比如对应于输入设备键盘鼠标。输出设备显示器的控制 终端和串口终端.也有对应于不存在设备的pty驱动。在如此众多的终端模型之中,...
  • tty文本字符界面显示中文乱码是个比较头疼的事情。偶尔一两次也没多大影响,但每执行一条命令之后都会输出方块文字,搞不懂电脑在说啥,的确影响心情。如果碰上mc和nano这样的cli应用,界面菜单上会有大量的方块乱码...
  • 为了简化终端的使用,以及终端驱动程序的编写,Linux kernel抽象出了TTY framework:对上,向应用程序提供使用终端的统一接口;对下,提供编写终端驱动程序(如serial driver)的统一框架。TTY framework通过TTY ...
  • 在上一章我们主要介绍了tty子系统的软件架构,并简要说明了数据结构间的关系,本...struct tty_file_private struct file struct tty_struct struct tty_driver struct tty_operations struct tty_ldisc struct tty...
  • Linux切换到tty登录时,明明输入了正确的用户名和密码,可仍然一直提示Login incorrect, 摸索了几次发现,这是由于我的密码中包含数字,而此时num lock数字键盘的锁定状态不正确引起的,只要重新按几下num lock...
  • linux虚拟tty驱动(kernel4.9版本以上),可产生多个tty串口设备于/dev/下,本人在Hi3516上交叉编译并应用,实现多个虚拟串口同时控制一个实际串口的操作
  • linux tty driver

    2016-12-12 22:05:23
    Linux TTY 驱动 1.前言 上世纪,六七十年代,虽然已经有电脑了,但还没有普及,电脑还是极其昂贵的,普通老百姓都买不起这么贵的一台电脑。那时候,UNIX的发明人——汤普森,为了实现多用户能够同时登陆UNIX系统...
  • 显示行号|选择喜欢的代码风格默认...tty 命令安装:-bash: tty: command not found#Debianapt-get install coreutils#Ubuntuapt-get install coreutils#Alpine...
  • linux tty

    2018-01-07 13:20:54
    who查看系统连接多少个登录终端,tty查看当前的终端号: [root@system1 ~]# tty /dev/pts/3 tty1-6是文本型控制台,7是x-window(图形)控制台.在本地机器上可以通过alt+f1(f1-f7键)切换到对应的登录控制台.比如...
  • Linux TTY Driver

    2020-03-10 22:58:09
    引用 蜗蜗科技 ... Linux终端和Line discipline图解 https://blog.csdn.net/dog250/article/details/78818612 一. TTY drive框图 二. TTY framework 2.1 框图 2.2 数据结构图 三. ...
  • 2.9 Linux tty终端

    千次阅读 2017-10-13 11:28:35
    Linux在内核启动完成以后,需要启动用户态的各种应用服务,让linux可以提供给用户使用。通常用户程序的执行过程如图所示。 其执行顺序是/sbin/init ——–>/sbin/mingetty ——–>/bin/login ——–>/bin/sh。Init...
  • LinuxTTY

    2021-12-16 16:07:37
    LinuxTTY1.串行端口终端(/dev/ttySn)2.虚拟终端(/dev/pty/)3.控制终端(/dev/tty)4.控制台终端(/dev/ttyn, /dev/console)5.其它类型 终端是一种字符型设备,它有多种类型,通常使用tty来简称各种类型的终端...
  • Linux系统TTY串口驱动实例详解

    千次阅读 2022-03-18 16:15:48
    Linux tty子系统包含:tty核心,tty线路规程和tty驱动。tty核心是对整个tty设备的抽象,对用户提供统一的接口,tty线路规程是对传输数据的格式化,tty驱动则是面向tty设备的硬件驱动。它们的关系如下图: 简单来分的...
  • linux-TTY子系统.pdf

    2020-07-24 17:32:47
    Linux系统中, 与终端相关的概念很容易让人迷糊. 首先有终端这个概念, 然后还有各种类型的终端(串口终端, 伪终端, 控制台终端, 控制终端), 还有一个概念叫console. 那么什么是终端? 什么是控制台终端? 什么是...
  • 在上一章中我们介绍了tty子系统相关的数据结构,本章我们主要介绍tty driver的注册与注销、线路... 主要实现tty controller 驱动的注册与注销操作,相应的函数包括tty_register_driver、tty_unregister_driver,下面...
  • Linux 黑话解释:TTY 是什么? | Linux 中国看不太懂。。参考文章:linuxtty是什么意思
  • Linux tty串口测试程序

    千次阅读 2015-04-10 14:07:53
    关于termios的详细介绍,可以另行查资料,或者参考:详解linux下的串口通讯开发:http://blog.itpub.net/24790158/viewspace-1041147/ #include #include #include #include #include #include #in

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 120,663
精华内容 48,265
关键字:

linux tty

友情链接: yuyu0090.rar