关于linux:Linux系统编程训练营8Linux-终端与进程

详解控制台与终端

乏味的问题:Linux 的终端,控制台,TTY, PTY 到底是什么?它们与过程有什么关系?

历史回顾:控制台

  • 控制台是一个间接管制设施的面板(属于设施的一部分)
  • 计算机设备的控制台:按键 & 指示灯 (键盘 & 显示器)
  • 晚期的电子计算机必然有一个控制台

历史回顾:终端 (Terminal)

  • 终端是一台独立于计算机的机器,是可能用来和计算机进行交互的设施
TTY -- 即:TeleType Writer 电传打字机,一种终端设备

历史倒退过程。。。

  • 电传打字机曾经淘汰
  • 计算机上的输出设施和显示设施从主机独立进去
  • 控制台与终端的物理表现形式逐步趋近
  • 计算机开始反对多任务处理
  • 。。。

终端与过程

  • TTY 演变为 Linux 中的抽象概念,对于过程而言,TTY是一种输入输出设施

虚构终端与伪终端

各种终端类型

类型 阐明
虚构终端(Virtual Terminal) 将这一套键盘和显示器映射为 6 个终端设备 /dev/tty1~tty6 tty0指代以后应用的终端 (CLI虚构出)
串口终端(Serial Port Terminal) 将连贯到窗口的外设看看作终端设备 /dev/ttyS1,…
终端模拟器(Terminal Emulator) 终端模拟程序(狭义) / 内核模仿模块(侠义) Putty, MobaXTERM, 内核模块,伪终端
伪终端(Pseudo Terminal) 运行在用户模式的终端模拟程序,分为主设施(pty master)和从设施(pty slave) /dev/ptmx(主), /dev/pts/3(从), …

内核终端模拟器

伪终端模型

伪终端(gnome-terminal)

伪终端

tiansong@tiansong:~$ pstree -A -p -s $$
systemd(1)---systemd(968)---gnome-terminal(1885)---bash(1973)---pstree(2052)

虚构终端

ubuntu 由 GUI 切换到 CLI : CTRL + ALT +F3

tiansong@tiansong:~$ pstree -A -p -s $$
systemd(1)---login(2064)---bash(2118)---pstree(2125)

ubuntu 由 CLI 切换到 GUI : CTRL + ALT +F1

伪终端程序设计原理

站在 shell 角度的总结:
1. shell 面对的只有 TTY 设施,而 TTY 是 Linux 中的抽象概念,因而须要一个具体的模块来反对这个形象的概念
2. 对于虚构终端,反对这个概念的模块就是终端模拟器(内核模块,运行于内核模式),能够间接应用键盘、显卡驱动进行输入输出
3. 对于伪终端,创立主、从设施,其中 shell 过程对接的是从设施,主设施对接用户过程 gnome-terminal (实质是 GUI 应用程序)

伪终端程序设计(master)

  • 创立 PTY 主从设施: master = posix_openpt(O_RDWR);
  • 获取主设施权限:

    • grantpt(master); // 获取设施应用权限
    • unlockpt(master); // 解锁设施,为读写做筹备
  • 读写主设施

    • c = read(master, &rx, 1);
    • len = write(master, txbuf, strlen(txbuf));

伪终端程序设计(slave)

  • 关上 PTY 从设施,slave = open(path_to_slave, O_RDWR);
  • 读写设施:

    • write(slave, "Delphi\r", 7);
    • read(slave, buf, sizeof(buf) - 1);

实战伪终端程序设计

master.c

#define _XOPEN_SOURCE  600
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>

int main()
{
    char rx = 0;
    char rxbuf[128] = {0};
    char txbuf[256] = {0};
    int master = 0;
    int c = 0;
    int i = 0;

    master = posix_openpt(O_RDWR);                         // 连贯主设施,等同于 gnome-terminal

    if (master > 0) {
        grantpt(master);
        unlockpt(master);

        printf("Slave: %s\n", ptsname(master));

        while ((c = read(master, &rx, 1)) == 1) {
            if (rx == '\r') {
                rxbuf[i] = 0;
                sprintf(txbuf, "from slave: %s\r", rxbuf);  // 等同于屏幕输入
                write(master, txbuf, strlen(txbuf));        // 等同于键盘输入
            } else {
                rxbuf[i++] = rx;
            }
        }
    }
    else {
        printf("create pty error...\n");
    }

    return 0;
}
tiansong@tiansong:~/Desktop/linux$ gcc master.c -o master.out
tiansong@tiansong:~/Desktop/linux$ ./master.out   // 不终止
Slave: /dev/pts/0

slave.c

#define _XOPEN_SOURCE  600
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>

int main(int argc, char *argv[])
{
    int slave = open(argv[1], O_RDWR);  // 等同于 shell

    if (slave > 0) {
        char buf[256] = {0};
        char *data = "D.T.Software\r";
        int len = strlen(data);

        write(slave, data, len);

        sleep(1);

        len = read(slave, buf, sizeof(buf) - 1);
        buf[(len > 0) ? len : 0] = 0;

        printf("Read: %s\n", buf);  // system(...)

        close(slave);
    }
    else {

    }

    return 0;
}
tiansong@tiansong:~/Desktop/linux$ gcc slave.c -o slave.out
tiansong@tiansong:~/Desktop/linux$ ./slave.out /dev/pts/0  // 新终端执行
Read: from slave: D.T.Software

终端必然与过程关联才有意义!那么,过程之间除了父子关系,是否还有其它关系?

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理