TTY 结构体

struct tty_struct 在首次打开 TTY 设备时由 TTY 层分配,并在最后一次关闭后释放。TTY 层将此结构传递给大多数 struct tty_operation 的钩子。tty_struct 的成员记录在底部的 TTY 结构体参考中。

初始化

void tty_init_termios(struct tty_struct *tty)

用于 termios 设置的助手

参数

struct tty_struct *tty

要设置的 tty

描述

初始化此 tty 的 termios 结构。这目前在 tty_mutex 下运行,因此我们可以放松对排序的要求。

名称

const char *tty_name(const struct tty_struct *tty)

返回 tty 命名

参数

const struct tty_struct *tty

tty 结构

描述

将 tty 结构转换为名称。该名称反映了内核命名策略,如果正在使用 udev,则可能不反映用户空间

锁定:无

引用计数

struct tty_struct *tty_kref_get(struct tty_struct *tty)

获取 tty 引用

参数

struct tty_struct *tty

tty 设备

返回

tty 对象的新引用

描述

锁定:调用者必须持有足够的锁/计数,以确保其现有引用不会消失。

void tty_kref_put(struct tty_struct *tty)

释放 tty kref

参数

struct tty_struct *tty

tty 设备

描述

释放对 tty 设备的引用,如果需要,让 kref 层为我们销毁该对象。

安装

int tty_standard_install(struct tty_driver *driver, struct tty_struct *tty)

通常的 tty->ops->install

参数

struct tty_driver *driver

tty 的驱动程序

struct tty_struct *tty

tty

描述

如果 driver 重写 tty->ops->install,它仍然可以调用此函数来执行标准安装操作。

读取 & 写入

int tty_put_char(struct tty_struct *tty, u8 ch)

向 tty 写入一个字符

参数

struct tty_struct *tty

tty

u8 ch

要写入的字符

描述

如果存在,使用提供的 tty->ops->put_char() 方法向 tty 写入一个字节。

注意

驱动程序层中的特定 put_char 操作可能很快就会消失。不要直接调用它,使用此方法

返回

成功输出的字符数。

启动 & 停止

void stop_tty(struct tty_struct *tty)

传播流控制

参数

struct tty_struct *tty

要停止的 tty

描述

对驱动程序执行流控制。可以在已停止的设备上调用,并且不会重新调用 tty_driver->stop() 方法。

此功能由线路规程用于停止传入流量以及驱动程序使用。因此,可以从任何上下文调用它,可以在 tty atomic_write_lock 下,但并非总是如此。

锁定

flow.lock

void start_tty(struct tty_struct *tty)

传播流控制

参数

struct tty_struct *tty

要启动的 tty

描述

尽可能启动已停止的 tty。如果 tty 之前已停止,现在正在启动,则会调用 tty_driver->start() 方法,并且唤醒线路规程。

锁定

flow.lock

唤醒

void tty_wakeup(struct tty_struct *tty)

请求更多数据

参数

struct tty_struct *tty

终端

描述

tty唤醒的内部和外部辅助函数。此函数通知线路规程(如果存在),驱动程序已准备好接收更多输出数据。

挂断

void tty_hangup(struct tty_struct *tty)

触发挂断事件

参数

struct tty_struct *tty

要挂断的tty

描述

tty 上发生了载波丢失(虚拟或其他)。安排在此事件后运行挂断序列。

void tty_vhangup(struct tty_struct *tty)

处理虚拟挂断

参数

struct tty_struct *tty

要挂断的tty

描述

用户已通过系统调用请求挂断终端。我们同步执行此操作,以便在系统调用返回时进程完成。为了安全起见,该保证是必要的。

int tty_hung_up_p(struct file *filp)

tty是否已挂断

参数

struct file *filp

tty的文件指针

返回

如果tty受到虚拟挂断或载波丢失的影响,则为真

杂项

int tty_do_resize(struct tty_struct *tty, struct winsize *ws)

调整大小事件

参数

struct tty_struct *tty

正在调整大小的tty

struct winsize *ws

新的尺寸

描述

更新termios变量并发送必要的信号以正确执行终端大小调整。

TTY结构标志

这些位用于tty_struct.flags字段中。

为了使中断不会弄乱队列,copy_to_cooked 必须相对于自身是原子的,tty->write 也必须是原子的。因此,您必须使用内联函数 set_bit()clear_bit() 来使事情成为原子的。

TTY_THROTTLED

驱动程序输入受到限制。lcsic 应该调用 tty_driver.unthrottle() 以便在准备好处理更多数据时(在阈值最小值时)恢复接收。

TTY_IO_ERROR

如果设置,会导致随后在 tty 上的所有用户空间读/写调用失败,返回 -EIO。(也可能没有 ldisc。)

TTY_OTHER_CLOSED

设备是 pty,另一端已关闭。

TTY_EXCLUSIVE

独占打开模式(单个打开器)。

TTY_DO_WRITE_WAKEUP

如果设置,会导致驱动程序调用 tty_ldisc_ops.write_wakeup() 方法,以便在它可以接受更多要传输的数据时恢复传输。

TTY_LDISC_OPEN

指示行规程已打开。仅用于调试目的。

TTY_PTY_LOCK

pty 代码私有的标志,用于实现 TIOCSPTLCK/TIOCGPTLCK 逻辑。

TTY_NO_WRITE_SPLIT

防止驱动程序将写入分成较小的块(将写入边界保留到驱动程序)。

TTY_HUPPED

TTY 已挂断。这在 tty_driver.hangup() 之后设置。

