1. 概念
终端:terminal 简称term, 早期的计算机系统是多任务多用户操作系统,这样一台只有显示器和键盘能通过串口连接到计算机的设备就叫做终端。
终端不是计算机本身就有的设备,终端是附加设备。
控制台:console,在计算机里把那套直接连接到电脑的键盘和显示器叫做控制台,一个计算机只有一个控制台,计算机启动时,会将所有信息都显示到控制台上,而不是终端上。
Echo “hello zz” > /dev/console
虚拟字符哑终端或虚拟控制台终端(tty1-tty6数量可以在/etc/inittab里自己调整) :
通过gettty软件虚拟出来,上述终端
虚拟图形终端:也是通过gettty软件虚拟出来,在虚拟图形终端中又可以通过软件(如rxvt)再虚拟无限多个伪终端(pts/0等)
输入命令:tty
可以查看当前终端, 测试 echo “hello” > /dev/tty
2. 伪终端pty
伪终端(Pseudo Terminal)是终端的发展,为满足现在需求(比如telnet、ssh、xterm、xwindow窗口的管理等)
例如: 如果某人在网上使用telnet程序连接到你的计算机上,则telnet程序就可能会打开/dev/ptmx设备获取一个fd。此时一个getty程序就应该运行在对应的/dev/pts/?上。当telnet从远端获取了一个字符时,该字符就会通过ptmx、pts/传递给 getty程序,getty程序在将收到的数据发送到指定的pts/?伪终端上;
伪终端发送数据时,getty程序就会通过pts/、ptmx和telnet程序往网络上返回“login:”字符串信息。这样,登录程序与telnet程序就通过“伪终端”进行通信。
telnet ====================> [ telnetd进程 ---> /dev/ptmx(master) ---> /dev/pts/?(slave) ---> getty ]
3. 设置终端属性函数的使用
int tcgetattr(int fd, struct termios *termios_p);
int tcsetattr(int fd, int optional_actions, const struct termios *termios_p);
例子:关闭ctrl-c/ctrl-z信号
tcgetattr(STDIN_FILENO, &orig_termios);
struct termios raw = orig_termios;
raw.c_lflag &= ~(ISIG);
tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw);
开启: raw.c_lflag |= ISIG;
信号
信号的概念
常见信号的一个处理流程如下图:
信号.png图1:信号处理流程
Linux系统中可以使用kill –l 查看系统定义的信号列表
编号34以上的是实时信号,可以通过man 7 signal查看
产生信号的条件:
a) 用户按下某些键
b) 硬件异常产生信号
c) 一个进程可以调用kill(2)函数发送信号给另一个进程
d) 当内核检测到某种软件条件发生时也可以通过信号通知进程,例如闹钟超时产生SIGALRM信号,向读端已关闭的管道写数据时产生SIGPIPE信号
用户进程对信号的处理方式:
使用sigaction(2)函数处理。
a) 忽略此信号, SIGKILL 和 SIGSTOP这个两个信号无法捕捉或忽略;
b) 执行该信号的默认处理动作;
c) 提供一个信号处理函数,要求内核在处理该信号时切换到用户态执行这个处理函数,这种方式称为捕捉(catch)一个信号。
阻塞信号
信号递达(Delivery) : 实际执行信号的处理动作称为信号递达;
信号未决(Pending) : 信号从产生到递达之间的状态称为信号未决;
信号阻塞(Block):被阻塞的信号将保持在未决状态,直到进程解除对此信号的阻塞,才执行
注册信号
Struct sigaction stSignalAct;
Memset(&stSignalAct, 0, sizeof(struct sigaction));
stSignalAct.sa_sigaction = SignalHand;
stSignalAct.sa_flags = SA_SIGINFO; // 注意这个设置
IRet = sigaction(SIGINT, &stSignalAct, NULL);
信号处理函数SignalHand中不能包含可能出现死循环的代码
参考:https://viewsourcecode.org/snaptoken/kilo/02.enteringRawMode.html
网友评论