博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
linux一切皆文件之tty字符设备(深入理解sshd创建pty的过程) (五)
阅读量:5992 次
发布时间:2019-06-20

本文共 5810 字,大约阅读时间需要 19 分钟。

一、知识准备

1、在linux中,一切皆为文件,所有不同种类的类型都被抽象成文件(比如:块设备,socket套接字,pipe队列)

2、操作这些不同的类型就像操作文件一样,比如增删改查等
3、块设备支持随机访问,而字符设备只能依据先后顺序来读取数据。最典型的字符设备就是tty

二、环境准备

组件 版本
OS CentOS Linux release 7.5.1804

三、什么是tty?

根据史料记载:

An ASR33 Teletype - origin of the abbreviation tty.

tty来源一种电传打印机(teletype),就像这样:

1416773-20181127094129107-1200079520.jpg

● 敲击键盘输入不同的字符,然后由打印机将字符打印在纸上

● 历史不断在往前发展,出现了计算机之后,计算机模拟了teletype的模式:通过外部终端输入,将输入的字符打印在屏幕上
● 在teletype与计算机之间用串口相连,并且在计算机上通过信号转换(模拟信号转换为数字信号),让计算机能够识别,从而操作计算机
● 由于计算机厂商众多,每个厂商都有自己风格的输入设备,所以计算机为了兼容这些设备,开发了内核tty模块

+-----------------+                           |                 |+--------+                 | +-------------+ ||teletype|-----------------> |serial       | |+--------+                 | |communication| |                           | +-----+-------+ |                           |       |         |                           |       v         |                           |  +----------+   |        +----------+                           |  |tty driver|   |------->| display  |                           |  +----------+   |        +----------+                           |                 |                           |computer         |                           +-----------------+

四、tty设备文件

登陆到操作系统(不使用SSH协议,而使用控制台直接登陆),首先查看当前进程号所使用的tty

[root@localhost ~]# tty/dev/tty1[root@localhost ~]# ls -l /dev/tty1crw--w---- 1 root tty 4, 1 Nov 20 23:24 /dev/tty1

当前所使用的是/dev/tty1,并且tty1也分配了主设备号与次设备号(关于主设备号与次设备号,请看之前的文章:块设备文件)

查看进程打开的描述符

[root@localhost ~]# echo $$5598[root@localhost ~]# ls -l /proc/5598/fdtotal 0lrwx------ 1 root root 64 Nov 19 22:23 0 -> /dev/tty1lrwx------ 1 root root 64 Nov 19 22:23 1 -> /dev/tty1lrwx------ 1 root root 64 Nov 19 22:23 2 -> /dev/tty1lrwx------ 1 root root 64 Nov 19 22:23 255 -> /dev/tty1

进程打开了4个文件描述符,这四个文件描述符都是/dev/tty1,他们的作用分别是:

0:标准输入
1:标准输出
2:标准错误
255:这个比较特殊,主要用于当tty重置的时候对0,1,2的一份复制(个人观点是对tty之前的历史信息作为一份复制)

更多的信息,请拜读大神的书《Shell Scripting: Expert Recipes for Linux, Bash, and more》,这里是链接(大概在267页):

五、ssh登陆之后的tty

刚才介绍的都是操作系统提供的控制台登陆之后的情况,如果用ssh服务登陆之后会产生什么情况呢?

首先介绍一个非常重要的概念,伪终端pty:

● pty是一对虚拟的字符设备,提供双向通信。pty一般由master与slave组成
● pty的出现是为了满足现在的登陆需求:网络登陆(ssh登陆、telnet登陆等)、Xwindow等
● 历史上有两套接口标准:分别是BSD与unix98,当前大多数pts都是基于unix98标准来实现的
● unix98的工作流程:
(1)进程对/dev/ptmx调用open(),返回pseudoterminal master(PTM)的文件描述符,并且在/dev/pts下创建pseudoterminal slave(PTS): /dev/pts/0
(2)调用grantpt()修改PTS的文件权限;调用unlockpt()对PTS解锁;最后调用slavename()得到PTS文件名字
(3)此时,PTM与PTS都已经正常打开,并且建立一条通道,两端分别连接PTM与PTS
(4)进程对PTM写的数据可以从PTS读出来,反之亦然

下面重点介绍一下基于unix98实现的sshd pty(主要分为登陆阶段和执行命令阶段):

登陆:

(1)当进程ssh client请求与sshd建立登陆连接的时候,经过TCP握手以及tls握手之后,确认是一个合法的请求,sshd会fork()一个子进程出来专门服务于这条连接

[root@localhost ~]# ps -ef | grep sshdroot       894     1  0 Nov25 ?        00:00:00 /usr/sbin/sshd -Droot      3126   894  0 Nov25 ?        00:00:00 sshd: root@pts/0

