>  기사  >  운영 및 유지보수  >  Linux TTY/PTS와 기능의 차이점에 대해 이야기해 보겠습니다.

Linux TTY/PTS와 기능의 차이점에 대해 이야기해 보겠습니다.

藏色散人
藏色散人앞으로
2021-09-19 17:00:183254검색

다음 리눅스 시스템 튜토리얼 칼럼에서는 Linux TTY/PTS와 그 기능의 차이점을 소개하겠습니다. 도움이 필요한 친구들에게 도움이 되길 바랍니다!

Linux TTY/PTS 개요

키보드로 문자를 입력하면 해당 프로세스로 어떻게 문자가 전송되나요? ps를 통해 tty1 및 pts/0과 같은 출력이 표시됩니다. who 및 기타 명령의 기능과 차이점은 무엇입니까?

TTY 역사

멀티태스킹을 지원하는 컴퓨터가 등장하기 전

컴퓨터가 나오기 전에 사람들은 이미 텔레타이프라는 장치를 사용하여 서로 정보를 전송하고 있었습니다.

+----------+     Physical Line     +----------+
| teletype |<--------------------->| teletype |
+----------+                       +----------+

두 개의 텔레타이프가 연결되어 있었습니다. 회선의 양쪽 끝에 모뎀과 유사한 장치가 있을 수도 있습니다(여기서는 무시됩니다). 텔레타이프의 한쪽 끝에서 키보드를 입력하면 해당 데이터가 텔레타이프의 다른 쪽 끝으로 전송됩니다. 특정 기능 그것이 무엇인지는 잘 모르겠습니다. (머릿속으로는 한쪽은 타자치고 한쪽은 인쇄된 그림인거 같아요)

오래된 골동품이고 제가 한번도 접해본적이 없어서 단순한 추측만 할 수 밖에 없네요.

멀티태스킹을 지원하는 컴퓨터 등장 이후

컴퓨터가 멀티태스킹을 지원한 이후 사람들은 이러한 텔레타이프를 컴퓨터의 단말처럼 컴퓨터에 연결해 컴퓨터를 조작할 수 있다는 생각을 하게 되었습니다.

텔레타이프를 사용하는 데에는 두 가지 주요 이유가 있습니다(개인 의견):

  • 실제로는 이미 다양한 제조업체에서 제공하는 수많은 텔레타이프가 있어 기존 리소스를 최대한 활용할 수 있습니다.

  • 관련 네트워크 텔레타이프는 상대적으로 성숙하고 연결이 편리함

그래서 연결은 다음과 같이 발전했습니다:

                                                                      +----------+ 
+----------+   +-------+     Physical Line     +-------+   +------+   |          |
| Terminal |<->| Modem |<--------------------->| Modem |<->| UART |<->| Computer |
+----------+   +-------+                       +-------+   +------+   |          |
                                                                      +----------+
  • 왼쪽에 있는 터미널은 다양한 텔레타이프

  • 모뎀은 물리적인 선의 양쪽에 사용됩니다. 우리가 흔히 "고양이"라고 부르는 것, 즉 네트워크가 점차 발전해왔기 때문에 모든 사람이 연결을 공유할 수 있다는 것입니다. (대략적인 추측일 수도 있음)

  • UART는 텔레타이프 신호를 컴퓨터가 인식할 수 있는 신호로 변환하는 장치로 이해될 수 있습니다.

Kernel TTY 하위 시스템

이러한 텔레타이프를 지원하기 위해 컴퓨터는 TTY라는 이름의 서브시스템의 내부 구조는 다음과 같습니다.

    +-----------------------------------------------+
    |                    Kernel                     |
    |                                 +--------+    |
    |   +--------+   +------------+   |        |    |       +----------------+
    |   |  UART  |   |    Line    |   |  TTY   |<---------->| User process A |
<------>|        |<->|            |<->|        |    |       +----------------+
    |   | driver |   | discipline |   | driver |<---------->| User process B |
    |   +--------+   +------------+   |        |    |       +----------------+
    |                                 +--------+    |
    |                                               |
    +-----------------------------------------------+
  • UART 드라이버는 외부 UART 장치에 연결됩니다.

  • 라인 규율은 주로 입력 및 출력의 일부 처리를 수행하는 부분이라고 이해할 수 있습니다. TTY 드라이버

  • TTY 드라이버 다양한 단말 장치를 처리하는 데 사용됩니다

  • 사용자 공간 프로세스는 TTY 드라이버를 통해 단말을 처리합니다.

