LINUX教程:Linux 伪终端的基本原理 及其在远程登录(SSH,telne
《LINUX教程:Linux 伪终端的基本原理 及其在远程登录(SSH,telnet等)中的应用》要点: 本文介绍了Linux中伪终端的创建,介绍了终端的回显、行缓存、控制字符等特性,并在此基础上解释和模拟了telnet、SSH开启长途会话的过程. 轻量级远程登录之前制作的一块嵌入式板子,安装了嵌入式Linux操作系统,可以通过串口(Console)登录.为了方便使用,需要寻找通过网线远程登录的办法.最初的想法是SSH,不过板子的ROM太小,存不了体积庞大庞大的OpenSSH套装.后来换用了telnet,直接拿busybox的telnetd做服务器,效果很好. 后来有一天,发现了Linux中有一个直接建立TCP连接的工具:nc .在服务端使用 打开一个终端A,输入敕令
该命令将bash的标准输入输出与nc的标准输出输入连接起来,并由nc将其与socket连接起来.同时,nc监听2333端口(如果使用小于1024的端口,必要root权限),等待远程连接.现在打开另一个终端B,准备连接:
这时,在终端B中出现了sh的提示符.输入一般的shell命令后可以执行并得到结果.看来linux自带的工具已经灵活、强大到足够搭建一个小型的长途登录系统.这个过程可以使用下面的图来描述: 通过tty命令,我们看到,此时的shell并没有一个tty终端.确实,它的标准输入输出都是管道.这会带来一个问题,需要把持tty的一些命令,比如vi、less、sudo等都无法正常使用(可以动手试试效果怎么样).更为要命的是,在终端B中按下Ctrl+C这样的控制键,内核把结束信号发送给了客户端nc,而不是远程的程序! Ctrl+C直接杀死nc,结束了会话.对比telnet,我们的登录系统还缺少什么东西.这便是伪终端(pseudoterminal). 了解伪终端终端和它的作用终端(terminal)是用户拜访计算机主机的设备,可以理解为一个显示器和一个键盘的组合.
那终端有什么用呢?简单地说,无论是使用Ctrl+C、Ctrl+Z来终止、暂停前台任务,还是login、sudo的不显示暗码,都是终端的功劳.(事实上,终端和linux的进程管理密切相关.Shell的作业调度、前后台进程组都是在终端的配合下完成的) 伪终端的介绍通过 master端是更接近用户显示器、键盘的一端,slave端是在虚拟终端上运行的CLI(Command Line Interface,命令行接口)法式.Linux的伪终端驱动法式,会把“master端(如键盘)写入的数据”转发给slave端供法式输入,把“法式写入slave端的数据”转发给master端供(显示器驱动等)读取. 我们打开的“终端”桌面程序,其实是一种终端模拟器.当终端模拟器运行时,它通过 (终端模拟器的显示原理就不在这里展开了,这里认为键盘按键形成一列字撙节、向显示器输出字撙节后便打印到屏幕上) linux中为什么要提出伪终端这个概念呢?shell等命令行程序不可以直接从显示器和键盘读取数据吗?为了同屏运行多个终端模拟器、并实现远程登录,还真不能让bash直接跨过伪终端这一层.在操作系统的一大思想——虚拟化的指导下,为多个终端模拟器、远程用户分配多个虚拟的终端是有需要的.上图中的shell使用的slave端就是一个虚拟化的终端.master端是模拟用户一端的交互.之所以称为虚拟化的终端,它除了转发数据流外,还要有点终端的样子. 作为终端的伪终端最为一个虚拟的终端,每一个伪终端里面封装了一个终端驱动,让它能做到这些工作:
对,这些就是转发数据之外的控制. 终端的属性:回显控制和行控制当用户按下一个按键时,字符会呈现在屏幕上.这可不是CLI进程写回来的.不信的话可以在终端里运行 终端驱动里存储了一个状态——回显控制:是否将写入master的字符再次送回master的读端(显示器).默认情况下这个是启用的.在命令行里可以使用
则会关掉当前终端的回显.这时按下按键,已经没有字符显示出来了.输入 除了用户通过命令行方式,CLI的程序还能通过系统调用来设置终端的回显,比如 另外,终端驱动还提供有行缓冲功能.还是以 是谁阻止
这时,运行cat,尝试输入笔墨.每输入一个字符,能够立即返回一个字符.(把min改为time,还能设置输入字符最长1秒后阻塞) 这些终端的状态属性信息还有很多,好比设置终端的宽度、高度等.具体可以参考 特殊控制字符特殊控制字符,是指Ctrl和其他键的组合.如Ctrl+C、Ctrl+Z等等.用户按下这些按键,终端模拟器(键盘)会在master端写入一个字节.规则是:Ctrl+字母得到的字节是(大写)字母的ascii码减去0x40.好比Ctrl+C是0x03,Ctrl+Z是0x1A.参见下表: 驱动收到这些特殊字符,并不会像收到正常字节那样处理.在echo的时候,它返回两个可见字符.好比键入Ctrl+C(0x03),就会回显^和C(0x5E 0x03)两个字符.更重要的是,驱动将会拦截某些控制字符,他们不会被转发给slave端,而是触发作业控制(job control)的规则:向前台进程组发送SIGINT信号. 要想绕过这一机制,我们可以使用stty的一些设置.下面的命令能够同时关闭控制字符的特殊语义、设置行缓冲年夜小为1:
然后,运行 实验:利用伪终端实现远程登录理解伪终端的基来源根基理后,我们就可以尝试解释telnet和SSH等远程登录的原理了.每次用户通过客户端连接服务端的时候,服务端创建一个伪终端master、slave字符设备对,在slave端运行login程序,将master端的输入输出通过网络传送至客户端.至于客户端,则将从网络收到的信息直接关联到键盘/显示器上.我们将这个过程描述为下图: 说了这么多,其实这个布局相比本文第一张图而言,只多了一个伪终端.下面具体描述各部分的实现细节. 服务端②:创建伪终端,并将master重定向至nc依照
详细信息可以查阅 我们可以直接关闭( 此末节代码总结如下:
将文件保留后,打开一个终端(称为终端A),运行下列命令,在命令行中建立此程序与
至此,图中的②构建完毕,已经有一个nc在监听2333端口,它的输入输出通过管道送到ptmxtest法式中,ptmxtest又将这些信息搬运给master端. 在我的Ubuntu中运行命令后显示,创立的slave设备文件是/dev/pts/20. 服务端①:将login程序与终端关联起来在图中①处的地方,必要将login与伪终端的输入输出关联起来.这一点通过输入输出重定向即可完成.不过,想要实现Ctrl+C等作业控制,还必要更多的设置.这涉及到一些Linux的进程管理的知识(感兴趣的可以去搜索“进程、进程组、会话、控制终端”等关键字). 一个进程与终端的联系,不仅取决于它的输入输出,还有它的控制终端(Controlling terminal,可通过 设置控制终端必要使用终端设备的
比较重要的信息是,我们可以指定TIOCSCTTY参数来设置控制终端,但它要求调用者是没有控制终端的会话组长(Session leader).所以要先指定TIOCNOTTY参数来放弃当前控制终端,并用 我们将login包装一层,完成上面的操作,得到新的法式mylogin:
保留文件后,打开一个终端(称为终端B),编译运行:
该命令将实验图中①处的slave设备,重定向至mylogin的stdin、stdout和stderr.在程序执行时,会将控制终端设置为伪终端,然后执行login.至此,服务端全部建立完毕. 客户端:连接远程机器,配置当地终端客户端处于实验图的③处.打开新的终端(终端C),这里简单地使用nc连接远程socket,并且nc的输入输出重定向至键盘、显示器即可.但是要注意,nc是运行在终端C上的,而终端C的默认属性会拦截字符Ctrl+C、使用行缓冲区域.这样nc的输入输出其实并不直接是键盘、显示器.为此,我们先设置终端C的属性,再运行nc:
然后,在终端C中出现了我们打印的setsid的信息,和login的提示符.在终端C中,使用键盘可以正常登录,得到shell的提示符.使用 至此为止,我们实现了类似telnet的长途登录. 结语linux中终端驱动自己有回显、行缓存、作业控制等丰富的属性,在此基础上实现的伪终端在终端模拟器、远程登录等场合下能够得到多种应用. 在实验过程中也牵扯到进程控制、输入输出重定向、网络通信这么多的知识,更体现出linux的复杂精致的结构.我感觉,linux 就像一个包罗万象、又自成体统的小宇宙,它采用独特的虚拟化技术,灵活的模块化和重用机制,虚拟出各种设备,实现了驱动程序的随意拼插.在这里,所有模块都得到了充分的利用,并能够像变形金刚那样对各类需求提出面面俱到的办理方案. 本文永远更新链接地址: 欢迎参与《LINUX教程:Linux 伪终端的基本原理 及其在远程登录(SSH,telnet等)中的应用》讨论,分享您的想法,编程之家PHP学院为您提供专业教程。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |