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

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

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

#include <stdlib.h>
#include <fcntl.h> int posix_openpt(int flags);
返回值:成功返回下一个可用的PTY主设备文件描述符,出错-
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)) < )
return(-);
if(grantpt(fdm) < )
goto errout;
if(unlock(fdm) < )
goto errout;
if((ptr = ptsname(fmd)) == NULL)
goto errout; strncpy(pts_name, ptr, pts_namesz);
pts_name[pts_namesz - ] = '\0';
return(fdm);
errout:
err = errno;
close(fdm);
errno = err;
return(-);
} int ptys_open(char *pts_name)
{
int fds;
#if defined(SOLARIS)
int err, setup;
#endif if((fds = open(pts_name, O_RDWR)) < )
goto errout; if(setup == ) {
if(ioctl(fds, I_PUSH, "ptem") < )
goto errout;
if(ioctl(fds, I_PUSH, "ldterm") < )
goto errout;
if(ioctl(fds, I_PUSH, "ttcompat") < ) {
errout:
err = errno;
close(fds);
errno = err;
return(-);
}
}
#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函数

 #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)
{
int fdm, fds;
pid_t pid;
char pts_name[]; if((fdm = ptym_open(pts_name, sizeof(pts_name))) < )
err_sys("can't open master pty: %s, error %d", pts_name, fdm); if(slave_name != NULL) {
strncpy(slave_name, pts_name, slave_namesz);
slave_name[slave_namesz - ] = '\0';
} if((pid = fork()) < )
return(-);
else if(pid == ) { /* childe */
if(setsid() < )
err_sys("setsid error"); if((fds = ptys_open(pts_name)) < )
err_sys("can't open slave pty");
close(fdm);
#if defined(BSD)
if(ioctl(fds, TIOCSCTTY, (char *)) < )
err_sys("TIOCSCTTY error");
#endif
if(slave_termios != NULL) {
if(tcsetattr(fds, TCSANOW, slave_termios) < )
err_sys("tcsetattr error on slave pty");
}
if(slave_winsize != NULL) {
if(ioctl(fds, TIOCSWINSZ, slave_winsize) < )
err_sys("TIOCSWINSZ error on slave pty");
} if(dup2(fds, STDIN_FILENO) != STDIN_FILENO)
err_sys("dup2 error to stdin");
if(dup2(fds, STDOUT_FILENO) != STDOUT_FILENO)
err_sys("dup2 error to stdout");
if(dup2(fds, STDERR_FILENO) != STDERR_FILENO)
err_sys("dup2 error to stderr");
if(fds != STDIN_FILENO && fds != STDOUT_FILENO &&
fds != STDERR_FILENO)
close(fds);
return();
} else {
*ptrfdm = fdm;
return(pid);
}
}

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. Java并发与多线程与锁优化

    前言 目前CPU的运算速度已经达到了百亿次每秒,所以为了提高生产率和高效地完成任务,基本上都采用多线程和并发的运作方式. 并发(Concurrency):是指在某个时间段内,多任务交替处理的能力.CP ...

  2. springboot2集成redis5报错:io.lettuce.core.RedisException: io.lettuce.core.RedisConnectionException: DENIED Redis is running in protected

    报错信息如下: Caused by: io.lettuce.core.RedisException: io.lettuce.core.RedisConnectionException: DENIED ...

  3. nofollow标签的作用 nofollow标签添加方法

    这篇文章主要介绍了nofollow标签的作用 nofollow标签添加方法,需要的朋友可以参考下   nofollow标签的作用 nofollow标签添加方法  模拟搜狗蜘蛛   nofollow标签 ...

  4. php strtolower()函数 语法

    php strtolower()函数 语法 作用:把所有字符转换为小写.大理石量具 语法:strtolower(string) 参数: 参数 描述 string 必须,规定要转换的字符串 说明:str ...

  5. manjaro linux java环境配置

    大佬博客 yaourt jdk 不管怎么装就是会出错 #报错信息 Error: dl failure on line 597 Error: failed /usr/lib/jvm/java-12-op ...

  6. Docker(应用服务引擎)

    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化.容器是完全使用沙箱机制,相互之间不会有任何 ...

  7. 九. jenkins用户权限管理

    由于jenkins默认的权限管理体系不支持用户组和角色的配置,所以需要使用第三方插件来支持角色的配置: Role-based Authorization Strategy 1.先安装插件,如下: 2. ...

  8. 用 Flask 来写个轻博客 (36) — 使用 Flask-RESTful 来构建 RESTful API 之五

    目录 目录 前文列表 PUT 请求 DELETE 请求 测试 对一条已经存在的 posts 记录进行 update 操作 删除一条记录 前文列表 用 Flask 来写个轻博客 (1) - 创建项目 用 ...

  9. Pipenv管理项目环境--Django项目的一些最佳实践

    virtualenv --- 使用不方便 提升效率,管理更便捷--- pipenv 新建环境:: pip3 install pipenv 在项目下,用pipenv安装 Djagno pipenv in ...

  10. USACO 6.3 章节 你对搜索和剪枝一无所知QAQ

    emmm........很久很久以前 把6.2过了 所以emmmmmm 直接跳过 ,从6.1到6.3吧 Fence Rails 题目大意 N<=50个数A1,A2... 1023个数,每个数数值 ...