TTY 内部结构¶
Kopen¶
这些函数用于从内核空间打开 TTY
-
void tty_kclose(struct tty_struct *tty)¶
关闭由 tty_kopen 打开的 tty
参数
struct tty_struct *tty
tty 设备
描述
执行释放和释放 tty 设备的最后步骤。 它与 tty_release_struct()
相同,只是它还在 tty->port 上重置 TTY_PORT_KOPENED
标志。
-
struct tty_struct *tty_kopen_exclusive(dev_t device)¶
为内核打开 tty 设备
参数
dev_t device
要打开的设备的 dev_t
描述
专门为内核打开 tty。 执行驱动程序查找,确保它尚未打开并执行首次 tty 初始化。
- 声明全局
tty_mutex
以序列化 并发首次 tty 初始化
并发 tty 驱动程序删除与查找
并发从驱动程序表中删除 tty
返回值
锁定的初始化 tty_struct
为内核内共享使用打开 tty 设备
参数
dev_t device
要打开的设备的 dev_t
描述
为内核内使用打开一个已经存在的 tty。 与上面的 tty_kopen_exclusive()
相比,它不确保是唯一用户。
锁定:与上面的 tty_kopen() 相同。
导出的内部函数¶
-
int tty_dev_name_to_number(const char *name, dev_t *number)¶
返回设备名称的 dev_t
参数
const char *name
用户空间中 /dev 下的设备名称
dev_t *number
指向此函数将填充的 dev_t 的指针
描述
此函数将设备名称(如 ttyS0 或 ttyUSB1)转换为 dev_t(如 (4, 64) 或 (188, 1))。 如果未注册相应的驱动程序,则该函数返回 -ENODEV
。
- 锁定:这会获取 tty_mutex 以保护 tty_drivers 列表免受
在我们遍历它时被修改,并确保在退出前释放它。
-
void tty_release_struct(struct tty_struct *tty, int idx)¶
释放 tty 结构
-
int tty_get_icount(struct tty_struct *tty, struct serial_icounter_struct *icount)¶
获取 tty 统计信息
参数
struct tty_struct *tty
tty 设备
struct serial_icounter_struct *icount
输出参数
描述
获取 tty 的 icount 统计信息的副本。
锁定:无(取决于驱动程序)
内部函数¶
-
void free_tty_struct(struct tty_struct *tty)¶
释放不再使用的 tty
参数
struct tty_struct *tty
要释放的 tty 结构
描述
释放写入缓冲区、tty 队列和 tty 内存本身。
锁定:无。 必须在 tty 确定未使用后调用
参数
struct file *file
要释放 private_data 的
描述
这应仅用于故障路径处理,当 tty_add_file 尚未调用时。
-
struct tty_driver *get_tty_driver(dev_t device, int *index)¶
查找 tty 的设备
参数
dev_t device
设备标识符
int *index
返回 tty 的索引
描述
此例程返回 tty 驱动程序结构,给定设备编号,并传回索引号。
锁定:调用方必须持有 tty_mutex
-
struct file *tty_release_redirect(struct tty_struct *tty)¶
如果存在,则释放 pty 上的重定向
参数
struct tty_struct *tty
tty 设备
描述
这适用于 pty 代码,因此如果主设备关闭,如果从设备是重定向,则它可以释放重定向。
-
void __tty_hangup(struct tty_struct *tty, int exit_session)¶
挂断事件的实际处理程序
参数
struct tty_struct *tty
tty 设备
int exit_session
如果非零,则向所有前台组进程发送信号
描述
这可以由“kworker”内核线程调用。 这是进程同步的,但不持有任何锁,因此我们需要确保我们拥有执行操作的相应锁。
挂断事件会清除挂断设备上的任何挂起的重定向。 它确保未来的写入将出错,并且它执行所需的行规程挂断和信号传递。 tty 对象本身保持不变。
- 锁定
BTM
用于撤消重定向的重定向锁
用于操作 tty 列表的文件列表锁
来自调用函数的 tty_ldiscs_lock
termios_rwsem 重置 termios 数据
tasklist_lock 用于遍历挂断事件的任务列表
->siglock 用于保护 ->signal/->sighand
-
void tty_vhangup_self(void)¶
为自己的 ctty 执行进程 vhangup
参数
void
无参数
描述
对当前控制 tty 执行 vhangup
-
void tty_vhangup_session(struct tty_struct *tty)¶
挂断会话领导者退出
参数
struct tty_struct *tty
要挂断的 tty
描述
会话领导者正在退出并挂断其控制终端。 前台进程组中的每个进程都会收到 SIGHUP
信号。
我们同步地执行此操作,以便当系统调用返回时,该进程已完成。 出于安全原因,此保证是必要的。
-
ssize_t tty_read(struct kiocb *iocb, struct iov_iter *to)¶
tty 设备文件的读取方法
参数
struct kiocb *iocb
内核 I/O 控制块
struct iov_iter *to
读取数据的目标
描述
在此终端设备上执行读取系统调用函数。 在调用线路规程方法之前检查挂断的设备。
- 锁定
在需要时内部锁定线路规程。 多个读取调用可能会并行挂起。
-
void tty_write_message(struct tty_struct *tty, char *msg)¶
向某个 tty 写入消息,而不仅仅是控制台。
参数
struct tty_struct *tty
目标 tty_struct
char *msg
要写入的消息
描述
这用于需要重定向到特定 tty 的消息。 我们现在没有将其放入 syslog 队列,如果真的需要,可能会在将来放入。
目前我们仍然必须持有 BTM 并测试 CLOSING 标志。
此函数已弃用,请勿在新代码中使用。
-
ssize_t tty_write(struct kiocb *iocb, struct iov_iter *from)¶
tty 设备文件的写入方法
参数
struct kiocb *iocb
内核 I/O 控制块
struct iov_iter *from
带有要写入数据的 iov_iter
描述
通过线路规程将数据写入 tty 设备。
- 锁定
根据需要锁定线路规程。 对 tty 驱动程序的写入由 atomic_write_lock 序列化,然后以块的形式处理到设备。 对于每个设备,不会并行调用线路规程写入方法。
-
int tty_send_xchar(struct tty_struct *tty, u8 ch)¶
发送优先级字符
参数
struct tty_struct *tty
要发送到的 tty
u8 ch
要发送的 xchar
描述
即使已停止,也将高优先级字符发送到 tty。
锁定:xchar 方法没有锁定,write 方法有写入排序。
-
void pty_line_name(struct tty_driver *driver, int index, char *p)¶
生成 pty 的名称
参数
struct tty_driver *driver
使用的 tty 驱动程序
int index
次要数字
char *p
至少 6 个字节的输出缓冲区
描述
从 driver 引用生成一个名称并将其写入输出缓冲区 p。
锁定:无
-
ssize_t tty_line_name(struct tty_driver *driver, int index, char *p)¶
生成 tty 的名称
参数
struct tty_driver *driver
使用的 tty 驱动程序
int index
次要数字
char *p
至少 7 个字节的输出缓冲区
描述
从 driver 引用生成一个名称并将其写入输出缓冲区 p。
锁定:无
-
struct tty_struct *tty_driver_lookup_tty(struct tty_driver *driver, struct file *file, int idx)¶
查找现有的 tty(如果有)
参数
struct tty_driver *driver
tty 的驱动程序
struct file *file
文件对象
int idx
次要数字
返回值
tty(如果找到)。 如果未找到,则返回 NULL
或 ERR_PTR()
(如果驱动程序的 lookup() 方法返回错误)。
描述
锁定:必须持有 tty_mutex。 如果找到 tty,则增加 tty kref。
-
int tty_driver_install_tty(struct tty_driver *driver, struct tty_struct *tty)¶
在驱动程序中安装 tty 条目
参数
struct tty_driver *driver
tty 的驱动程序
struct tty_struct *tty
tty
描述
将 tty 对象安装到驱动程序表中。 tty->index 字段将在调用此方法时设置。 此方法负责确保分配和配置任何需要的其他结构。
锁定:目前为 tty_mutex
-
void tty_driver_remove_tty(struct tty_driver *driver, struct tty_struct *tty)¶
从驱动程序表中删除 tty
参数
struct tty_driver *driver
tty 的驱动程序
struct tty_struct *tty
要删除的 tty
描述
从驱动程序表中删除 tty 对象。 tty->index 字段将在调用此方法时设置。
锁定:目前为 tty_mutex
-
int tty_reopen(struct tty_struct *tty)¶
快速重新打开打开的 tty
参数
struct tty_struct *tty
要打开的 tty
描述
不允许在主 ptys 上重新打开,并返回 -EIO
。
锁定:调用方必须持有 tty_lock
返回值
成功时为 0,出错时为 -errno。
-
struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx)¶
初始化 tty 设备
参数
struct tty_driver *driver
我们正在打开设备的 tty 驱动程序
int idx
设备索引
描述
准备 tty 设备。 这可能不是“新的”干净设备,也可能是活动设备。 pty 驱动程序需要特殊处理,因为这一点。
- 锁定
该函数在 tty_mutex 下调用,这可以保护我们免受 tty 结构或驱动程序本身消失的影响。
在退出时,tty 设备已连接线路规程,引用计数为 1。 如果为 pty/tty 用途创建了一个对,而另一个是对 pty 主设备,则它也具有 1 的引用计数。
WSH 06/09/97:重写以消除竞争并在打开失败后正确清理。 新代码使用互斥锁保护打开操作,因此非常简单。 对于重新打开 tty 的(最常见)情况,可以放宽互斥锁锁定。
返回值
新的 tty 结构
-
void tty_flush_works(struct tty_struct *tty)¶
刷新 tty/pty 对的所有工作
参数
struct tty_struct *tty
要刷新工作的 tty 设备(或 pty 对的任何一端)
描述
同步刷新属于 tty(以及“另一个”tty)的所有工作。
-
void release_one_tty(struct work_struct *work)¶
释放 tty 结构内存
参数
struct work_struct *work
我们正在删除的 tty 的工作
描述
释放与 tty 结构关联的内存,并清除驱动程序表槽。 当设备不再使用时,会调用此函数。 当设备的设置失败时,也会调用此函数。
- 锁定
在处理驱动程序保留的 tty 列表时,会在内部获取文件列表锁。
此方法从工作队列中调用,以便驱动程序专用清理操作可以休眠(至少 USB 需要这样做)
-
void release_tty(struct tty_struct *tty, int idx)¶
释放 tty 结构内存
参数
struct tty_struct *tty
tty 设备释放
int idx
tty 设备的索引释放
描述
释放 tty 和可能的链接伙伴(考虑 pty 对),并减少后备模块的引用计数。
- 锁定
tty_mutex 在处理驱动程序保留的 tty 列表时,会在内部获取文件列表锁。
-
int tty_release_checks(struct tty_struct *tty, int idx)¶
在真正释放 tty 之前进行检查
参数
struct tty_struct *tty
要检查的 tty
int idx
tty 的索引
描述
在真正释放 tty 之前执行一些偏执检查。除非定义了 TTY_PARANOIA_CHECK
,否则这是一个空操作。
参数
struct inode *inode
tty 的 inode
struct file *filp
用于处理 tty 的文件指针
描述
每次关闭引用此 tty 的文件句柄时,都会最后一次调用此函数。但是,可能存在多个此类引用。
- 锁定
获取 BKL。请参阅 tty_release_dev()。
即使释放 tty 结构也是一件棘手的事情。我们必须非常小心,确保所有结构同时释放,否则中断可能会得到错误的指针。
WSH 09/09/97:重写以避免一些可能导致双重释放或释放仍在使用的内存的糟糕的竞争条件。
-
struct tty_struct *tty_open_current_tty(dev_t device, struct file *filp)¶
获取当前任务的锁定 tty
参数
dev_t device
设备号
struct file *filp
指向 tty 的文件指针
返回值
仅当 device 是 /dev/tty 时,当前任务的锁定 tty
描述
执行当前任务的控制 tty 的重新打开。
我们无法像其他节点一样返回驱动程序和索引,因为 devpts 将无法工作。它期望 inode 来自 devpts FS。
-
struct tty_driver *tty_lookup_driver(dev_t device, struct file *filp, int *index)¶
查找给定设备文件的 tty 驱动程序
参数
dev_t device
设备号
struct file *filp
指向 tty 的文件指针
int *index
return 驱动程序中设备的索引
描述
如果返回值没有错误,则调用者有责任通过 tty_driver_kref_put()
来减少引用计数。
锁定:tty_mutex
保护 get_tty_driver()
返回值
此 inode 的驱动程序(引用计数增加)
-
struct tty_struct *tty_open_by_driver(dev_t device, struct file *filp)¶
打开 tty 设备
参数
dev_t device
要打开的设备的 dev_t
struct file *filp
指向 tty 的文件指针
描述
执行驱动程序查找,检查重新打开,或者执行首次 tty 初始化。
- 声明全局 tty_mutex 进行序列化
并发首次 tty 初始化
并发 tty 驱动程序删除与查找
并发从驱动程序表中删除 tty
返回值
锁定初始化的或重新打开的 tty_struct
参数
struct inode *inode
设备文件的 inode
struct file *filp
指向 tty 的文件指针
描述
tty_open()
和 tty_release()
会保持 tty 计数,其中包含在 tty 上完成的打开次数。我们不能使用 inode 计数,因为不同的 inode 可能指向同一个 tty。
pty 主设备以及跟踪串行线路需要打开计数:当发生最后一次关闭时,DTR 会被丢弃。(现在不只是通过 tty->count 完成。 - Ted 1/27/92)
pty 的 termios 状态在第一次打开时被重置,以便设置不会跨重用而持续存在。
- 锁定
tty_mutex
保护 tty、tty_lookup_driver()
和tty_init_dev()
。tty->count 应该保护其余部分。
->siglock 保护 ->signal/->sighand
注意
由于 tty_mutex
,没有引用的 tty_unlock/lock 情况才是安全的
参数
struct file *filp
正在轮询的文件
poll_table *wait
要更新的轮询等待结构
描述
调用线路规程轮询方法以获取设备的轮询状态。
锁定:锁定的线路规程,但其他调用者可以自由地重新进入 ldisc 轮询方法。
-
int tiocsti(struct tty_struct *tty, u8 __user *p)¶
伪造输入字符
参数
struct tty_struct *tty
伪造输入到 tty 中
u8 __user *p
指向字符的指针
描述
伪造到 tty 设备的输入。执行必要的锁定和输入管理。
FIXME:不遵守流量控制?
- 锁定
调用的函数获取 tty_ldiscs_lock
current->signal->tty 检查在没有锁的情况下是安全的
-
int tiocgwinsz(struct tty_struct *tty, struct winsize __user *arg)¶
实现窗口查询 ioctl
参数
struct tty_struct *tty
tty
struct winsize __user *arg
用于结果的用户缓冲区
描述
将窗口大小的内核概念复制到用户缓冲区中。
锁定:获取 tty->winsize_mutex 以确保 winsize 数据的一致性。
-
int tiocswinsz(struct tty_struct *tty, struct winsize __user *arg)¶
实现窗口大小设置 ioctl
参数
struct tty_struct *tty
tty 侧的 tty
struct winsize __user *arg
用于结果的用户缓冲区
描述
将用户对窗口大小的看法复制到内核。传统上,这只是咨询信息,但对于 Linux 控制台,它实际上具有驱动程序级别的含义并触发 VC 大小调整。
- 锁定
与驱动程序相关。默认的 do_resize 方法采用 tty termios 互斥锁和 ctrl.lock。控制台获取自己的锁,然后调用默认方法。
参数
struct file *file
要成为控制台的文件
描述
允许管理员移动重定向的控制台设备。
锁定:使用 redirect_lock 来保护重定向信息
-
int tiocsetd(struct tty_struct *tty, int __user *p)¶
设置线路规程
参数
struct tty_struct *tty
tty 设备
int __user *p
指向用户数据的指针
描述
根据用户请求设置线路规程。
锁定:请参阅 tty_set_ldisc()
,此函数只是一个辅助函数
-
int tiocgetd(struct tty_struct *tty, int __user *p)¶
获取线路规程
参数
struct tty_struct *tty
tty 设备
int __user *p
指向用户数据的指针
描述
直接从 ldisc 中检索线路规程 ID。
锁定:等待 ldisc 引用(以防线路规程正在更改或 tty 正在挂断)
-
int send_break(struct tty_struct *tty, unsigned int duration)¶
执行的定时中断
参数
struct tty_struct *tty
要中断的设备
unsigned int duration
超时(毫秒)
描述
在缺乏自身驱动程序级别定时中断功能的硬件上执行定时中断。
- 锁定
tty->atomic_write_lock 序列化
-
int tty_tiocmget(struct tty_struct *tty, int __user *p)¶
获取调制解调器状态
参数
struct tty_struct *tty
tty 设备
int __user *p
指向结果的指针
描述
如果支持此功能,则从 tty 驱动程序获取调制解调器状态位。如果不可用,则返回 -ENOTTY
。
锁定:无(取决于驱动程序)
-
int tty_tiocmset(struct tty_struct *tty, unsigned int cmd, unsigned __user *p)¶
设置调制解调器状态
参数
struct tty_struct *tty
tty 设备
unsigned int cmd
命令 - 清除位、设置位或设置所有位
unsigned __user *p
指向所需位的指针
描述
如果支持此功能,则从 tty 驱动程序设置调制解调器状态位。如果不可用,则返回 -ENOTTY
。
锁定:无(取决于驱动程序)
-
struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx)¶
分配新的 tty
参数
struct tty_driver *driver
将处理返回的 tty 的驱动程序
int idx
tty 的次要设备号
描述
此子程序分配并初始化一个 tty 结构。
锁定:无 - 此刻不会公开相关 tty