zoukankan      html  css  js  c++  java
  • apue 第19章 伪终端

     伪终端是指对于一个应用程序而言,他看上去像一个终端,但事实上它并不是一个真正的终端。

    • 进程打开伪终端设备,然后fork。子进程建立一个新的会话,打开一个相应的伪终端从设备。复制输入、输出和标准错误文件描述符,调用exec,子进程从设备编程伪终端。
    • 伪终端能像终端一样,但是无意义的函数调用如改变波特率、发送中断符、设置奇偶校验将被忽略。
    • 伪终端可以做输入和输出。

    posix_opent函数提供了一种可移植的方法来打开下一个可用伪终端主设备

    #include <stdlib.h>
    #include <fcntl.h>
    
    int posix_openpt(int flags);
    返回值:成功返回下一个可用的PTY主设备文件描述符,出错-1
    flags:设备操作标记,可以是0或者以下两项的之一,O_RDWR允许对设备同时进行读写操作,此标记通常需要指定
    O_NOCTTY不将设备作为进程的控制终端

    在伪终端从设备可用之前,它的权限必须设置,以便应用程序可以访问它。

    改变指定master对应从设备的属主与访问权限

    #define _XOPEN_SOURCE
    #include <stdlib.h>
    
    int grantpt(int fd);
    int unlockpt(int fd);
    返回值:成功0,出错-1
    fd:文件描述符

    ptsname返回PTY从设备的名字

    #define _XOPEN_SOURCE
    #include <stdlib.h>
    
    char *ptsname(int fd);
    
    #define _GNU_SOURCE
    #include <stdlib.h>
    int ptsname_r(int fd, char *buf, size_t buflen);
    fd:文件描述符

    apue写的函数,打开下一个可用的PTY主设备。调用者必须分配一个数组来存放主设备或从设备名字。

    #include "apue.h"
    
    int ptym_open(char *pts_name, int pts_namesz);
    返回值:成功返回PTY主设备文件描述符,出错-1
    int ptys_open(char *pts_name);
    返回值:成功返回PTY设备文件描述符,出错-1
    pts_name:打开设备的名字
    pts_namesz:缓冲区字节长度

     实现函数:

    #include "apue.h"
    #include <errno.h>
    #include <fcntl.h>
    #if defined(SOLARIS)
    #include <stropts.h>
    #endif
    
    int ptym_open(char *pts_name, int pts_namesz)
    {
        char *ptr;
        int fdm, err;
    
        if((fdm = posix_openpt(O_RDWR)) < 0)
            return(-1);
        if(grantpt(fdm) < 0)
            goto errout;
        if(unlock(fdm) < 0)
            goto errout;
        if((ptr = ptsname(fmd)) == NULL)
            goto errout;
    
        strncpy(pts_name, ptr, pts_namesz);
        pts_name[pts_namesz - 1] = '';
        return(fdm);
    errout:
        err = errno;
        close(fdm);
        errno = err;
        return(-1);
    }
    
    int ptys_open(char *pts_name)
    {
        int fds;
    #if defined(SOLARIS)
        int err, setup;
    #endif
    
        if((fds = open(pts_name, O_RDWR)) < 0)
            goto errout; 
    
        if(setup == 0) {
            if(ioctl(fds, I_PUSH, "ptem") < 0)
                goto errout;
            if(ioctl(fds, I_PUSH, "ldterm") < 0)
                goto errout;
            if(ioctl(fds, I_PUSH, "ttcompat") < 0) {
    errout:
                err = errno;
                close(fds);
                errno = err;
                return(-1);
            }
        }
    #endif
        return(fds);
    }
    pty_open

    用fork调用打开主设备和从设备,创建作为会话首进程的子进程并使其具有控制终端。 

    #include "apue.h"
    #include <termios.h>
    
    pid_t pty_fork(int *ptrfdm, char *slave_name, int slave_namesz,
        const struct termios *slave_termios,
        const struct winsize *slave_winsize);

     pty_fork函数

     1 #include "apue.h"
     2 #include <termios.h>
     3 
     4 pid_t pty_fork(int *ptrfdm, char *slave_name, int slave_namesz,
     5         const struct termios *slave_termios,
     6         const struct winsize *slave_winsize)
     7 {
     8     int fdm, fds;
     9     pid_t pid;
    10     char pts_name[20];
    11 
    12     if((fdm = ptym_open(pts_name, sizeof(pts_name))) < 0)
    13         err_sys("can't open master pty: %s, error %d", pts_name, fdm);
    14 
    15     if(slave_name != NULL) {
    16         strncpy(slave_name, pts_name, slave_namesz);
    17         slave_name[slave_namesz - 1] = '';
    18     }
    19 
    20     if((pid = fork()) < 0)
    21         return(-1);
    22     else if(pid == 0) {                /* childe */
    23         if(setsid() < 0)
    24             err_sys("setsid error");
    25 
    26         if((fds = ptys_open(pts_name)) < 0)
    27             err_sys("can't open slave pty");
    28         close(fdm);
    29 #if defined(BSD)
    30         if(ioctl(fds, TIOCSCTTY, (char *)0) < 0)
    31             err_sys("TIOCSCTTY error");
    32 #endif
    33         if(slave_termios != NULL) {
    34             if(tcsetattr(fds, TCSANOW, slave_termios) < 0)
    35                 err_sys("tcsetattr error on slave pty");
    36         }
    37         if(slave_winsize != NULL) {
    38             if(ioctl(fds, TIOCSWINSZ, slave_winsize) < 0)
    39                 err_sys("TIOCSWINSZ error on slave pty");
    40         }
    41 
    42         if(dup2(fds, STDIN_FILENO) != STDIN_FILENO)
    43             err_sys("dup2 error to stdin");
    44         if(dup2(fds, STDOUT_FILENO) != STDOUT_FILENO)
    45             err_sys("dup2 error to stdout");
    46         if(dup2(fds, STDERR_FILENO) != STDERR_FILENO)
    47             err_sys("dup2 error to stderr");
    48         if(fds != STDIN_FILENO && fds  != STDOUT_FILENO &&
    49             fds != STDERR_FILENO)
    50             close(fds);
    51         return(0);
    52     } else {
    53         *ptrfdm = fdm;
    54         return(pid);
    55     }
    56 }
    pty_fork
    无欲速,无见小利。欲速,则不达;见小利,则大事不成。
  • 相关阅读:
    leetcode-14
    贪心算法
    MySQL索引
    leetcode-13
    leetcode-12
    leetcode-11
    深度和广度优先搜索
    CentOS出错You don't have permission to access on this server
    linux给文件或目录添加apache权限
    让CentOS在同一个窗口打开文件夹
  • 原文地址:https://www.cnblogs.com/ch122633/p/8110239.html
Copyright © 2011-2022 走看看