(2)子进程3126/dev/ptmx调用open(),得到PTM的文件描述符以及PTS的文件名

#这里使用strace跟踪sshd主进程和它创建的子进程,然后打开另外一个shell登陆服务器[root@localhost ~]# strace -p 894 -ff -o sshdstrace: Process 894 attachedstrace: Process 3126 attachedstrace: Process 3127 attachedstrace: Process 3128 attachedstrace: Process 3129 attachedstrace: Process 3130 attachedstrace: Process 3131 attachedstrace: Process 3132 attachedstrace: Process 3133 attachedstrace: Process 3134 attachedstrace: Process 3135 attachedstrace: Process 3136 attachedstrace: Process 3137 attachedstrace: Process 3138 attachedstrace: Process 3139 attachedstrace: Process 3140 attached[root@localhost ~]# grep ptmx ./sshd.*./sshd.3126:open("/dev/ptmx", O_RDWR)               = 8

sshd894创建了一个子进程3126用来处理这条TCP连接。进程对/dev/ptmx调用open(),得到PTM的文件描述符8

(2)子进程3126/dev/pts下创建了一个字符设备文件/dev/pts/08/dev/pts/0成为一对master/slave

(3)子进程3126会再fork()一个子进程3128,子进程3128打开/dev/pts/0 3个描述符(标准输入,标准输出,标准错误),并且执行操作系统默认的shell(本文中bash)

[root@localhost ~]# ps -ef | grep 3126root      3126   894  0 03:16 ?        00:00:00 sshd: root@pts/0root      3128  3126  0 03:16 pts/3    00:00:00 -bash[root@localhost ~]# ls -l /proc/3128/fdtotal 0lrwx------ 1 root root 64 Nov 26 03:16 0 -> /dev/pts/0lrwx------ 1 root root 64 Nov 26 03:16 1 -> /dev/pts/0lrwx------ 1 root root 64 Nov 26 03:16 2 -> /dev/pts/0lrwx------ 1 root root 64 Nov 26 03:22 255 -> /dev/pts/0

至此,通信流程大概是这样:

+----------------++------------+           |                || ssh client +---------->|      sshd      |+----+-------+           |                |     |                   +--------+-------+     |                            |     |                            |     |                         fork()     |                            |     |                            |     |                            v     |                       +----+-----+     fork()    +----------+      +-----+     +---------------------->|pid: 3126 |-------------->|pid: 3128 |----->|bash |                             +-+--------+               +----------+      +-----+                               |                              ^                               |                              |                       +-------+                              |                +------|--------------------------------+     |                |      |                 +-----------+  |     |                |      v                 |           |  |     |                |  +---------+    fd=8   +-----------+  |     |                |  |/dev/ptmx|---------->|/dev/pts/0 |--------+                |  +---------+           +-----------+  |                |                        |           |  |                |                        +-----------+  |                +---------------------------------------+

执行命令:

(4)当ssh client发出一个ls命令,通过TCP连接来到31263126ls写入PTM文件描述符8

(5)/dev/ptmx查询到关联记录 PTM:8对应PTS:/dev/pts/0,把ls转发到/dev/pts/0当中
(6)31280 -> /dev/pts/0中读取之后执行ls
(7)ls返回结果之后写入1 -> /dev/pts/0,然后根据关联记录回写到/dev/ptmx
(8)3126/dev/ptmx读取之后返回到ssh client

六、参考资料


至此,本文结束

在下才疏学浅,有撒汤漏水的,请各位不吝赐教...

转载于:https://www.cnblogs.com/MrVolleyball/p/10024540.html

你可能感兴趣的文章
mybatis添加记录时返回主键id
查看>>
Python 学习笔记 -- 继承与多态(入门级实例)
查看>>
HTML, CSS. JS的各种奇淫技巧
查看>>
leetcode442
查看>>
MySQL性能优化之参数配置
查看>>
Windows 7下Eclipse搭建Android开发环境
查看>>
mysqldump备份单表数据
查看>>
.bat 脚本
查看>>
hive 面试题
查看>>
Linux基础命令的操作(时间与日期,日历,计算器)
查看>>
Hyperledger子项目
查看>>
autofac文档:服务类型,名称和键
查看>>
Android IOS WebRTC 音视频开发总结(二三)-- hurtc使用说明
查看>>
c3p0数据库连接池+mysql数据库基本使用方法
查看>>
provides you GHD hair straighteners with a slight scalp massage
查看>>
Windows Azure Camp---漫步云端,创意无限
查看>>
hadoop 1.2.1 安装步骤 伪分布式
查看>>
位运算的应用和实例
查看>>
js 标准对象
查看>>
HRBUST 2072 树上求最大异或路径值
查看>>