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

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

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

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

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

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

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

ptsname返回PTY从设备的名字

  1. #define _XOPEN_SOURCE
  2. #include <stdlib.h>
  3.  
  4. char *ptsname(int fd);
  5.  
  6. #define _GNU_SOURCE
  7. #include <stdlib.h>
  8. int ptsname_r(int fd, char *buf, size_t buflen);
    fd:文件描述符

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

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

实现函数:

  1. #include "apue.h"
  2. #include <errno.h>
  3. #include <fcntl.h>
  4. #if defined(SOLARIS)
  5. #include <stropts.h>
  6. #endif
  7.  
  8. int ptym_open(char *pts_name, int pts_namesz)
  9. {
  10. char *ptr;
  11. int fdm, err;
  12.  
  13. if((fdm = posix_openpt(O_RDWR)) < )
  14. return(-);
  15. if(grantpt(fdm) < )
  16. goto errout;
  17. if(unlock(fdm) < )
  18. goto errout;
  19. if((ptr = ptsname(fmd)) == NULL)
  20. goto errout;
  21.  
  22. strncpy(pts_name, ptr, pts_namesz);
  23. pts_name[pts_namesz - ] = '\0';
  24. return(fdm);
  25. errout:
  26. err = errno;
  27. close(fdm);
  28. errno = err;
  29. return(-);
  30. }
  31.  
  32. int ptys_open(char *pts_name)
  33. {
  34. int fds;
  35. #if defined(SOLARIS)
  36. int err, setup;
  37. #endif
  38.  
  39. if((fds = open(pts_name, O_RDWR)) < )
  40. goto errout;
  41.  
  42. if(setup == ) {
  43. if(ioctl(fds, I_PUSH, "ptem") < )
  44. goto errout;
  45. if(ioctl(fds, I_PUSH, "ldterm") < )
  46. goto errout;
  47. if(ioctl(fds, I_PUSH, "ttcompat") < ) {
  48. errout:
  49. err = errno;
  50. close(fds);
  51. errno = err;
  52. return(-);
  53. }
  54. }
  55. #endif
  56. return(fds);
  57. }

pty_open

用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);

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[];
  11.  
  12. if((fdm = ptym_open(pts_name, sizeof(pts_name))) < )
  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 - ] = '\0';
  18. }
  19.  
  20. if((pid = fork()) < )
  21. return(-);
  22. else if(pid == ) { /* childe */
  23. if(setsid() < )
  24. err_sys("setsid error");
  25.  
  26. if((fds = ptys_open(pts_name)) < )
  27. err_sys("can't open slave pty");
  28. close(fdm);
  29. #if defined(BSD)
  30. if(ioctl(fds, TIOCSCTTY, (char *)) < )
  31. err_sys("TIOCSCTTY error");
  32. #endif
  33. if(slave_termios != NULL) {
  34. if(tcsetattr(fds, TCSANOW, slave_termios) < )
  35. err_sys("tcsetattr error on slave pty");
  36. }
  37. if(slave_winsize != NULL) {
  38. if(ioctl(fds, TIOCSWINSZ, slave_winsize) < )
  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();
  52. } else {
  53. *ptrfdm = fdm;
  54. return(pid);
  55. }
  56. }

