64.Linux/Unix 系统编程手册(下) -- 伪终端

1.概述
	伪终端是一个虚拟设备,它提供了一个 IPC 通道。通道的一端是一个期望连接到终端设备的程序。通道的另一端也是一个程序,这个程序通过
  IPC 通道来发送其输入并读取输出以此来驱动面向终端的程序。

    通过网络通信,套接字提供了解决这个问题的驱动部分。但是,我们无法直接面向终端程序的标准输入,输出和错误信息连接到套接字上。这是因为
  面向终端程序期望连接的是一个终端---以此才能执行第34章和62章的操作。这样的操作包括将终端置为非规范程序,将回显打开或关闭,以及设定终端
  前台进程组。如果某个程序尝试在一个套接字上执行这样的操作,那么相关的系统调用将失败。
    此外,面向终端的程序期望终端驱动程序对其输入和输出做特定类型的处理。举个例子,在规范模式下,当终端驱动程序在一行的开始处发现文件结尾(ctrl+D),
  将导致下一次 read() 调用不会返回任何数据。
    最后,面向终端的程序必须有一个控制终端。这样允许程序通过打开 /dev/tty 来获取一个控制终端的文件描述符,并且也使得产生针对该程序的作业控制和
  相关的信号成为可能。

  伪终端主从设备:
  	伪终端提供了网络连接和面向终端程序之间那缺失的一环。伪终端是一对互联的虚拟设备:主伪终端和从伪终端,有时被共称为伪终端对。伪终端对提供了一条
  IPC 通道,这有点像双向管道---两个进程能分别打开主端和从端,并通过伪终端双向传输数据。
    关于伪终端,关键点在于从设备表现的像一个标准终端一样。所以施加于终端设备的操作同样也可以施加于伪终端从设备上。这里面有些操作对伪终端来说没有
  什么意义(例如,设定终端的线速什么的),但这并无大碍,因为伪终端从设备会悄悄忽略它。

  如何使用伪终端:
  	pty 是伪终端的常用缩写形式。面向终端的程序的标准输入,输出以及错误都连接到伪终端从设备上,它也是程序的控制终端。在伪终端的另一侧,驱动程序作为
  用户的代理,提供面向终端程序的输入并读取程序的输出。
    通常驱动程序同时读取输入并将输出写入到另外一个IO通道中。它的行为像一个中继,在伪终端和另外一个程序间双向传递数据。为了实现这一点,驱动程序必须
  同时监控2个方向上的输入。这通常由IO多路复用来实现,也可以采用一对进程或线程在两个方向上传递数据。
    一般情况下使用伪终端的应用进程会按照如下步骤来做:
    	1.驱动程序打开伪终端主设备
    	2.驱动程序调用 fork() 创建一个子进程。子进程执行如下操作:
    		a)调用 setsid() 来启动一个新的会话,使该子进程称为会话的头领进程。该操作也使得子进程失去它的控制终端。
    		b)打开同伪终端主设备相对应的从设备。由于子进程是会话的头领进程,且没有控制终端,伪终端从设备就变成了子进程的控制终端。
    		c)调用 dup() 为从设备复制标准输入,输出,错误的文件描述符
    		d)调用 exec() 启动要连接到伪终端从设备的面向终端程序

    此时这2个程序就可以通过伪终端进行通信了。任何由驱动程序写到主设备的信息,都会在从设备这端作为面向终端程序的输入。任何由面向终端的程序写到从设备的信息,
  都可以在主设备由驱动程序读取。

    伪终端也可以能够用来连接任意的进程对(即,不一定是父子进程)。所有要做的就是打开伪终端主设备的进程需要将相关联的从设备名称通知给另一个进程即可,可能是
  将名称写到一个文件上又或者是通过其他 IPC 机制来传递。

    ssh 机制:
    	在远端主机上,伪终端主设备的驱动程序 ssh 服务器(sshd),连接到伪终端从设备的面向终端的程序是 登录 shell。ssh 服务器作为胶水,通过连接到 ssh 客户端
    的套接字将伪终端连接起来。一旦所有登录方面的细节全部完成,ssh 服务器和客户端的主要用途就是在本地主机上的用户终端和远端主机的 shell 之间双向传递字符。

    伪终端的应用:
    	1.expect
    	2.xterm
    	3.screen
    	4.script
    	5.当向文件或者管道写输出时,有时候可以用伪终端绕过由 stdio 实现的默认块缓冲机制,与之相对应的是终端输出的行缓冲。

2.UNIX 98 伪终端
	posix_openpt(); // 打开一个未使用的伪终端主设备,返回稍后会用到的代表该设备的文件描述符
	grantpt();  // 修改对应于伪终端主设备的从设备属主和权限
	unlockpt();  // 解锁对应于伪终端主设备的从设备,这样就能打开从设备了
	ptsname();  // 返回对应于伪终端主设备的从设备名称。之后从设备就可以通过 open() 来打开了

	UNIX 98 伪终端数量的限制:
		因为每一对使用中的伪终端都会占用一小段不能被交换的内核内存空间,因此内核对系统中 UNIX 98 伪终端 的数量有一个限制。
	到 Linux 2.6.4 之后,对伪终端的数量限制定义在 /proc/sys/kernel/pty/max ,默认 4096,可以设定最大值为 1048576.
	还有一个相关的只读文件 /proc/sys/kernel/pty/nr ,这个文件记录了当前系统中有多少 UNIX 98 伪终端 正在使用中。


3.伪终端IO
	一对伪终端同一个双向管道很相似。任何写入到伪终端主设备的数据都会在从设备端作为输入出现。而任何写入到从设备端的数据也会在主设备作为输入出现。
	伪终端对同双向管道之间的区别在于,伪终端的从设备端表现的像一个终端设备一样。从设备端解释输入的方式就和一个普通的控制终端解释键盘输入的方式一样。
  比如我们写入一个 ctrl+C 字符(通常代表中断字符)到伪终端主设备上,则从设备将其作为前台进程组产生一个 SIGINT 信号。如同一个常规的终端一样,当伪终端
  从设备工作与规范模式下时,输入是按照行缓冲的。换句话说,只有当我们向伪终端主设备写入一个换行符时,向从设备端读取输入的程序才会看到一行输入。
    同管道一样,伪终端的缓冲能力也是有限的。如果我们讲极限耗尽,那么未来的写操作会阻塞,知道伪终端另外一端的进程读取了一些字节后才能再次写入。

    信包模式:
    	信包模式是当伪终端从设备上的软流空相关的事件发生时,自动通知给运行在伪终端主设备上进程的机制。这些事件包括:
    	1.刷新输入和输出队列
    	2.停止或开启终端输出
    	3.开启或关闭流控
    信包模式能帮助处理提供网络登录服务的伪终端应用。
    信包模式可以通过对代表伪终端主设备的文件描述符上执行 TIOCPKT ioctl() 来开启。
    ioctl(mfd,TIOCPKT,%arg);
    当开启了信包模式后,从伪终端主设备读取要么返回一个非零控制符,这是一个比特掩码,表示从设备端的状态是否改变,要么返回零字节,紧跟着写入到从设备端的单个
  或多个字节数据。
    当工作于信包模式的伪终端状态发生改变时,select() 会提示主设备端发生异常情况。

4.终端属性和窗口大小
	伪终端主从设备共享终端属性和窗口大小结构。这表示运行在伪终端主设备上的程序可以通过在主设备文件描述符上调用 tcsetattr()和 ioctl()来修改从设备端的属性和
  窗口大小。




 

 

 

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值