• 终端设备 tty,pty,pts 概念与文件描述符的联系


    1节 理解终端设备ttyptypts概念

    理解终端设备tty、pty、pts概念

    简要描述:

    • 终端设备默认具有输入、输出功能。
    • 现代我们最常用的接入服务器端的方式(如:ssh通过tcp/ip的方式连接服务器端,作为服务器的终端设备)为服务的接入方式。
    • 但服务器端默认的连接终端为tty模式,(是以串口设备的接入方式,如我们的键盘、显示器),服务器默认提供tty1...tty6共6个终端接口,用Ctrl+Alt+F1...F6切换。
    • 所以在ssh通过tcp/ip连接服务器端的时候,服务器系统会将该服务转换为ptmx设备形态(可以理解为硬件链路)接入服务器端。
    • 同时将该ssh服务fork的子进程转换为pts设备(可以理解为输入输出设备),再用PTY驱动将两个设备绑定起来。  

    第2节 终端设备与文件描述符fd(file description)及重定向的关系

    计算机3个组件 与文件描述 文件描述的数字表示 对应文件
    存储器 磁盘相关 3 ~ 65535 (终端设备执行)程序所打开磁盘上的文件
    输入设备 相关 0(符号:<或0<) /dev/stdin
    输出设备 相关 1(符号:>或1>) /dev/stdout
      错误报告 2(符号:2>) /dev/stderr

    简要描述:

    1. Linux中一切皆文件,所有的存在都以文件的形式展示出来,文件描述符专用于描述系统调用文件使用情况,为每个打开的文件都打上标识且占用一个文件描述符。
    2. 终端设备与文件描述符及重定向[ >,< ](注意不是追加重定向)不是单独存在,而是相辅相成。  
    3. 重定向主要的作用是数据源流从一个设备流向另一个设备中。(磁盘上的所有类型文件,在概念上都属于设备文件,因为文件都是保存在磁盘中,对文件的操作,其本质上就是对磁盘操作)。
    4. 终端设备一般含有计算机的3大部件中的输入设备和输出设备(这与计算机发展历史相关,输入设备可以是键盘或其他能输出数据的设备,输出设备可以是显示器或其他能接收数据的设备)。
    5. 每个终端设备接入Linux系统,系统为该终端的输入功能绑定为0的文件描述符,输出功能绑定为1的文件描述符,在处理终端设备发送过来的指令出现错误时,错误提示绑定为2的文件描述符。

    第3节 终端设备与文件描述符及重定向的默认行为

    3.1 终端设备与文件描述符及重定向的默认行为

      默认情况下:系统会帮用户默认补全输入及输出的重定向路径。所以一般情况下,手工写上重定向时,就是修改系统默认的输入与输出的路径。

    比如:

      cat jeson.sh   # 等效 cat 0< jeson.sh 1> /dev/pts/0

      处理方法   输入设备负责为处理的方法提供数据源    处理完的结果交给输出设备(由输出设备将数据输出)
    用户输入 cat     jeson.sh      
    系统自动补全 cat 0 < jeson.sh 1 > /dev/pts/0
       

    输入设备

    可理解cpu获取数据入口

       数据源设备  发送设备

    可理解cpu输出数据的出口

       接收设备

      磁盘上的所有类型文件,在概念上都属于设备文件,因为文件都是保存在磁盘中,对文件的操作,其本质上就是对磁盘操作。磁盘属于存储设备。 

    3.2 描述符与重定向;将数据重定向相应的设备中

    pts/0  将echo输出的数据,定位到/dev/tty1 的输出设备

    tty1  显示pts/0输入的数据

    [jeson@mage-jump-01 ~/]# who
    root     tty1         2018-10-02 17:57
    jeson    pts/0        2018-10-02 20:12 (10.0.0.1)
    [root@mage-jump-01 ~/]#ll /dev/fd/  # 查看自身的登录终端
    总用量 0
    lrwx------ 1 root root 64 10月  2 20:16 0 -> /dev/pts/0
    lrwx------ 1 root root 64 10月  2 20:16 1 -> /dev/pts/0
    lrwx------ 1 root root 64 10月  2 20:16 2 -> /dev/pts/0
    lr-x------ 1 root root 64 10月  2 20:16 3 -> /proc/19301/fd
    [root@mage-jump-01 ~/]# echo "how are you today?" >/dev/tty1
    [jeson@mage-jump-01 ~/]# who
    root     tty1         2018-10-02 17:57
    jeson    pts/0        2018-10-02 20:12 (10.0.0.1)
    [root@mage-jump-01 ~/]#ll /dev/fd/  # 查看自身的登录终端
    total 0
    lrwx------ 1 root root 64 Oct  2 20:21 0 -> /dev/tty1
    l-wx------ 1 root root 64 Oct  2 20:21 1 -> /root/test.txt
    lrwx------ 1 root root 64 Oct  2 20:21 2 -> /dev/tty1
    lr-x------ 1 root root 64 Oct  2 20:21 3 -> /proc/19376/fd
    [root@mage-jump-01 ~/]#how are you today?

     pts/0和tty1 终端登录后的PID号

    [jeson@mage-jump-01 ~/]$ps aux|egrep "[p]ts|tty"
    USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
    root      18588  0.0  0.3 116624  3408 tty1     Ss+  18:06   0:01 -bash
    jeson     19491  0.0  0.2 156676  2328 ?        S    20:32   0:00 sshd: jeson@pts/0
    jeson     19492  0.0  0.3 116616  3232 pts/0    Ss   20:32   0:00 -bash
    jeson     19648  0.0  0.1 155324  1864 pts/0    R+   20:36   0:00 ps aux
    jeson     19649  0.0  0.0 112720   992 pts/0    S+   20:36   0:00 grep -E --color=auto [p]ts|tty

    只要有PID号,/proc就会为其pid建立一个目录,该目录放该pid相关的数据文件

    [jeson@mage-jump-01 ~/]$ls /proc/ | grep -E '[1-9]+' | column
    1       17      19491   221     242     27      30      492     501     665
    10      18      19492   222     243     270     342     493     502     7
    11      18024   19636   224     263     271     365     494     503     743
    1164    18588   19668   229     264     272     38      495     505     8
    1166    18891   19669   231     265     273     40      496     57      88
    13      19      19670   233     266     274     41      497     650     9
    14      19398   2       236     267     28      42      498     651
    15      19413   20      237     268     29      44      499     653
    16      19489   21      239     269     3       476     5       658

    3.3 终端设备接入系统,系统为终端设备设置对应文件描述符的操作方式(0,1,2)

    系统为每一个接入终端都配备默认的文件描述符
    [jeson@mage-jump-01 ~/]$ll /dev/std*
    lrwxrwxrwx 1 root root 15 10月  1 18:38 /dev/stderr -> /proc/self/fd/2
    lrwxrwxrwx 1 root root 15 10月  1 18:38 /dev/stdin -> /proc/self/fd/0
    lrwxrwxrwx 1 root root 15 10月  1 18:38 /dev/stdout -> /proc/self/fd/1 
    系统为pts/0接入终端默认绑定的文件描述符操作
    [jeson@mage-jump-01 ~/]$ll /proc/self/fd
    总用量 0
    lrwx------ 1 jeson jeson 64 10月  2 21:12 0 -> /dev/pts/0  # stdin与pts/0远程终端关联
    lrwx------ 1 jeson jeson 64 10月  2 21:12 1 -> /dev/pts/0  # stdout与pts/0远程终端关联
    lrwx------ 1 jeson jeson 64 10月  2 21:12 2 -> /dev/pts/0  # stderr与pts/0远程终端关联
    lr-x------ 1 jeson jeson 64 10月  2 21:12 3 -> /proc/19778/fd 
    得出系统设备、特殊文件描述符、终端的链接关系为
    /dev/stderr   ->  /proc/self/fd/2  -> /dev/pts/0
    /dev/stdin    ->  /proc/self/fd/0  -> /dev/pts/0
    /dev/stdout   ->  /proc/self/fd/1  -> /dev/pts/0 

    3.4 打开文件描述符

    1. 打开文件描述符有程序自动指定和人为手动指定编号两种方式
    2. 程序在打开文件描述符的时候,有三种可能的行为:从描述符中读、向描述符中写、可读也可写。
    3. 从lsof的FD列可以看出程序打开这个文件是为了从中读数据,还是向其中写数据,亦或是既读又写。

      例如:以下实例就是打开文件从中读、写、读写数据的(3r的r是read,w是write,u是read and write)。    

    窗口1

    窗口2 

    程序自动指定编号 人为手动指定编号
     只读模式;命令行执行如下命令 
    [jeson@mage-jump-01 ~/]$lsof -n | grep 'read.txt'|column -t
      tail  2135  jeson  3r  REG  8,2  0  41054766  /home/jeson/read.txt 
    tail -f read.txt exec 3<read.txt
    只写模式;命令行执行如下命令
    [jeson@mage-jump-01 ~/]$lsof -n | grep 'write.txt'|column -t
      cat  2099  jeson  1w或3w  REG  8,2  0  41054756  /home/jeson/write.txt  
    cat > write.txt exec 3>read.txt
    可读可写模式;命令行执行如下命令
    [jeson@mage-jump-01 ~/]$lsof -n | grep 'read_write.txt'|column -t
      vim  2197  jeson  4u  REG  8,2  12288  41054769  /home/jeson/.read_write.txt.sap
    vim read_write.txt exec 4<>read.txt

     3.5 复制、关闭文件描述符

      文件描述符的复制(duplicate),文件描述符的复制表示当前操作的文件描述符被(作用或者理解为移动)到另一个文件描述符中。

      [n]>&digit- :将文件描述符digit代表的输出文件移动到n上,并关闭digit值的描述符。

      [n]<&digit- :将文件描述符digit代表的输入文件移动到n上,并关闭digit值的描述符。

      [n]<&- :直接关闭n描述符。

    实例 1:

    [jeson@mage-jump-01 ~/]$lsof -n | grep "read.txt" | column -t
    bash    19492  jeson  3r  REG  8,2  0  41054753  /home/jeson/read.txt
    [jeson@mage-jump-01 ~/]$exec 4<&3- 
    [jeson@mage-jump-01 ~/]$lsof -n | grep "read.txt" | column -t
    bash    19492  jeson  4r  REG  8,2  0  41054753  /home/jeson/read.txt 
    [jeson@mage-jump-01 ~/]$exec 4<&-
    [jeson@mage-jump-01 ~/]$lsof -n | grep "read.txt" | column -t
    [jeson@mage-jump-01 ~/]$

    可见:fd=3移动到fd=4后,原本与fd=3关联的read.txt已经关闭,并且关联到fd=4上; 最后把fd=4直接关掉了。

    实例 2:

    [jeson@mage-jump-01 ~/]$echo "I am a boy"
    I am a boy
    [jeson@mage-jump-01 ~/]$echo "I am a boy" >/dev/null 2>&1
    [jeson@mage-jump-01 ~/]$ 

    画图说明:

    第4节 文件描述符的高阶使用 

    案例 1 :

    [jeson@mage-jump-01 ~/]$echo "123456" >jeson.sh
    [jeson@mage-jump-01 ~/]$exec 5<>jeson.sh 
    [jeson@mage-jump-01 ~/]$read -n 3 <&5
    [jeson@mage-jump-01 ~/]$echo $REPLY
        123
    [jeson@mage-jump-01 ~/]$echo -n "+" >&5
    [jeson@mage-jump-01 ~/]$exec 3>&-
    [jeson@mage-jump-01 ~/]$cat jeson.sh 
        123+56 

      简要描述:

      打开文件 jeson.sh 以read/write方式,并分配fd=5给该文件进程。
      这时fd=0已经绑定到fd=5上,而fd=5的重定向目标为jeson.sh,所以fd=0的目标也是jeson.sh,即从jeson.sh中读取数据。这里read命令读取3个字符,由于read命令中没有指定变量,因此分配给默认变量REPLY。注意,这个命令执行结束后,fd=0的重定向目标会变回/dev/stdin。
        这时fd=1也已经绑定到fd=5上,而fd=5的重定向目标文件为jeson.sh,所以fd=1的目标也是jeson.sh文件,即数据写入到jeson.sh中。这里写入一个+号。注意,这个命令结束后,fd=1的重定向目标回变回/dev/stdout。
        关闭fd=5,这也会关闭其指向的文件jeson.sh,关闭文件操作进程。

    案例 2 :

    [jeson@mage-jump-01 ~/]$exec 6>&1
    [jeson@mage-jump-01 ~/]$exec > jeson.sh
    [jeson@mage-jump-01 ~/]$echo "I am a boy"
    [jeson@mage-jump-01 ~/]$exec 1>&6-
    [jeson@mage-jump-01 ~/]$cat jeson.sh 
      I am a boy

       简要描述:

    1. 打开文件描述符进程fd=6,并指向1对应的/dev/stdout。
    2. 打开文件描述符fd=1进程指向jeson.sh文件。
    3. 输入的数据,定位到描述符fd=1进程,1进程对应jeson.sh文件。
  • 相关阅读:
    Kafka写入流程和副本策略
    Kafka消费分组和分区分配策略
    Kafka安装和常用操作命令
    面试:谈谈你对大数据的理解
    HDFS写数据和读数据流程
    java笔记之分支、循环语句
    java笔记之分支、循环语句
    java笔记之运算符
    java笔记之运算符
    java笔记之java内存结构
  • 原文地址:https://www.cnblogs.com/jeson-lbb/p/9724710.html
Copyright © 2020-2023  润新知