tty 编程

tty 编程

经常使用 tty, 但是对于 tty 工作原理了解的真的是不足的.

  • ctrl-c 是怎么实现的, 谁把收到的按键变成了 signal, signal 发给谁了.
  • pty 的 master, slave 有什么区别
  • 标准输出与错误输出与 pty 的关系
  • ssh 协议加密之外做了什么, ssh 协议是怎么实现, 远程操作的
  • tty 的工作模式

以上这些问题现代的程序员了解的好像并不多. 因为这些都是基础的原理, 并且已经有大量的工具. 我们只是用就是了.

ctrl-c 是怎么变成 signal 的, 这个是一个根本性的问题, 也是 tty(pty) 所做的一个重要的工作.
我们知道, 我们可以使用 kill -int 发送这个信号. 但是 ctrl-c 是这个操作下, 是由谁送的信息呢? ctrl-c 到底是
一个什么特殊的操作呢? 其实 ctrl-c 就是一组输入, 键盘在收到用户的这个操作的时候, 产生的 ^C 输入, 这个输入
传递到了 pty 这个设备. 这个设备在检测到了 pty, 就会在内核里产生信号给下在使用的程序组.

我们可能知道 pty, 但是真的不是很了解这个pty. pty 创建之后会有两个 fd, 分别是 masterfd, slavefd.
masterfd 一般由父进程控制, 子进程使用 slavefd. 比如打开了个终端了, 终端这个程序会占用 masterfd, 终端程序会启动 bash,
bash 的标准输入, 标准输出, 错误输出其实都是这个 dup 自这个 fd. 或者说, 其实都是指向了打开的 pty.
这里的感觉, pty 和管道之类的很相似. 从 masterfd 写入, slavefd 可以读取, 从 slavefd 写入, masterfd 可以读取到.
但是 pty 还有一些特别的属性. 如窗口大小, 之类的.

masterfd 对于 tty 的拥有的权限也更大一些.
回到刚刚的问题, 我们现在知道了, 所有的输入都要经过 pty 这个设备, pty 在工作模式有很多, 一般情况下的经典模式下收到了 ^C
就会生成 int 信号, 并发送给使用 slavefd 的进程. 如果设置成 raw 模式, 那么就不会进行转换了.
后端的进程会直接收到了 ^C 这个字符串.

我们了解一下 ssh 登录的一个基本流程, 我们可以很好的理解, ssh 的工作原理还有 tty 的一些特性.
这里所说的流程, 其实并不是 ssh 特有的, ssh 的特点在于加密. 我们这里不谈这个.

我们打开一个终端, 这里会创建一个 pty, 我们在 bash 下启动了 ssh, ssh 就是一个占用了, 输入输出的普通程序.
他会通过网络连接到远程的机器的 sshd 服务. 这个服务会在运程机器上开启一个 pty, 并启动一个新的 bash 使用 pty.
我们在这边所有输入给本地 ssh 的输入, 都会被传发给远程的 sshd, sshd 再通过远程机器的 pty 写入到远程的 bash.

启动的过程中, 本地的 ssh 会设置本地 pty 的属性, 不对于 ^C 这样的字符进行传换, 而是直接收到 ^C, 然后转发给远程的 pty.

terminal ==> pty ==> ssh ---------- sshd => pty ==> bash

ssh 到 sshd 之类的协议还固定了, 比如窗口大小调整之类的事情, 来保持本地的 pty 与 远程的 pty 的窗口大小一样.

以上大概就是一个 ssh 的工作流程. 我们可以说, ssh + sshd 其实就是给了 bash 一个工作的环境, 然后通过网络,
把 bash 的输出给传递到本地, 再把输入传递进来.

了解了这些, 我们是不是就可以发现一些, 不容易的事情就变得容易了, 比如 ssh 的代理.

terminal ==> pty ==> ssh ---------- sshd => pty ==> kg
                                                       \
                                                         pty  ==> ssh ---------- sshd => pty ==> bash


发表评论

邮箱地址不会被公开。 必填项已用*标注