N_TTY¶
默认(和回退)TTY 行规程。 它尝试按照 POSIX 的规定处理字符。
外部函数¶
-
void n_tty_inherit_ops(struct tty_ldisc_ops *ops)¶
继承 N_TTY 方法
参数
struct tty_ldisc_ops *ops
struct tty_ldisc_ops
在哪里保存 N_TTY 方法允许“子类”行规程“继承”N_TTY 方法。
内部函数¶
-
void n_tty_kick_worker(const struct tty_struct *tty)¶
启动输入工作进程(如果需要)
参数
const struct tty_struct *tty
终端
描述
如果翻转缓冲区工作可能已停止,则重新安排它。
- 锁定
调用者持有独占
termios_rwsem
,或者- n_tty_read()/消费者路径
持有非独占
termios_rwsem
-
void n_tty_write_wakeup(struct tty_struct *tty)¶
异步 I/O 通知器
参数
struct tty_struct *tty
tty 设备
描述
ptys、串行驱动等需要它。因为附加到主设备并依赖 ASYNC IO 的进程必须被唤醒。
-
void put_tty_queue(u8 c, struct n_tty_data *ldata)¶
将字符添加到 tty
参数
u8 c
字符
struct n_tty_data *ldata
n_tty 数据
描述
将字符添加到 tty read_buf 队列。
- 锁定
- n_tty_receive_buf()/生产者路径
调用者持有非独占
termios_rwsem
-
void reset_buffer_flags(struct n_tty_data *ldata)¶
重置缓冲区状态
参数
struct n_tty_data *ldata
要重置的行规程数据
描述
重置读取缓冲区计数器并清除标志。从 n_tty_open()
和 n_tty_flush_buffer()
调用。
- 锁定
调用者持有独占
termios_rwsem
,或者(不需要锁定)
-
void n_tty_flush_buffer(struct tty_struct *tty)¶
清除输入队列
参数
struct tty_struct *tty
终端设备
描述
刷新输入缓冲区。当 tty 层想要刷新缓冲区(例如在挂断时)或者 N_TTY
行规程内部必须清除挂起的队列(例如某些信号)时调用。
持有 termios_rwsem
以排除生产者/消费者,同时重置缓冲区索引。
锁定:ctrl
.lock,独占 termios_rwsem
-
int is_utf8_continuation(u8 c)¶
utf8 多字节检查
参数
u8 c
要检查的字节
返回值
如果 utf8 字符 c 是多字节延续字符,则为 true。 我们使用它来正确计算打印时字符的屏幕大小。
-
int is_continuation(u8 c, const struct tty_struct *tty)¶
多字节检查
参数
u8 c
要检查的字节
const struct tty_struct *tty
终端设备
返回值
如果 utf8 字符 c 是多字节延续字符并且终端处于 unicode 模式,则为 true。
-
int do_output_char(u8 c, struct tty_struct *tty, int space)¶
输出一个字符
参数
u8 c
字符(或部分 unicode 符号)
struct tty_struct *tty
终端设备
int space
tty 驱动程序写入缓冲区中的可用空间
描述
这是一个辅助函数,用于处理一个输出字符(包括 TAB、CR、LF 等特殊字符),进行 OPOST 处理并将结果放入 tty 驱动程序的写入缓冲区。
请注意,Linux 目前忽略 TABDLY、CRDLY、VTDLY、FFDLY 和 NLDLY。 它们在今天的世界中根本不相关。 如果您需要它们,请在此处添加它们。
锁定:应在 output_lock
下调用,以保护列状态和缓冲区中的剩余空间。
返回值
使用的缓冲区空间的字节数,如果剩余空间为 0,则为 -1。
-
int process_output(u8 c, struct tty_struct *tty)¶
输出后处理器
参数
u8 c
字符(或部分 unicode 符号)
struct tty_struct *tty
终端设备
描述
使用 OPOST 处理输出一个字符。
锁定:output_lock
用于保护列状态和剩余空间(此外,这是从 tty 层的写入锁下的 n_tty_write()
中调用的)。
返回值
当输出设备已满且必须重试字符时为 -1。
-
ssize_t process_output_block(struct tty_struct *tty, const u8 *buf, unsigned int nr)¶
块后处理器
参数
struct tty_struct *tty
终端设备
const u8 *buf
字符缓冲区
unsigned int nr
要输出的字节数
描述
使用 OPOST 处理输出一个字符块。
此路径用于加速块控制台写入,以及在处理块输出数据时。 它仅处理通常发现的简单情况,并有助于为控制台驱动程序生成符号块,从而提高性能。
锁定:output_lock
用于保护列状态和剩余空间(此外,这是从 tty 层的写入锁下的 n_tty_write()
中调用的)。
返回值
输出的字符数。
-
size_t __process_echoes(struct tty_struct *tty)¶
写入挂起的回显字符
参数
struct tty_struct *tty
终端设备
描述
将先前缓冲的回显(以及其他 ldisc 生成的)字符写入 tty。
由 ldisc 生成的字符(包括回显)需要缓冲,因为驱动程序的写入缓冲区在大量程序输出期间可能会被填满。 在这些条件下,直接回显到驱动程序通常会失败,导致字符丢失并导致 ldisc 状态信息不匹配。
由于 ldisc 状态必须表示写入时实际发送到驱动程序的字符,因此列状态中的某些更改等操作也会保存在缓冲区中并在此处执行。
使用循环 fifo 缓冲区,以便优先处理最近的字符。 此外,当使用带有前缀“^”的回显控制字符时,该对会被原子处理,因此不会分开。
锁定:调用者必须持有 output_lock
。
-
void add_echo_byte(u8 c, struct n_tty_data *ldata)¶
将字节添加到回显缓冲区
参数
u8 c
要回显的 unicode 字节
struct n_tty_data *ldata
n_tty 数据
描述
将字符或操作字节添加到回显缓冲区。
-
void echo_move_back_col(struct n_tty_data *ldata)¶
添加向后移动一列的操作
参数
struct n_tty_data *ldata
n_tty 数据
描述
添加一个操作到回显缓冲区,向后移动一列。
-
void echo_set_canon_col(struct n_tty_data *ldata)¶
添加一个操作来设置规范列
参数
struct n_tty_data *ldata
n_tty 数据
描述
添加一个操作到回显缓冲区,将规范列设置为当前列。
-
void echo_erase_tab(unsigned int num_chars, int after_tab, struct n_tty_data *ldata)¶
添加一个操作来擦除一个 tab
参数
unsigned int num_chars
已使用的字符列数
int after_tab
如果 num_chars 在先前的 tab 之后开始,则为 true
struct n_tty_data *ldata
n_tty 数据
描述
添加一个操作到回显缓冲区,以擦除一个 tab。
由橡皮擦函数调用,该函数知道自先前的 tab 或输入开始以来已使用了多少个字符列。 此信息稍后将与规范列(如果适用)一起使用,以返回正确的列数。
-
void echo_char_raw(u8 c, struct n_tty_data *ldata)¶
原始回显字符
参数
u8 c
要回显的 unicode 字节
struct n_tty_data *ldata
行规程数据
描述
将用户输入回显到屏幕上。 只有当 L_ECHO(tty) 为 true 时才能调用此函数。 从 tty_driver.receive_buf()
路径调用。
此变体不会特别处理控制字符。
-
void echo_char(u8 c, const struct tty_struct *tty)¶
回显一个字符
参数
u8 c
要回显的 unicode 字节
const struct tty_struct *tty
终端设备
描述
将用户输入回显到屏幕上。 只有当 L_ECHO(tty) 为 true 时才能调用此函数。 从 tty_driver.receive_buf()
路径调用。
此变体标记控制字符以回显为“^X”(其中 X 是表示控制字符的字母)。
-
void finish_erasing(struct n_tty_data *ldata)¶
完成擦除
参数
struct n_tty_data *ldata
n_tty 数据
-
void eraser(u8 c, const struct tty_struct *tty)¶
处理擦除功能
参数
u8 c
字符输入
const struct tty_struct *tty
终端设备
描述
当来自驱动程序层的流中存在擦除字符时,执行擦除和必要的输出。 处理 UTF-8 多字节符号的复杂性。
- 锁定:n_tty_receive_buf()/生产者路径
调用者持有非独占
termios_rwsem
-
void isig(int sig, struct tty_struct *tty)¶
处理 ISIG 选项
参数
int sig
信号
struct tty_struct *tty
终端
描述
当由于终端输入而发送信号时调用。 从 tty_driver.receive_buf()
路径调用,因此被序列化。
如果 !NOFLSH,则执行输入和输出刷新。 在这种情况下,回显缓冲区是“输出”。 首先处理信号,以提醒任何当前读者或作者停止并退出他们的 i/o 循环。
锁定:ctrl
.lock
-
void n_tty_receive_break(struct tty_struct *tty)¶
处理中断
参数
struct tty_struct *tty
终端
描述
在传入的比特流中点击了 RS232 中断事件。 根据 termios 设置,这可能会导致各种事件。
- 锁定:n_tty_receive_buf()/生产者路径
调用者持有非独占 termios_rwsem
注意
如果刷新输入缓冲区,则可能获得独占 termios_rwsem
-
void n_tty_receive_overrun(const struct tty_struct *tty)¶
处理溢出报告
参数
const struct tty_struct *tty
终端
描述
数据到达的速度比我们处理的速度快。 虽然 tty 驱动程序已标记此问题,但错过的位将永远消失。
从 receive_buf 路径调用,因此是单线程的。 不需要锁定,因为 num_overrun 和 overrun_time 是函数私有的。
-
void n_tty_receive_parity_error(const struct tty_struct *tty, u8 c)¶
错误通知器
参数
const struct tty_struct *tty
终端设备
u8 c
字符
描述
处理奇偶校验错误并排队正确的数据,以在必要时指示错误情况。
- 锁定:n_tty_receive_buf()/生产者路径
调用者持有非独占
termios_rwsem
-
bool n_tty_receive_char_flow_ctrl(struct tty_struct *tty, u8 c, bool lookahead_done)¶
接收流控制字符
参数
struct tty_struct *tty
终端设备
u8 c
字符
bool lookahead_done
前瞻已经处理了这个字符
描述
接收和处理流控制字符操作。
如果流控制字符的前瞻已经在正常接收之前提前处理了该字符,则在正常接收期间会跳过这些操作。
如果 c 作为流控制字符被消耗,则返回 true,该字符不能被视为正常字符。
-
void n_tty_receive_char(struct tty_struct *tty, u8 c)¶
执行处理
参数
struct tty_struct *tty
终端设备
u8 c
字符
描述
处理从驱动程序收到的输入的单个字符。 通过上述驱动程序的规则,这会相对于自身进行序列化。
- 锁定:n_tty_receive_buf()/生产者路径
调用者持有非独占
termios_rwsem
,如果规范模式处于活动状态,则发布 canon_head
-
size_t n_tty_receive_buf_common(struct tty_struct *tty, const u8 *cp, const u8 *fp, size_t count, bool flow)¶
处理输入
参数
struct tty_struct *tty
设备接收输入
const u8 *cp
输入字符
const u8 *fp
每个字符的标志(如果
NULL
,所有字符都是TTY_NORMAL
)size_t count
cp 中的输入字符数
bool flow
启用流量控制
描述
当收到字符块时,由终端驱动程序调用。 必须从软上下文中调用此函数,而不是从中断上下文中调用。 驱动程序负责一次一个地按顺序调用(或使用 flush_to_ldisc()
)。
在规范模式下,最大行长度为 4096 个字符(包括行终止字符); 长于 4096 个字符的行将被截断。 在 4095 个字符之后,输入数据仍然被处理但不存储。 溢出处理确保 tty 始终可以接收更多输入,直到至少可以读取一行。
在非规范模式下,读取缓冲区只会接受 4095 个字符; 如果输入模式切换到规范模式,这将为换行符提供必要的空间。
请注意,在非规范模式下,读取缓冲区可能会_包含_ 4096 个字符:当模式切换到非规范模式时,读取缓冲区可能已经包含规范行的大值 4096 个字符。
- 锁定:n_tty_receive_buf()/生产者路径
声明非独占
termios_rwsem
发布 commit_head 或 canon_head
返回值
处理的来自 cp 的输入字符数。
-
void n_tty_set_termios(struct tty_struct *tty, const struct ktermios *old)¶
termios 数据已更改
参数
struct tty_struct *tty
终端
const struct ktermios *old
先前的数据
描述
当用户更改 termios 标志时,tty 层会调用此函数,以便行规程可以提前计划。 此函数无法休眠,并且受 tty 层的保护,免于重新进入。 用户可以保证,当 ldisc 关闭时,此函数不会被重新进入或正在进行中。
锁定:调用者持有 tty->termios_rwsem
-
void n_tty_close(struct tty_struct *tty)¶
关闭此 tty 的 ldisc
参数
struct tty_struct *tty
设备
描述
当由于关闭或纪律变更而关闭此行规程时,从终端层调用。 当其他 ldisc 方法正在进行时,不会调用该函数。
-
int n_tty_open(struct tty_struct *tty)¶
打开 ldisc
参数
struct tty_struct *tty
要打开的终端
描述
当此行规程附加到终端设备时调用。 可以休眠。 串行调用,以便不会并行发生其他事件。 在关闭之前不会发生进一步的打开。
-
bool copy_from_read_buf(const struct tty_struct *tty, u8 **kbp, size_t *nr)¶
直接复制读取数据
参数
const struct tty_struct *tty
终端设备
u8 **kbp
数据
size_t *nr
数据大小
描述
辅助函数,用于加速 n_tty_read()
。仅当 ICANON
关闭时调用;它直接从 tty 队列复制字符。
- 锁定
在 ldata->atomic_read_lock sem 下调用
- n_tty_read()/消费者路径
调用者持有非独占的
termios_rwsem
;read_tail 已发布
返回值
如果成功复制了数据,但仍有更多数据可以获取,则为 true。
-
bool canon_copy_from_read_buf(const struct tty_struct *tty, u8 **kbp, size_t *nr)¶
以规范模式复制读取数据
参数
const struct tty_struct *tty
终端设备
u8 **kbp
数据
size_t *nr
数据大小
描述
用于 n_tty_read()
的辅助函数。仅当 ICANON
打开时调用;它将一行输入(包括行分隔符)复制到结果缓冲区中。
- 锁定
在
atomic_read_lock
互斥锁下调用- n_tty_read()/消费者路径
调用者持有非独占的
termios_rwsem
;read_tail 已发布
注意
当 termios 从非规范模式更改为规范模式并且读取缓冲区包含数据时,n_tty_set_termios()
模拟 EOF 推送(就像输入 C-d 一样),但缓冲区中 _没有_ DISABLED_CHAR
。这会导致已经作为输入处理的数据立即可用作输入,即使尚未收到换行符。
-
int job_control(struct tty_struct *tty, struct file *file)¶
检查作业控制
参数
struct tty_struct *tty
tty
struct file *file
文件句柄
描述
对此 file/tty 描述符执行作业控制管理检查,如果适用,则发送任何需要的信号,如果应该采取操作,则返回负错误代码。
- 锁定
重定向写入测试是安全的
current->signal->tty 检查是安全的
ctrl.lock 用于安全地引用 tty->ctrl.pgrp
-
ssize_t n_tty_read(struct tty_struct *tty, struct file *file, u8 *kbuf, size_t nr, void **cookie, unsigned long offset)¶
tty 的读取函数
参数
struct tty_struct *tty
tty 设备
struct file *file
文件对象
u8 *kbuf
内核空间缓冲区指针
size_t nr
I/O 大小
void **cookie
如果非
NULL
,则这是一个继续读取unsigned long offset
从哪里继续读取(在 n_tty 中未使用)
描述
执行线路规程的读取。我们保证线路规程不会在我们之下关闭,但我们可能会获得多个并行读取器,并且必须自己处理此问题。我们可能还会遇到挂断。始终在用户上下文中调用,可能会休眠。
此代码必须确保永远不会在挂断时休眠。
- 锁定:n_tty_read()/consumer 路径
声明非独占的 termios_rwsem;发布 read_tail
-
ssize_t n_tty_write(struct tty_struct *tty, struct file *file, const u8 *buf, size_t nr)¶
tty 的写入函数
参数
struct tty_struct *tty
tty 设备
struct file *file
文件对象
const u8 *buf
用户空间缓冲区指针
size_t nr
I/O 大小
描述
终端设备的写入函数。它与其他写入调用者串行化,但不与 termios 更改、读取和其他此类事件串行化。由于接收代码将回显字符,从而调用驱动程序的写入方法,因此 output_lock
在此处调用的输出处理函数以及回显处理函数中使用,以保护列状态和缓冲区中剩余的空间。
此代码必须确保永远不会在挂断时休眠。
- 锁定:output_lock 用于保护列状态和剩余空间
(请注意,process_output*() 函数本身会获取此锁)
-
__poll_t n_tty_poll(struct tty_struct *tty, struct file *file, poll_table *wait)¶
N_TTY 的 poll 方法
参数
struct tty_struct *tty
终端设备
struct file *file
访问它的文件
poll_table *wait
轮询表
描述
当要求线路规程对数据或特殊事件进行 poll() 时调用。此代码与其他事件(保存打开/关闭)串行化。
此代码必须确保永远不会在挂断时休眠。
锁定:在没有内核锁的情况下调用 -- 很好。