文章目录
CLI (命令行界面)GUI(图形用户界面)Terminal(终端)终端机字符终端 (Character Terminal)图形终端 (Graphical Terminal)Console (控制台)TTY 设备终端仿真器 (Terminal Emulator)虚拟控制台 (Virtual Console)伪终端(Pseudo Terminal)LINUX下的终端Shell程序猿都用过终端、Shell,并且经历越多会越来越发现他们的强大和无处不在。而很多小白和有工作经验但是半路出家的程序猿经常搞不清CLI、Shell、Console的概念,或者是会用但是不明所以。
作为一个专业的程序员,这些当然是不允许的。这篇文章是整理一下自己的一些理解,相关错误欢迎指正,希望能对新手有些帮助,一起进步。
CLI (命令行界面)
CLI 绝大多数人都见过了或者使用过了,比如Vue
、Flutter
的CLI,iOS开发使用的Command Line Tools
、Cocopods
,包括有些人可能用过的DOS操作系统MS-DOS
。
CLI是Command-Line Interface
的缩写,也就是命令行界面。
是在图形用户界面(GUI)
得到普及之前使用最为广泛的用户界面,它通常不支持鼠标,用户通过键盘输入指令,计算机接收到指令后,予以执行。也有人称之为字符用户界面(character user interface, CUI)
。
在GUI已经全面普及的今天,CLI不但没有被各种操作系统摒弃反而还在不断的加强和优化,主要是因为CLI仍然有丰富的应用场景和优势。
比GUI更快的操作速度。因为不需要处理图形和鼠标等交互,CLI更节省系统资源,在熟记命令的前提下操作速度比GUI要快很多。多用户登录。大家都知道Linux是多用户多任务操作系统,使用CLI就很方便,比如同时使用不同的用户分别查询日志、查询数据库、使用FTP上传文件。批量操作。如果你需要维护一群计算机,CLI当然是最佳选择;使用Windows的过程中很多人都遇到过批量命名文件之类的需求,而很多实现方案都是用Windows 命令提示符
也就是CLI操作。特定的设备和场景。不间断运行的服务器、交换机、路由器等电信设备,CLI往往更合适,运维工程师绝大多数时间都是使用Shell在工作。此外,像Vue、Flutter等开发框架和工具,专门开发一套GUI是耗时耗力、得不偿失的事情,CLI就更加快捷。
GUI(图形用户界面)
GUI 是Graphical User Interface
的缩写,也就是图形化用户界面。
GUI是采用图形方式显示的计算机操作用户界面,计算机画面上显示窗口、图标、按钮等图形,表示不同目的之动作,用户通过鼠标等指针设备进行选择。
与早期计算机使用的命令行界面相比,图形界面对于用户来说在视觉上更易于接受,学习成本大幅下降,也让电脑的大众化得以实现。
这里大家就比较熟悉了,不过目前处于垄断地位的Windows操作系统并不是最早商用的。
1973年第一个可视化操作的Alto电脑在施乐帕洛阿尔托研究中心(Xerox PARC)完成。Alto是第一个把计算机所有元素结合到一起的图形界面操作系统。它使用3键鼠标、位运算显示器、图形窗口、以太网络连接。1981年施乐公司推出推出世界上第一个商用的图形用户界面系统“Star 8010”工作站。1983年苹果电脑公司推出Apple Lisa个人电脑,搭载 Lisa OS,是全球第一款搭载图形用户界面(GUI)的个人电脑。不久,苹果电脑又推出第二个图形用户界面系统 System Software(现称 macOS)。1985年微软推出Windows 1.01。1986年首款用于Unix的窗口系统X Window System发布。1988年IBM发布OS/2 1.10标准版演示管理器(Presentation Manager),这是第一种支持Intel计算机的稳定的图形界面。1992年微软公司发布Windows 3.1,增加了多媒体支持。1995年微软的Windows 95发布,其窗口操作系统的外观基本定型。1997年苹果电脑公司发布Mac OS 8。2001年微软发布Windows XP。
Terminal(终端)
终端机
终端(Computer terminal),是一台电脑或者计算机系统用来让用户输入数据及显示其计算结果的机器,简而言之就是人类用户与计算机交互的设备。
它属于计算机的外设,是一种输入输出设备,本身并不提供运算处理功能。
在早期的大型机 (Mainframe) 和小型机 (Minicomputer) 的时期,计算机是非常庞大且昂贵的,且有散热和防尘需求,所以计算机和操作人员在不同的房间里,操作人员通过专门的设备–终端
来和计算机实现交互,所以也叫终端机
。
早期的终端是一种电传打字机(Teletype),它原本的用途是在电报线路上收发电报,但是它既有可以发送信号的键盘,又能把接收到的信号打印在纸带上,完全可以作为人机交互设备。
我们知道Unix是多用户系统,那么就要求每个用户都要配置自己的终端,而在当时的显示器和键盘都是在一起的,十分昂贵,于是Unix的创始人们找到了成本低廉的ASR-33 电传打字机
作为替代,就这样计算机历史上第一个真正的多用户操作系统 Unix出现,而电传打字机就成为了第一个 Unix 终端。
字符终端 (Character Terminal)
也叫文本终端 (Text Terminal)
,是只能接收和显示文本信息的终端。早期的终端全部是字符终端。
字符终端又分为哑终端 (Dumb Terminal)
和智能终端(Intelligent Terminal)
,后者可以理解转义序列、定位光标和显示位置,而哑终端不行。
最具代表性的是DEC公司在1978 年推出的的 VT100,由于其设计良好并且是第一批支持 ANSI 转义序列与光标控制的智能终端而成为史上最流行的字符终端。
图形终端 (Graphical Terminal)
随着显示技术的发展,图形终端也开始出现。图形终端不但可以接收和显示文本信息,也可以显示图形与图像。
具有代表性的图形终端有Tektronix 4010
系列。
但是随着显示器的普及,他们基本上已经被全功能显示器所取代,专门的图形终端已经极为少见。
Console (控制台)
这个名词就更加熟悉了,很多IDE包括Chrome等浏览器的开发工具中都有Console,主要是用来输出信息以及执行一些命令。
像数控机床、面粉机等一些数控设备的控制箱被称作控制台,而在计算机早期,控制台指的是直接连接在计算机上的一台输入输出设备(终端),通过它去控制、管理计算机。计算机启动的消息、内核消息、后台服务消息等都会显示到控制台上,而不会显示到其它用户的终端上。
虽然控制台也是终端,但它是计算机本身的基本设备,其它终端是附加的设备。一台计算机可以连接很多个终端,但只有一个控制台。
现在终端和控制台都由硬件概念,逐渐演化成了软件的概念。简单的说,能直接显示系统消息的那个终端称为控制台,其他的则称为终端。或者我们在平时的使用中压根就不区分 Linux 中的终端与控制台。
维基百科中,也有控制台(console)是命令行界面的别称
的定义。
TTY 设备
TTY是与终端相关的术语中最混乱的一个。TTY是teletype(电传打印机)
的缩写,我的理解是TTY设备是终端抽象层面的统称,包括虚拟控制台,串口以及伪终端设备。
TTY子系统
在早期终端设备都是TTY,Unix 系统为了支持这些电传打字机设计了名为 tty 的子系统,主要包括三部分:
UART 驱动
如上图所示,物理终端通过电缆连接到计算机上的 UART(通用异步接收器和发射器)。操作系统中有一个 UART 驱动程序用于管理字节的物理传输。
行规范
上图中内核中的 Line discipline(行规范)用来提供一个编辑缓冲区和一些基本的编辑命令(退格,清除单个单词,清除行,重新打印),主要用来支持用户在输入时的行为(比如输错了,需要退格)。
TTY 驱动
TTY 驱动用来进行会话管理,并且处理各种终端设备。
UART 驱动、行规范和 TTY 驱动都位于内核中,它们的一端是终端设备,另一端是用户进程,它们三个加在一起被称为 “TTY 设备”。在Unix 操作系统中Everything is a file
,这些具体的硬件设备被抽象为位于 /dev/tty* 的设备文件。
后来的终端演变成了键盘 + 显示器,但是 tty 这个名称还是留了下来,它们的概念也慢慢的混淆在了一起。
Everything is a file
是Unix的设计哲学,不太熟悉的可以参考这里。
个人理解其实就是面向对象的思想,万物皆对象,只不过在Unix中使用文件来描述抽象出来的对象。
终端仿真器 (Terminal Emulator)
终端仿真器 (Terminal Emulator)又或叫做虚拟终端、终端模拟器、软件仿真终端,其实就是模拟终端的软件。
随着技术发展,专门的终端硬件了逐渐被键盘与显示器所取代,但是我们又需要与那些传统的、不兼容图形接口的命令行程序(比如说 GNU 工具集里的大部分命令)交互,这些程序并不能直接读取我们的键盘输入,也没办法把计算结果显示在我们的显示器上,于是就有了模拟传统终端的软件–终端仿真器。
对于命令行 (CLI) 程序,终端仿真器会「假装」成一个传统终端设备;而对于现代的图形接口,终端模仿真器会「假装」成一个 GUI 程序。
终端仿真器的标准工作流程是:
捕获你的键盘输入;将输入发送给命令行程序(程序会认为这是从一个真正的终端设备输入的);拿到命令行程序的输出结果;调用图形接口输出结果渲染至显示器。
如上文所述,真正的终端设备已经不存在,我们现在所说的终端其实都是终端模拟器,几个经典的例子:
GNU/Linux:gnome-terminal、Konsole;
macOS:Terminal.app、iTerm2;
Windows:Win32 控制台、ConEmu 等。
虚拟控制台 (Virtual Console)
上面提到了终端设备时代有控制台和普通终端的区分,在终端仿真器完全取代了真实的终端设备的今天,也存在对应的虚拟控制台(Virtual Console)和伪终端(Pseudo Terminal)。
他们的主要区别是虚拟控制台存在于内核态,伪终端存在于用户态。
虚拟控制台由系统内核直接提供,所以即使在图形界面完全挂掉的情况下,只要系统本身还运行,仍然可以使用虚拟控制台进行操作和维护。
比如在Linux 操作系统中,Ctrl + Alt + F1–F6 组合键可以切换全屏终端界面,而Ctrl + Alt + F7 可以切换回图形界面。
伪终端(Pseudo Terminal)
为了便于将终端仿真移入用户空间,同时仍保持 TTY 子系统(指 TTY 驱动和行规范)的完整,伪终端被发明了出来(Pseudo Terminal 或 PTY)。
伪终端在内核中分为两部分,分别是 master side 和 在 TTY 驱动中实现的 slave side。上图中的 xterm 是一个运行在用户态的终端仿真程序。
在MacOS中我们可以很好的区分虚拟控制台和伪终端。
控制台
就属于虚拟控制台
。
而**终端
**是终端窗口 (Terminal Window)
,属于伪终端
。
LINUX下的终端
具体到Linux系统来看,设备文件分为两种:块设备文件(b)和字符设备文件©,一般存储在dev目录下。
控制终端(/dev/tty)
tty是表示当前进程的的tty设备,映射到实际的虚拟终端设备。如tty1、tty2等。
在命令行模式下,是映射到虚拟终端,tty1-tty6。
在图形界面下,会被映射到/dev/pts伪终端上。如/dev/pts/0、/dev/pts/1等。
它是动态的,不同的进程对应不同的tty文件,类似Object-C的 self。
当我们在终端中向/dev/tty
打印字符,会在当前的终端中显示出来
#echo "test" > /dev/ttytest
tty
命令,可以查看当前的控制台或虚拟终端,如果在图形界面下,查看到的会是伪终端设备。
控制台终端(/dev/console)
/dev/console即控制台,是与操作系统交互的设备,如主机本身的屏幕。系统会将错误信息和诊断信息等发送到该设备。
在Linux 系统中,计算机显示器通常被称为控制台终端 (Console)。
console只有一个,它是一个虚拟的tty,映射到真正的tty上。一般情况下 /dev/console 指向 /dev/tty0。
console和tty的区别:
console是个输出设备,功能很简单,只能在内核中访问;tty是字符设备,可以被用户程序访问。
虚拟终端(/dev/ttyn)
它仿真了类型为Linux的一种终端(TERM=Linux),并且有一些设备特殊文件与之相关联:tty0、tty1、tty2 等。
Linux中,虚拟终端有tty1-tty63,通过CTRL+ALT+【F1-F6】进行切换,六个快捷键组合默认对应tty1-tty6。
开始登陆时,默认登陆的是tty1。
/dev/tty0
tty0是当前虚拟终端(tty1-tty6)的别名,系统所产生的信息会发送到该终端上,因此不管当前正在使用哪个虚拟终端,系统信息都会发送到控制台终端上,在显示器上就可以看到不同虚拟终端的信息。
使用CTRL+ALT+F1切换到CLI模式,向/dev/tty0 输出字符,会打印到当前屏幕上
#echo "test" > /dev/tty0test
只有系统或超级用户root可以向/dev/tty0进行写操作。
tty、console、tty0的区别
个人理解,console是真实终端设备时期的控制台模拟,负责接收系统消息,
tty则在进程级别上映射不同类型的TTY设备,对不同的进程来说,其具体指向是不同的,可能是虚拟终端tty1-tty6,也可能是/dev/pts伪终端
tty0是在系统级别的指代,对应tty1-tty6,对所有进程,tty0 指向的都是当前的虚拟终端。
PC机: console->tty0->tty1~tty63
嵌入式: console->ttySx->串口设备
伪终端
伪终端是成对的逻辑终端设备(即master和slave设备, 对master的操作会反映到slave上),衍生出了 pty、ptmx、pts 等概念。
伪终端主要是用于网络登陆、xwindow窗口的管理等。
例如/dev/ptyp3和/dev/ttyp3(或者在设备文件系统中分别是/dev/pty/m3和 /dev/pty/s3)。它们与实际物理设备并不直接相关。如果一个程序把ptyp3(master设备)看作是一个串行端口设备,则它对该端口的读/ 写操作会反映在该逻辑终端设备对应的另一个ttyp3(slave设备)上面。而ttyp3则是另一个程序用于读写操作的逻辑设备。
串口设备(ttySn)
由于早期计算机上的 串行端口 (Serial Port) 最大的用途就是连接终端设备,所以当时的 Unix 会把串口上的设备也同样抽象为 tty 设备(位于 /dev/ttyS*)。因此,现在人们也经常将串口设备称呼为 tty 设备。
其它
Linux系统中还针对很多不同的字符设备存在有很多其它种类的终端设备特殊文件。例如针对ISDN设备的/dev/ttyIn终端设备等。
Shell
Shell提供了一个用户操作系统的入口。用户通过 Shell 去调用其他各种各样的应用程序,完成操作的执行。可以认为是 Shell 提供了与内核交互的用户界面。
Shell 的分类
Shell 通常可以分命令行 Shell 与 图形 Shell。
前者提供一个命令行界面 (CLI),后者提供一个图形用户界面 (GUI)。
Windows 下的 explorer.exe 就是一个典型的图形 Shell(因为它接受来自你的指令,并且会帮你与内核交互完成你的指令)。
常见或历史上知名的命令行 Shell:
Unix 系统:
sh (Bourne shell);
bash (Bourne-Again shell),目前绝大多数 Linux 发行版的默认 shell;
zsh (Z shell);
fish (Friendly interactive shell),专注于易用性与友好用户体验;
Windows 下的 cmd.exe (命令提示符) 与 PowerShell。
Shell 与终端的分工
终端负责是从用户这里接收输入(键盘、鼠标等输入设备),扔给 Shell,然后把 Shell 返回的结果展示给用户(比如通过显示器)。
而 Shell 负责从终端那里拿到用户输入的命令,解析后交给操作系统内核去执行,并把执行结果返回给终端。