*nix 伪终端如何工作?什么是主/从通道?

2024-01-14

我想在 Linux 系统上用 C 语言编写一个简单、愚蠢的 X 终端模拟器。

起初,我只是想我必须打开一个 shell 并显示其输出。 我检查了xterm和rxvt代码,看起来有点复杂。

首先,我必须使用 openpty 打开一个伪终端。所以我查看了手册页,发现 openpty 填充了 2 个文件描述符,主文件描述符和从文件描述符。 由于这些特殊文件的系统依赖性,xterm 和 rxvt 代码都很混乱。

我理解 termios 的东西:它只是一堆有关终端转义码的信息。 我真正不明白的是:我应该如何处理主/从文件描述符?

一个打开终端、登录、在 shell 上执行“ls”的示例程序非常棒。

(英语不是我的母语,请原谅我最终的错误)

编辑: 这是我想出的示例代码:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <pty.h>
#include <utmp.h>
#include <ctype.h>

void
safe_print (char* s)
{
    while(*s) { 
        if(*s == '\n')
            putchar("\n");
        else if(iscntrl(*s))
            printf("\\e(%d)", *s);
        else
            putchar(*s);
        s++;
    }
}


int
main (int argc, char** argv)
{
    char buf[BUFSIZ] = {0};
    int master;
    int ret = forkpty(&master, NULL, NULL, NULL);

    if(ret == -1)
        puts("no fork"), exit(0);

    if(!ret) { 
        execl("/bin/sh", "sh", NULL);
        exit(0);
    }

    sleep(1); /* let the shell run */


    if(argc >= 2) {
        write(master, argv[1], strlen(argv[1]));
        write(master, "\n", 1);
    } else {
        write(master, "date\n", sizeof "date\n");
    }


    while(1) {
        switch(ret = read(master, buf, BUFSIZ)) {
        case -1:
            puts("error!"); 
            exit(1);
            break;
        case 0:
            puts("nothing.."), sleep(1);
            break;
        default:
            buf[ret] = '\0';
            safe_print(buf);

        }
    }

    close(master);

    return 0;
}    

关于你的问题的主/从部分,从手册页(从我系统上的 openpty(3) 手册页引用):

伪终端是一对 字符设备、主设备和 从设备。从设备 为进程提供接口 与 tty(4) 中描述的相同。 然而,尽管所有其他设备 提供所描述的接口 在 tty(4) 中有一个硬件设备 他们背后的某种奴隶 相反,设备有另一个进程 通过master来操纵它 伪终端的一半。那是, 主设备上写入的任何内容 作为输入提供给从设备 以及奴隶身上写的任何东西 设备作为输入呈现 主设备。

手册页是您的朋友。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