pty_fork

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

  1. [apue] 书中关于伪终端的一个纰漏

    在看 apue 第 19 章伪终端第 6 节使用 pty 程序时,发现“检查长时间运行程序的输出”这一部分内容的实际运行结果,与书上所说有出入. 于是展开一番研究,最终发现是书上讲的有问题,现在摘出来 ...

  2. apue 第18章 终端I/O

    终端I/O有两种不同的工作模式: (1)规范模式:输入以行单位进行处理,每个读请求也最多返回一行. (2)非规范模式:输入字符不装配成行. 终端设备是由通常位于内核中的终端驱动程序控制的.每个终端设备 ...

  3. apue第四章学习总结

    apue第四章学习总结 4.1.若以stat函数去替换lstat函数,会发生: 原来的目录路径: $:~/workspace/apue2/include$ ls -l apue.h abc lrwxr ...

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

      blog.csdn.net/todd911/article/details/8025540 Linux上许多网络服务应用,如l2tp.pptp.telnet,都用到了伪终端.有朋友在问这方面的概念 ...

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

    转自http://www.xuebuyuan.com/877887.html 2013年09月07日 ⁄ 综合 ⁄ 共 4047字 ⁄ 字号 小 中 大 ⁄ 评论关闭 Linux上许多网络服务应用,如 ...

  6. Unix环境高级编程(二十)伪终端

    1.综述 伪终端对于一个应用程序而言,看上去像一个终端,但事实上伪终端并不是一个真正的终端.从内核角度看,伪终端看起来像一个双向管道,而事实上Solaris的伪终端就是用STREAMS构建的.伪终端总 ...

  7. 第19章 集合框架(3)-Map接口

    第19章 集合框架(3)-Map接口 1.Map接口概述 Map是一种映射关系,那么什么是映射关系呢? 映射的数学解释 设A,B是两个非空集合,如果存在一个法则,使得对A中的每一个元素a,按法则f,在 ...

  8. 第19章 queue队列容器

    /* 第19章 queue队列容器 19.1 queue技术原理 19.2 queue应用基础 19.3 本章小结 */ // 第19章 queue队列容器 // 19.1 queue技术原理 // ...

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

    章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP ...

随机推荐

  1. SDUT 1266 出栈序列统计(卡特兰数)

    这道题是回溯算法,网上一查是卡特兰数先占上代码,题解过两天会写. #include <bits/stdc++.h> using namespace std; int main() { // ...

  2. Linux0.11内核源码——内核态线程(进程)切换的实现

    以fork()函数为例,分析内核态进程切换的实现 首先在用户态的某个进程中执行了fork()函数 fork引发中断,切入内核,内核栈绑定用户栈 首先分析五段论中的第一段: 中断入口:先把相关寄存器压栈 ...

  3. 2018-2019-2 20175105王鑫浩《Java程序设计》实验四 《Android开发基础》实验报告

    实验四 <Android开发基础> 实验报告封面 课程:Java程序设计 班级:1751班 姓名:王鑫浩 学号:20175105 指导教师:娄嘉鹏 实验日期:2019年5月17日 实验时间 ...

  4. dubbo 漫谈一

    转:腾信视频 阿甘 https://ke.qq.com/course/216518 https://blog.csdn.net/xlgen157387/article/details/51865289 ...

  5. 从xxxx检测到有潜在危险的 Request.Form 提示黄页

    相信很多朋友都遇到过"从客户端xxxxxx"检测到有潜在危险的 Request.Form 然后给一个黄页提示.然后检测代码又找不到错误的代码提示. 原因:是因为在页面里边使用了富文 ...

  6. error C2065: “CString”: 未声明的标识符 ;fatal error C1189: #error : afxstr.h can only be used in MFC proje

    转自VC错误:http://www.vcerror.com/?p=1388 问题描述: error C2065: "CString": 未声明的标识符 fatal error C1 ...

  7. 单例模式@Singleton在测试中的运用

    前言 单例模式是一种比较常用的设计模式,目的是:保证一个类仅有一个实例,并提供一个访问它的全局访问点. 测试种可能用到的场景 : 在很多时候,有些对象我们希望在整个程序只有一个实例,如线程池.数据库连 ...

  8. Openstack API 类型 & REST 风格

    目录 目录 Openstack 提供了三种操作方式 Web界面 CIL 指令行 RESTful API REST 风格 RESTFul风格的API设计 基于HTTP协议的RESTful API Ope ...

  9. ubuntu+qt+opencv

    linux下Qt+OpenCv环境的搭建: https://blog.csdn.net/yaowangII/article/details/84303124 1.qt:https://blog.csd ...

  10. div里添加元素样式

    function YUEFEN() { $(".BBNL_2").click(function () { $(".BBNL_2").css("colo ...