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,出错-1fd:文件描述符

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] = ‘\0‘;
    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] = ‘\0‘;
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

原文地址:https://www.cnblogs.com/ch122633/p/8110239.html

时间: 2024-08-28 21:25:51

apue 第19章 伪终端的相关文章

linux的终端,网络虚拟终端,伪终端(转)

转自http://www.xuebuyuan.com/877887.html 2013年09月07日 ⁄ 综合 ⁄ 共 4047字 ⁄ 字号 小 中 大 ⁄ 评论关闭 Linux上许多网络服务应用,如l2tp.pptp.telnet,都用到了伪终端.有朋友在问这方面的概念,把偶知道的写下来,以供讨论. 一.终端要理解伪终端(Pseudo Terminal),先来看看什么是“终端”(Terminal). 终端是一种字符型设备,它有多种类型,通常使用tty来简称各种类型的终端设备. 1.串行端口终端

linux的终端,网络虚拟终端,伪终端

linux的终端,网络虚拟终端,伪终端 转自:http://www.xuebuyuan.com/877887.html Linux上许多网络服务应用,如l2tp.pptp.telnet,都用到了伪终端.有朋友在问这方面的概念,把偶知道的写下来,以供讨论. 一.终端要理解伪终端(Pseudo Terminal),先来看看什么是“终端”(Terminal). 终端是一种字符型设备,它有多种类型,通常使用tty来简称各种类型的终端设备. 1.串行端口终端(/dev/ttySx)串行端口终端(Seria

4.13日第12次作业,16章外包,17章需求,19章组织级与大型项目

29-高项-田哲琦 16章.外包管理 1.外包的形式有哪五种?什么是利益关系?P346-348 答:企业现行采用的主要外包形式如下: 1).活动外包 2).服务外包 3).内包 4).合包 5).利益关系. 利益关系(benfit-based relationship),这是一种长期合作关系,双方先为此关系进行投资,再根据预先拟定的协议分享利益,共同承担风险,同时共享利益. 2.外包管理的目标是什么?要实现这个目标,对外包管理提出哪四个方面的要求?P348 答:软件外包管理总的目标是用强有力的手

第19章 queue队列容器

/* 第19章 queue队列容器 19.1 queue技术原理 19.2 queue应用基础 19.3 本章小结 */ // 第19章 queue队列容器 // 19.1 queue技术原理 // 19.2 queue应用基础 ------------------------------------------------------------------------------------------- //273 #include <queue> #include <iostre

终端,虚拟终端,伪终端

终端,虚拟终端和伪终端概念之间的区别是: 一.终端 英文为System Console,指的是"键盘和打印机硬件设备组合",或者是"键盘和显示器硬件设备组合",或者是"其他的输入和输出硬件设备组合". System Console的定义跟操作系统和应用软件无关,只跟硬件有关. 二.虚拟终端 英文为Virtual console,指的是在BSD,UnixWare,Linux等操作系统中提供的特性,在该特性中,通过程序来模拟多个Virtual con

Lua_第19章 String 库(上)

Lua_第19章String 库 Lua解释器对字符串的支持很有限.一个程序可以创建字符串并连接字符串,但不能截取子串,检查字符串的大小,检测字符串的内容.在 Lua中操纵字符串的功能基本来自于 string 库. String 库中的一些函数是非常简单的:string.len(s)返回字符串 s 的长度;string.rep(s, n)返回重复 n 次字符串 s 的串;你使用 string.rep("a", 2^20)可以创建一个 1M bytes 的字符 串(比如,为了测试需要);

Lua_第19章 String 库(下)

Lua_第19章 String 库(下) 19.3捕获(Captures) Capture(下面译为捕获或者capture,模式中捕获的概念指,使用临时变量来保存匹配的子模式,常用于 向前引用.)是这样一种机制:可以使用模式串的一部分匹配目标串的一部分.将你想捕 获的模式用圆括号括起来,就指定了一个capture.在 string.find 使用captures 的时候,函数会返回捕获的值作为额外的结果.这常被用 来将一个目标串拆分成多个: pair = "name =Anna" _,

《TCP/IP详解卷1:协议》第19章 TCP的交互数据流-读书笔记

章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP:网际协议(1)-读书笔记 <TCP/IP详解卷1:协议>第3章 IP:网际协议(2)-读书笔记 <TCP/IP详解卷1:协议>第4章 ARP:地址解析协议-读书笔记 <TCP/IP详解卷1:协议>第5章 RARP:逆地址解析协议-读书笔记 <TCP/IP详解卷1:协

Linux终端概念,伪终端,串行终端,虚拟终端,控制台

终端的历史由来 最初的计算机由于价格昂贵,因此,一台计算机一般是由多个人同时使用的.在这种情况下一台计算机需要连接上许多套键盘和显示器来供多个人使用.在以前专门有这种可以连上一台电脑的设备,只有显示器和键盘,还有简单的处理电路,本身不具有处理计算机信息的能力,他是负责连接到一台正常的计算 机上(通常是通过串口),然后登陆计算机,并对该计算机进行操作.当然,那时候的计算机操作系统都是多任务多用户的操作系统.这样一台只有显示器和键盘能够通过串口连接到计算机 的设备就叫做终端. 而控制台又是什么回事呢