*nix 伪终端如何工作?什么是主/从通道? 的相关文章

  • C 语言中的套接字如何工作?

    我对 C 中的套接字编程有点困惑 You create a socket bind it to an interface and an IP address and get it to listen I found a couple of
  • 纹理映射 C++ OpenGL

    我已经阅读了相关内容 包括 Nehe 和此处的解决方案 但我找不到具体的答案 我正在尝试加载一张名为stars jpg 的照片 我想通过使用 uv 坐标映射它来使其成为场景的背景 方法是 glBegin GL QUADS glTexCoor
  • .NET:EventHandler 竞争条件修复如何工作?

    以下模式用于在引发事件时避免竞争条件 以防另一个线程取消订阅 MyEvent 使其为空 class MyClass public event EventHandler MyEvent public void F EventHandler h
  • 从 C++ 中的函数返回二维数组[重复]

    这个问题在这里已经有答案了 可能的重复 C 从函数返回多维数组 https stackoverflow com questions 3716595 c returning multidimension array from function
  • 为什么数组不可赋值? [复制]

    这个问题在这里已经有答案了 据我所知 C 标准禁止使用数组作为可修改的左值 即在赋值的左侧 int lhs 4 rhs 4 0 1 2 3 lhs rhs illegal 现在 我一直想知道为什么会这样 我可以看到上面的语句 以及写入数组的
  • 起订量工作单元

    我是单元测试的新手 我想为我的搜索功能创建一个测试 我的服务层看起来像 public class EmployeeService BaseService IEmployeeService public EmployeeService IUn
  • 如何从远程 ssh 连接上运行的 tmux(复制模式)复制到本地剪贴板

    我通过 OS X 上的 VirtualBox 运行 Linux 我通过在无头状态下运行虚拟机 然后使用端口转发 sshing 到 Linux 机器来实现这一点 现在 无论复制到我的虚拟机上的剪贴板 我都可以粘贴到我的远程 ssh 会话上 但
  • C 风格强制转换与内在强制转换

    假设我已经定义了 m256d x我想提取低 128 位 我会做 m128d xlow mm256 castpd256 pd128 x 然而 我最近看到有人这样做 m128d xlow m128d x 是否有用于演员的首选方法 为什么要用第一
  • 为什么C++中没有“NULL引用”?

    我正在阅读 C 常见问题解答 8 6 什么时候应该使用引用 什么时候应该使用指针 http www parashift com c faq lite refs vs ptrs html 特别是以下声明 可以时使用引用 必要时使用指针 上述情
  • 将node.js +expressjs应用程序的NODE_ENV设置为ubuntu下的守护进程

    我按照这些说明让守护进程正常工作 http kevin vanzonneveld net techblog article run nodejs as a service on ubuntu karmic http kevin vanzon
  • cmake 包括其他目录中的 h 文件

    我在 cmake 项目下进行测试时遇到问题 我的项目是这样安排的 TerrainMap PointAccumulator heightQuadGrid Test 在 TerrainMap 目录中 CMakeLists txt 文件简单地概述
  • 如何在PropertyGrid中自定义绘制GridItem?

    我想以与所有者在 ListView 详细信息 和其他控件中绘制项目类似的方式在 PropertyGrid 中绘制属性值 如果将属性声明为 Color 类型 则其值将使用字符串描述旁边的颜色样本来绘制 如果属性是图像类型 则在字符串描述旁边绘
  • 在 Ubuntu 16.04 上编译 PCL 1.7,CMake 生成的 Makefile 中出现错误

    我正在尝试让 PCL 1 7 点云库 而不是其他 pcl 在 Ubuntu 16 04 上运行 我最终希望用于 C 的东西 但现在我只是想让这些例子工作 我使用的是 Ubuntu GNU 5 3 1 附带的默认编译器和 Cmake 版本 3
  • 如何查明我的字符串是否包含“micro”Unicode 字符?

    我有一个包含实验室数据的 Excel 电子表格 如下所示 g L ppb 我想测试希腊字母 是否存在 如果发现我需要做一些特别的事情 通常 我会写这样的东西 if cell StartsWith matchSequence lt unive
  • Opencv 对象检测:ORB GPU 检测器和 SURF GPU 描述符提取器

    我只是做了一个小实验来尝试不同的检测器 描述符组合 我的代码使用 ORB GPU 检测器来检测特征 并使用 SURF GPU 描述符来计算描述符 我使用 BruteForceMatcher GPU 来匹配描述符 并使用 knnMatch 方
  • 错误:C# 尝试读取或写入受保护的内存

    我很难纠正这个错误 该应用程序在 4 台不同的机器上进行了测试 在其中 3 台上运行良好 但一台 Vista PC 在尝试通过 WebBrowser1 打开页面时出现此错误 解决这个问题的任何帮助对我都会非常有帮助 System Acces
  • 在 C# 中设置风扇速度

    我知道以前有人问过这个问题 但我似乎无法让它发挥作用 我已调用以下内容 using System Management using System Management Instrumentation using System Runtime
  • 如何将 IDispatch* 放入托管代码中

    我一直在考虑尝试使用 C 编写一个实现 OPOS 服务对象的 COM 对象 我已经使用自动化和 MFC 在 C 中完成了它 这并不太困难 所以我坚持尝试将其转换为一种方法 我将排除界面中的其他方法 因为它们很简单 或者我希望如此 id 6
  • Image.Save 异常“GDI+ 中发生一般错误。”保存到 MemoryStream 时

    我有一个服务器客户端应用程序 我想从服务器获取屏幕截图 但在线bitmap Save ms System Drawing Imaging ImageFormat Png 我得到这个例外 A generic error occurred in
  • 用于读取文件的 Bash 脚本

    不知道为什么最后一行没有从脚本中删除 bin bash FILENAME 1 while read line do cut d f2 echo line done lt FILENAME cat file 1 test 2 test 3 t

随机推荐