LinuxLinux学习之路读书笔记

APUE读书笔记-19伪终端(16)

2020-10-13  本文已影响0人  QuietHeart

(7)pty程序的do_driver函数

#include "apue.h"
void do_driver(char *driver)
{
    pid_t   child;
    int     pipe[2];

    /*
     * Create a stream pipe to communicate with the driver.
     */
    if (s_pipe(pipe) < 0)
        err_sys("can't create stream pipe");

    if ((child = fork()) < 0) {
        err_sys("fork error");
    } else if (child == 0) {        /* child */
        close(pipe[1]);

        /* stdin for driver */
        if (dup2(pipe[0], STDIN_FILENO) != STDIN_FILENO)
            err_sys("dup2 error to stdin");

        /* stdout for driver */
        if (dup2(pipe[0], STDOUT_FILENO) != STDOUT_FILENO)
            err_sys("dup2 error to stdout");
        if (pipe[0] != STDIN_FILENO && pipe[0] != STDOUT_FILENO)
            close(pipe[0]);

        /* leave stderr for driver alone */
        execlp(driver, driver, (char *)0);
        err_sys("execlp error for: %s", driver);
    }
    close(pipe[0]);     /* parent */
    if (dup2(pipe[1], STDIN_FILENO) != STDIN_FILENO)
        err_sys("dup2 error to stdin");
    if (dup2(pipe[1], STDOUT_FILENO) != STDOUT_FILENO)
        err_sys("dup2 error to stdout");
    if (pipe[1] != STDIN_FILENO && pipe[1] != STDOUT_FILENO)
        close(pipe[1]);

    /*
     * Parent returns, but with stdin and stdout connected
     * to the driver.
     */
}

通过我们自己写的被pty调用的driver程序,我们可以以任何需要的方式来驱动交互程序。即使它的标准输入和标准输出连接到pty上面,driver进程也还是可以通过读写/dev/tty来和用户进行交互。这个方案还是不如expect程序通用,但是它只通过不到50行的代码,就为pty程序添加了一个有用的选项。

译者注

原文参考

参考: APUE2/ch19lev1sec6.html

7、高级特性

伪终端还有一些额外的特性,我们这里简单对它们列出。这些特性在Sun Microsystems和BSD的pty的man手册第4节中描述了。

包模式

包模式可以让PTY master获知PTY slave的状态变化。在Solaris上面,这个模式通过向PTY master端推送pckt的STREAMS模块来实现。我们在前面第2节中的"Solaris下面伪终端的结构"图中,对其进行了展示。在FreeBSD, Linux, 和 Mac OS X中,这个模式通过ioctl的TIOCPKT命令来激活。

Solaris和其他平台的包模式细节有一些不同。Solaris下面,由于pckt模块将特定的事件转化成非数据的STREAMS消息,所以从PTY master读取的进程需要调用getmsg来获得来自stream头的消息。在其他平台下面,每次从PTY master读取都会返回一个状态字节接着一个可选的数据。

除去这些实现上面的细节,包模式的目的就是在PTY slave上面的行规则模块发生如下事件的时候,通知读取PTY master的进程:当读取队列被flushed,当写队列被flushed,当输出停止的时候(例如Control-S导致其停止),当输出重新启动的时候,当XON/XOFF流控制在被禁止之后再次被使能的时候,在XON/XOFF流控制在被使能之后又被禁止的时候。这些事件,在诸如rlogin客户和rlogind服务进程中可能会被用到。

上一篇 下一篇

猜你喜欢

热点阅读