간단함을 위해 UART 드라이버와 라인 규율은 사용하지 않습니다. 다음 소개에 별도로 나열되어 있습니다. TTY 드라이버

TTY 장치

의 일부로 간주될 수 있습니다. 각 터미널에 대해 TTY 드라이버는 해당 터미널에 해당하는 TTY 장치를 생성합니다. this:

                      +----------------+
                      |   TTY Driver   |
                      |                |
                      |   +-------+    |       +----------------+
 +------------+       |   |       |<---------->| User process A |
 | Terminal A |<--------->| ttyS0 |    |       +----------------+
 +------------+       |   |       |<---------->| User process B |
                      |   +-------+    |       +----------------+
                      |                |
                      |   +-------+    |       +----------------+
 +------------+       |   |       |<---------->| User process C |
 | Terminal B |<--------->| ttyS1 |    |       +----------------+
 +------------+       |   |       |<---------->| User process D |
                      |   +-------+    |       +----------------+
                      |                |
                      +----------------+

드라이버가 수신할 때 터미널이 연결되면 해당 터미널 모델과 매개변수에 따라 해당 tty 장치가 생성됩니다(대부분의 터미널 연결이 직렬 연결이기 때문에 위 그림의 장치 이름은 ttyS0이라고 합니다). 각 터미널은 다를 수 있으며 고유한 특수 명령과 사용 습관이 있으므로 각 tty 장치의 구성이 다를 수 있습니다. 예를 들어 삭제 키를 누르면 이전 문자가 삭제되는 경우도 있고 다음 문자가 삭제되는 경우도 있습니다. 구성이 올바르지 않으면 일부 키가 원하는 대로 작동하지 않을 수 있습니다. 이는 시뮬레이션된 터미널을 사용할 때도 마찬가지입니다. . 기본 구성이 습관과 일치하지 않는 경우 일부 개인화된 구성을 수행해야 합니다.

이후 컴퓨터의 지속적인 발전으로 인해 텔레타이프 장치는 더 이상 전문적인 터미널 장비가 필요하지 않으며 각 기계는 원격으로 다른 기계의 터미널이 될 수 있습니다. ssh이지만 커널 TTY 드라이버 아키텍처는 변경되지 않았습니다. I/O를 위해 시스템의 프로세스와 상호 작용하려면 여전히 TTY 장치를 사용해야 하므로 다양한 터미널 시뮬레이션 소프트웨어가 등장했으며 시뮬레이션도 여러 가지입니다. VT100, VT220, XTerm 등과 같은 공통 터미널

  1. toe -a 명령을 사용하여 시스템에서 지원하는 모든 터미널 유형을 나열할 수 있습니다. toe -a列出系统支持的所有终端类型

  2. 可以通过命令infocmp来比较两个终端的区别,比如infocmp vt100 vt220

infocmp 명령을 사용하여 toe -a와 같은 두 터미널 간의 차이점을 비교할 수 있습니다. code>infocmp vt100 vt220는 vt100과 vt220의 차이를 출력합니다.

프로그램이 TTY를 처리하는 방법

TTY 장치가 생성 및 구성되는 방법을 논의하기 전에 먼저 프로세스에서 TTY가 사용되는 방법을 살펴보겠습니다.

#先用tty命令看看当前bash关联到了哪个tty
dev@debian:~$ tty
/dev/pts/1

#看tty都被哪些进程打开了
dev@debian:~$ lsof /dev/pts/1
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
bash     907  dev    0u   CHR  136,1      0t0    4 /dev/pts/1
bash     907  dev    1u   CHR  136,1      0t0    4 /dev/pts/1
bash     907  dev    2u   CHR  136,1      0t0    4 /dev/pts/1
bash     907  dev  255u   CHR  136,1      0t0    4 /dev/pts/1
lsof    1118  dev    0u   CHR  136,1      0t0    4 /dev/pts/1
lsof    1118  dev    1u   CHR  136,1      0t0    4 /dev/pts/1
lsof    1118  dev    2u   CHR  136,1      0t0    4 /dev/pts/1

