expect 程序
伪终端可以用来以非交互的模式来运行交互的程序。大量的程序需要一个终端来运行。有一个例子就是passwd命令,这个程序需要用户键入一个密码来相应提示符号。
除了可以修改所有的交互程序,让它们本身可以支持批量处理模式的操作,一个更好的解决方法就是,提供一个方式,可以让所有的交互程序能够从一个脚本中运行。expect程序就提供了这样的功能。它使用伪终端来运行其他的程序,这和我们后面讲述的pty程序类似,但是expect可以提供一种程序语言来检查运行的应用程序的输出,然后确定再将给应用程序发送什么作为应用程序的输入。当一个交互的程序从一个脚本中运行的时候,我们无法从脚本中只拷贝所有内容到应用程序,以及反之。所以,我们需要给应用程序发送一些输入,查看它的输出,然后决定之后给应用程序发送什么。
运行协作处理进程
在前面协作处理进程(协作处理进程参见前面,简之即被协作者输入给协作者,协作者处理之后再送回给被协作者)的例子中,我们无法启动一个使用标准输入输出库作为输入输出的协作处理程序,因为当我们通过一个管道和协作处理程序交互的时候,标准输入输出库是将标准输入输出设成满缓冲形式的,这样会导致死锁。如果我们没有那个编译好了的协作处理程序的源代码,那么我们无法使用fflush来解决这个问题。15章第4节中"通过写它的标准输入以及读取它的标准输出来运行写作处理程序"这个图,展示的就是一个进程来驱动协作处理程序。我们需要做的只是将一个伪终端放置在两个进程之间。这样使得协作处理程序以为,它运行在一个终端上面,而不是另外一个进程驱动它运行。如下图所示。
使用伪终端来驱动一个协作处理进程
coprocess
+-----------+ pipe1 +-------------+ +-------------+
| driving |---------->| pseudo |----------->| stdin |
| program |<----------| terminal |<-----------| stdout |
+-----------+ pipe2 +-------------+ +-------------+
现在协作处理进程的标准输入和标准输出看起来就像是一个终端设备,所以标准输入输出库会设置这两个流为行缓冲的方式。
父进程可以以两种方式获得在它本身和协作处理进程之间的伪终端。(这里父进程可以是前面使用两个管道和协作处理进程通信的程序,也可以是使用一个单一的STREAMS管道的程序)。一个方法就是,父进程直接调用pty_fork函数(后面有这个函数相关的内容)而不是调用fork。另一个方法就是使用exec执行pty程序(后面有这个程序的实现),并且将协作处理进程作为它的参数。我们将在介绍完了pty程序之后,看看这两个解决的方法。
网友评论