TTY_HUPPING

TTY 正在挂断以中止潜在的读取器。

TTY_LDISC_CHANGING

此 TTY 的行规程正在更改。设置此项时,I/O 不应阻塞。使用 tty_io_nonblock() 进行检查。

TTY_LDISC_HALTED

此 TTY 的行规程已停止。不应将任何工作排队到此 ldisc。

TTY 结构参考

struct tty_struct

打开时与 tty 关联的状态

定义:

struct tty_struct {
    struct kref kref;
    int index;
    struct device *dev;
    struct tty_driver *driver;
    struct tty_port *port;
    const struct tty_operations *ops;
    struct tty_ldisc *ldisc;
    struct ld_semaphore ldisc_sem;
    struct mutex atomic_write_lock;
    struct mutex legacy_mutex;
    struct mutex throttle_mutex;
    struct rw_semaphore termios_rwsem;
    struct mutex winsize_mutex;
    struct ktermios termios, termios_locked;
    char name[64];
    unsigned long flags;
    int count;
    unsigned int receive_room;
    struct winsize winsize;
    struct {
        spinlock_t lock;
        bool stopped;
        bool tco_stopped;
    } flow;
    struct {
        struct pid *pgrp;
        struct pid *session;
        spinlock_t lock;
        unsigned char pktstatus;
        bool packet;
    } ctrl;
    bool hw_stopped;
    bool closing;
    int flow_change;
    struct tty_struct *link;
    struct fasync_struct *fasync;
    wait_queue_head_t write_wait;
    wait_queue_head_t read_wait;
    struct work_struct hangup_work;
    void *disc_data;
    void *driver_data;
    spinlock_t files_lock;
    int write_cnt;
    u8 *write_buf;
    struct list_head tty_files;
#define N_TTY_BUF_SIZE 4096;
    struct work_struct SAK_work;
};

成员

kref

通过 tty_kref_get()tty_kref_put() 进行引用计数,达到零时会释放该结构

index

此 tty 的索引(例如,构造像 tty12 这样的名称

dev

类设备或 NULL(例如,ptys、serdev)

driver

操作此 tty 的 struct tty_driver

port

此设备的持久存储(即 struct tty_port

ops

此 tty 的 driverstruct tty_operations(打开、关闭等)

ldisc

此 tty 的当前行规程(默认为 n_tty)

ldisc_sem

保护行规程更改(ldisc)--锁定 tty 而不是 pty

atomic_write_lock

防止并发写入,即锁定 write_cntwrite_buf 和类似内容

legacy_mutex

历史遗留(BKL -> BTM -> legacy_mutex),保护对此 tty 的多个操作

throttle_mutex

防止并发 tty_throttle_safe()tty_unthrottle_safe()(但不是 tty_unthrottle()

termios_rwsem

保护 termiostermios_locked

winsize_mutex

保护 winsize

termios

当前 tty 的 termios,从/复制到 driver.termios

termios_locked

锁定的 termios(通过 TIOCGLCKTRMIOSTIOCSLCKTRMIOS ioctl)

name

tty_line_name() 构造的 tty 的名称(例如 ttyS3)

flags

TTY_THROTTLEDTTY_IO_ERROR... 的按位或

count

打开进程的计数,达到零时会取消此 tty 的所有工作并丢弃一个 kref(但不释放此 tty)

receive_room

允许馈送到 ldisc 而不会丢失的字节数

winsize

终端“窗口”的大小(参见 winsize_mutex

flow

分组在一起的流设置

flow.lock

flow 成员的锁

flow.stopped

通过 stop_tty()/start_tty() 停止/启动的 tty

flow.tco_stopped

tty 通过 TCOOFF/ TCOON ioctl 停止/启动(它优先于 flow.stopped

ctrl

控制设置组合在一起

ctrl.pgrp

此 tty 的进程组 (setpgrp(2))

ctrl.session

此 tty 的会话 (setsid(2))。写入受 ctrl.locklegacy_mutex 的保护,读取者必须至少使用其中一个。

ctrl.lock

ctrl 成员的锁

ctrl.pktstatus

数据包模式状态(TIOCPKT_ 常量的按位或)

ctrl.packet

数据包模式已启用

hw_stopped

不受 tty 层控制,由 driver 控制用于 CTS 处理

closing

在关闭期间设置时,n_tty 仅处理 START 和 STOP 字符

flow_change

控制节流的行为,请参阅 tty_throttle_safe()tty_unthrottle_safe()

link

链接到另一个 pty (master -> slave 和反之亦然)

fasync

O_ASYNC 的状态 (用于 SIGIO);由 fasync_helper() 管理

write_wait

并发写入者在此队列中等待,直到允许他们写入

read_wait

读取者在此队列中等待数据

hangup_work

通常是执行挂起的工作 (do_tty_hangup());在释放 tty 时,(重新)用于 release_one_tty()

disc_data

指向 ldisc 私有数据的指针(例如,指向 struct n_tty_data

driver_data

指向 driver 私有数据的指针(例如,struct uart_state

files_lock

保护 tty_files 列表

write_cnt

tty_write() 中写入到 write_buf 的字节计数

write_buf

tty_write() 期间用于复制用户数据的临时缓冲区

tty_files

此 tty 的(重新)打开者列表(即,链接的 struct tty_file_private

SAK_work

如果 tty 有挂起的 do_SAK,它会在此处排队

描述

tty 打开时与 tty 关联的所有状态。tty 设备的持久存储在此处引用为 port,并在 struct tty_port 中进行了说明。