#往tty里面直接写数据跟写标准输出是一样的效果
dev@dev:~$ echo aaa > /dev/pts/2
aaa

pts도 tty 장치이며 이들의 관계는 뒤에 있습니다.

위의 lsof를 보면 현재 실행 중인 bash 및 lsof 프로세스의 stdin(0u), stdout(1u), stderr(2u)이 모두 이 TTY에 바인딩되어 있음을 알 수 있습니다.
  • 다음은 tty와 프로세스 및 I/O 장치 간의 상호 작용에 대한 구조적 다이어그램입니다.

       Input    +--------------------------+    R/W     +------+
    ----------->|                          |<---------->| bash |
                |          pts/1           |            +------+
    <-----------|                          |<---------->| lsof |
       Output   | Foreground process group |    R/W     +------+
                +--------------------------+
    🎜🎜 tty를 파이프로 이해할 수 있고 한쪽 끝에 작성된 내용을 다른 쪽 끝에서 읽을 수 있으며 그 반대도 마찬가지입니다. 그 반대. 🎜
  • 这里input和output可以简单的理解为键盘和显示器,后面会介绍在各种情况下input/ouput都连接的什么东西。

  • tty里面有一个很重要的属性,叫Foreground process group,记录了当前前端的进程组是哪一个。process group的概念会在下一篇文章中介绍,这里可以简单的认为process group里面只有一个进程。

  • 当pts/1收到input的输入后,会检查当前前端进程组是哪一个,然后将输入放到进程组的leader的输入缓存中,这样相应的leader进程就可以通过read函数得到用户的输入

  • 当前端进程组里面的进程往tty设备上写数据时,tty就会将数据输出到output设备上

  • 当在shell中执行不同的命令时,前端进程组在不断的变化,而这种变化会由shell负责更新到tty设备中

从上面可以看出,进程和tty打交道很简单,只要保证后台进程不要读写tty就可以了,即写后台程序时,要将stdin/stdout/stderr重定向到其它地方(当然deamon程序还需要做很多其它处理)。

先抛出两个问题(后面有答案):

  • 当非前端进程组里面的进程(后台进程)往tty设备上写数据时,会发生什么?会输出到outpu上吗?

  • 当非前端进程组里面的进程(后台进程)从tty设备上读数据时,会发生什么?进程会阻塞吗?

TTY是如何被创建的

下面介绍几种常见的情况下tty设备是如何创建的,以及input和output设备都是啥。

键盘显示器直连(终端)

先看图再说话:

                   +-----------------------------------------+
                   |          Kernel                         |
                   |                           +--------+    |       +----------------+ 
 +----------+      |   +-------------------+   |  tty1  |<---------->| User processes |
 | Keyboard |--------->|                   |   +--------+    |       +----------------+
 +----------+      |   | Terminal Emulator |<->|  tty2  |<---------->| User processes |
 | Monitor  |<---------|                   |   +--------+    |       +----------------+
 +----------+      |   +-------------------+   |  tty3  |<---------->| User processes |
                   |                           +--------+    |       +----------------+
                   |                                         |
                   +-----------------------------------------+

键盘、显示器都和内核中的终端模拟器相连,由模拟器决定创建多少tty,比如你在键盘上输入ctrl+alt+F1时,模拟器首先捕获到该输入,然后激活tty1,这样键盘的输入会转发到tty1,而tty1的输出会转发到显示器,同理用输入ctrl+alt+F2,就会切换到tty2。

当模拟器激活tty时如果发现没有进程与之关联,意味着这是第一次打开该tty,于是会启动配置好的进程并和该tty绑定,一般该进程就是负责login的进程。

当切换到tty2后,tty1里面的输出会输出到哪里呢?tty1的输出还是会输出给模拟器,模拟器里会有每个tty的缓存,不过由于模拟器的缓存空间有限,所以下次切回tty1的时候,只能看到最新的输出,以前的输出已经不在了。

不确定这里的终端模拟器对应内核中具体的哪个模块,但肯定有这么个东西存在

