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)¶
处理 vhangup
参数
struct tty_struct *tty
要挂断的 tty
描述
用户已通过系统调用要求挂断终端。 我们同步执行此操作,以便系统调用返回时,该过程完成。 这种保证对于安全原因来说是必要的。
参数
struct file *filp
tty 的文件指针
返回
如果 tty 已经受到 vhangup 或载波丢失,则为 true
其他¶
-
int tty_do_resize(struct tty_struct *tty, struct winsize *ws)¶
resize 事件
参数
struct tty_struct *tty
正在调整大小的 tty
struct winsize *ws
新尺寸
描述
更新 termios 变量并发送必要的信号以正确执行终端大小调整。
TTY 结构体标志¶
-
enum tty_struct_flags¶
TTY 结构体标志
常量
TTY_THROTTLED
驱动程序输入已节流。 ldisc 应调用
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.flags
字段中使用。
为了使中断无法破坏队列,copy_to_cooked 必须相对于自身是原子的,tty->write 也必须如此。 因此,您必须使用内联函数 set_bit()
和 clear_bit()
使其成为原子。
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;
struct work_struct SAK_work;
};
成员
kref
通过
tty_kref_get()
和tty_kref_put()
进行引用计数,当达到零时释放该结构体index
此tty的索引(例如,构造像tty12这样的 **name**)
dev
类设备或
NULL
(例如,ptys, serdev)driver
操作此tty的
struct tty_driver
port
此设备的持久性存储(即
struct tty_port
)ops
此tty的 driver 的
struct tty_operations
(open,close等)ldisc
此tty的当前线路规程(默认为n_tty)
ldisc_sem
保护线路规程更改(**ldisc**)-- 锁定tty而不是pty
atomic_write_lock
防止并发写入者,即锁定 **write_cnt**,**write_buf** 等
legacy_mutex
历史遗留(BKL -> BTM -> **legacy_mutex**),保护对此tty的几个操作
throttle_mutex
防止并发的
tty_throttle_safe()
和tty_unthrottle_safe()
(但不是tty_unthrottle()
)termios_rwsem
保护 **termios** 和 **termios_locked**
winsize_mutex
保护 **winsize**
termios
当前tty的termios,从/到 **driver.termios** 复制
termios_locked
锁定的termios(通过
TIOCGLCKTRMIOS
和TIOCSLCKTRMIOS
ioctl)name
由
tty_line_name()
构造的tty的名称 (例如,ttyS3)flags
TTY_THROTTLED
,TTY_IO_ERROR
等的按位或count
打开进程的计数,达到零会取消此tty的所有工作并删除一个 **kref**(但不会释放此tty)
receive_room
允许提供给 **ldisc** 而不会丢失的字节数
winsize
终端“窗口”的大小(参见 **winsize_mutex**)
flow
流设置分组在一起
flow.lock
**flow** 成员的锁
flow.stopped
由
stop_tty()
/start_tty()
停止/启动的ttyflow.tco_stopped
由
TCOOFF
/TCOON
ioctl 停止/启动的tty(它优先于 **flow.stopped**)ctrl
控制设置分组在一起
ctrl.pgrp
此tty的进程组(setpgrp(2))
ctrl.session
此tty的会话(setsid(2))。写入受 **ctrl.lock** 和 **legacy_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设备的持久性存储在此处作为 **port** 引用,并在 struct tty_port
中进行文档化。