SSH远程访问

 +----------+       +------------+
 | Keyboard |------>|            |
 +----------+       |  Terminal  |
 | Monitor  |<------|            |
 +----------+       +------------+
                          |
                          |  ssh protocol
                          |
                          ↓
                    +------------+
                    |            |
                    | ssh server |--------------------------+
                    |            |           fork           |
                    +------------+                          |
                        |   ↑                               |
                        |   |                               |
                  write |   | read                          |
                        |   |                               |
                  +-----|---|-------------------+           |
                  |     |   |                   |           ↓
                  |     ↓   |      +-------+    |       +-------+
                  |   +--------+   | pts/0 |<---------->| shell |
                  |   |        |   +-------+    |       +-------+
                  |   |  ptmx  |<->| pts/1 |<---------->| shell |
                  |   |        |   +-------+    |       +-------+
                  |   +--------+   | pts/2 |<---------->| shell |
                  |                +-------+    |       +-------+
                  |    Kernel                   |
                  +-----------------------------+

这里的Terminal可能是任何地方的程序,比如windows上的putty,所以不讨论客户端的Terminal程序是怎么和键盘、显示器交互的。由于Terminal要和ssh服务器打交道,所以肯定要实现ssh的客户端功能。

这里将建立连接和收发数据分两条线路解释,为了描述简洁,这里以sshd代替ssh服务器程序:

建立连接

  • 1.Terminal请求和sshd建立连接

  • 2.如果验证通过,sshd将创建一个新的session

  • 3.调用API(posix_openpt())请求ptmx创建一个pts,创建成功后,sshd将得到和ptmx关联的fd,并将该fd和session关联起来。

#pty(pseudo terminal device)由两部分构成,ptmx是master端,pts是slave端,
#进程可以通过调用API请求ptmx创建一个pts,然后将会得到连接到ptmx的读写fd和一个新创建的pts,
#ptmx在内部会维护该fd和pts的对应关系,随后往这个fd的读写会被ptmx转发到对应的pts。

#这里可以看到sshd已经打开了/dev/ptmx
dev@debian:~$ sudo lsof /dev/ptmx
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
sshd    1191  dev    8u   CHR    5,2      0t0 6531 /dev/ptmx
sshd    1191  dev   10u   CHR    5,2      0t0 6531 /dev/ptmx
sshd    1191  dev   11u   CHR    5,2      0t0 6531 /dev/ptmx
  • 4.同时sshd创建shell进程,将新创建的pts和shell绑定

收发消息

  • 1.Terminal收到键盘的输入,Terminal通过ssh协议将数据发往sshd

  • 2.sshd收到客户端的数据后,根据它自己管理的session,找到该客户端对应的关联到ptmx上的fd

  • 3.往找到的fd上写入客户端发过来的数据

  • 4.ptmx收到数据后,根据fd找到对应的pts(该对应关系由ptmx自动维护),将数据包转发给对应的pts

  • 5.pts收到数据包后,检查绑定到自己上面的当前前端进程组,将数据包发给该进程组的leader

  • 6.由于pts上只有shell,所以shell的read函数就收到了该数据包

  • 7.shell对收到的数据包进行处理,然后输出处理结果(也可能没有输出)

  • 8.shell通过write函数将结果写入pts

  • 9.pts将结果转发给ptmx

  • 10.ptmx根据pts找到对应的fd,往该fd写入结果

  • 11.sshd收到该fd的结果后,找到对应的session,然后将结果发给对应的客户端

键盘显示器直连(图形界面)

 +----------+       +------------+
 | Keyboard |------>|            |
 +----------+       |  Terminal  |--------------------------+
 | Monitor  |<------|            |           fork           |
 +----------+       +------------+                          |
                        |   ↑                               |
                        |   |                               |
                  write |   | read                          |
                        |   |                               |
                  +-----|---|-------------------+           |
                  |     |   |                   |           ↓
                  |     ↓   |      +-------+    |       +-------+
                  |   +--------+   | pts/0 |<---------->| shell |
                  |   |        |   +-------+    |       +-------+
                  |   |  ptmx  |<->| pts/1 |<---------->| shell |
                  |   |        |   +-------+    |       +-------+
                  |   +--------+   | pts/2 |<---------->| shell |
                  |                +-------+    |       +-------+
                  |    Kernel                   |
                  +-----------------------------+

为了简化起见,本篇不讨论Linux下图形界面里Terminal程序是怎么和键盘、显示器交互的。

这里和上面的不同点就是,这里的Terminal不需要实现ssh客户端,但需要把ssh服务器要干的活也干了(当然ssh通信相关的除外)。

SSH + Screen/Tmux

常用Linux的同学应该对screen和tmux不陌生,通过它们启动的进程,就算网络断开了,也不会受到影响继续执行,下次连上去时还能看到进程的所有输出,还能继续接着干活。

这里以tmux为例介绍其原理:

 +----------+       +------------+
 | Keyboard |------>|            |
 +----------+       |  Terminal  |
 | Monitor  |<------|            |
 +----------+       +------------+
                          |
                          |  ssh protocol
                          |
                          ↓
                    +------------+
                    |            |
                    | ssh server |--------------------------+
                    |            |           fork           |
                    +------------+                          |
                        |   ↑                               |
                        |   |                               |
                  write |   | read                          |
                        |   |                               |
                  +-----|---|-------------------+           |
                  |     ↓   |                   |           ↓
                  |   +--------+   +-------+    |       +-------+  fork   +-------------+
                  |   |  ptmx  |<->| pts/0 |<---------->| shell |-------->| tmux client |
                  |   +--------+   +-------+    |       +-------+         +-------------+
                  |   |        |                |                               ↑
                  |   +--------+   +-------+    |       +-------+               |
                  |   |  ptmx  |<->| pts/2 |<---------->| shell |               |
                  |   +--------+   +-------+    |       +-------+               |
                  |     ↑   |  Kernel           |           ↑                   |
                  +-----|---|-------------------+           |                   |
                        |   |                               |                   |
                        |w/r|   +---------------------------+                   |
                        |   |   |            fork                               |
                        |   ↓   |                                               |
                    +-------------+                                             |
                    |             |                                             |
                    | tmux server |<--------------------------------------------+
                    |             |
                    +-------------+

系统中的ptmx只有一个,上图中画出来了两个,目的是为了表明tmux服务器和sshd都用ptmx,但它们之间又互不干涉。

这种情况要稍微复杂一点,不过原理都是一样的,前半部分和普通ssh的方式是一样的,只是pts/0关联的前端进程不是shell了,而是变成了tmux客户端,所以ssh客户端发过来的数据包都会被tmux客户端收到,然后由tmux客户端转发给tmux服务器,而tmux服务器干的活和ssh的类似,也是维护一堆的session,为每个session创建一个pts,然后将tmux客户端发过来的数据转发给相应的pts。

由于tmux服务器只和tmux客户端打交道,和sshd没有关系,当终端和sshd的连接断开时,虽然pts/0会被关闭,和它相关的shell和tmux客户端也将被kill掉,但不会影响tmux服务器,当下次再用tmux客户端连上tmux服务器时,看到的还是上次的内容。

TTY和PTS的区别

从上面的流程中应该可以看出来了,对用户空间的程序来说,他们没有区别,都是一样的;从内核里面来看,pts的另一端连接的是ptmx,而tty的另一端连接的是内核的终端模拟器,ptmx和终端模拟器都只是负责维护会话和转发数据包;再看看ptmx和内核终端模拟器的另一端,ptmx的另一端连接的是用户空间的应用程序,如sshd、tmux等,而内核终端模拟器的另一端连接的是具体的硬件,如键盘和显示器。

常见的TTY配置

先先来看看当前tty的所有配置:

dev@dev:~$ stty -a
speed 38400 baud; rows 51; columns 204; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = M-^?; eol2 = M-^?; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; discard = ^O; min = 1; time = 0;
-parenb -parodd -cmspar cs8 -hupcl -cstopb cread -clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc ixany imaxbel -iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke -flusho -extproc

stty还可以用来修改tty的参数,用法请参考man stty

只要是有权限的程序,都可以通过Linux提供的API来修改TTY的配置,下面介绍一些常见的的配置项。

rows 51; columns 204;

这个配置一般由终端控制,当终端的窗口大小发生变化时,需要通过一定的手段修改该配置,比如ssh协议里面就有修改窗口大小的参数,sshd收到客户端的请求后,会通过API修改tty的这个参数,然后由tty通过信号SIGWINCH通知前端程序(比如shell或者vim),前端程序收到信号后,再去读tty的这个参数,然后就知道如何调整自己的输出排版了。

intr = ^C

tty除了在终端和前端进程之间转发数据之外,还支持很多控制命令,比如终端输入了CTRL+C,那么tty不会将该输入串转发给前端进程,而是将它转换成信号SIGINT发送给前端进程。这个就是用来配置控制命令对应的输入组合的,比如我们可以配置“intr = ^E”表示用CTRL+E代替CTRL+C。

start = ^Q; stop = ^S;

这是两个特殊的控制命令,估计经常有人会碰到,在键盘上不小心输入CTRL+S后,终端没反应了,即没输出,也不响应任何输入。这是因为这个命令会告诉TTY暂停,阻塞所有读写操作,即不转发任何数据,只有按了CTRL+Q后,才会继续。这个功能应该是历史遗留,以前终端和服务器之间没有流量控制功能,所以有可能服务器发送数据过快,导致终端处理不过来,于是需要这样一个命令告诉服务器不要再发了,等终端处理完了后在通知服务器继续。

该命令现在比较常用的一个场景就是用tail -f命令监控日志文件的内容时,可以随时按CTRL+S让屏幕停止刷新,看完后再按CTRL+Q让它继续刷,如果不这样的话,需要先CTRL+C退出,看完后在重新运行tail -f命令。

echo

在终端输入字符的时候,之所以我们能及时看到我们输入的字符,那是因为TTY在收到终端发过去的字符后,会先将字符原路返回一份,然后才交给前端进程处理,这样终端就能及时的显示输入的字符。echo就是用来控制该功能的配置项,如果是-echo的话表示disable echo功能。

-tostop

如果你在shell中运行程序的时候,后面添加了&,比如./myapp &,这样myapp这个进程就会在后台运行,但如果这个进程继续往tty上写数据呢?这个参数就用来控制是否将输出转发给终端,也即结果会不会在终端显示,这里“-tostop”表示会输出到终端,如果配置为“tostop”的话,将不输出到终端,并且tty会发送信号SIGTTOU给myapp,该信号的默认行为是将暂停myapp的执行。

TTY 관련 신호

위 구성 소개에서 언급한 SIGINT, SIGTTOU, SIGWINCHU 외에도 여러 TTY 관련 신호가 있습니다

SIGTTIN

백그라운드 프로세스가 tty를 읽을 때 tty는 다음으로 신호를 보냅니다. 해당 프로세스 그룹의 경우 기본 동작은 프로세스 그룹의 프로세스 실행을 일시 중지하는 것입니다. 일시 중지된 프로세스를 계속 실행하는 방법은 무엇입니까? 다음 글의 SIGCONT를 참고하세요.

SIGHUP

예를 들어 ssh 세션의 연결이 끊어져 tty의 다른 쪽 끝이 중단되면 sshd가 ptmx와 연결된 fd를 닫으면 커널은 tty와 관련된 모든 프로세스에 SIGHUP 신호를 보내고 프로세스는 수신 이 신호를 받은 후의 기본 동작은 프로세스를 종료하는 것입니다.

SIGTSTP

터미널이 CTRL+Z를 누르면 tty는 SIGTSTP를 수신한 후 프런트엔드 프로세스 그룹으로 보냅니다. 기본 동작은 프런트엔드 프로세스 그룹을 백엔드에 넣고 모든 실행을 일시 중지하는 것입니다. 프로세스 그룹의 프로세스.

tty와 관련된 신호를 캡처하고 기본 동작을 수정할 수 있습니다

결론

이 글에서는 tty id, process와 밀접하게 관련된 프로세스 세션을 자세히 소개하겠습니다. 그룹, 직업, 후배 프로그램 등 많은 관심 부탁드립니다.

관련 추천: "linux 비디오 튜토리얼"

위 내용은 Linux TTY/PTS와 기능의 차이점에 대해 이야기해 보겠습니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 segmentfault.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제