#### 两种模式

键盘驱动程序的基本工作就是收集键盘输入并把它传给用户程序。键盘驱动程序有两种设计哲学：一是驱动程序仅仅接收输入并不加修改地向上传递，这种思想是基于字符的，被叫做**生模式**(raw mode)，在POSIX里也叫**非规范模式**(noncanonical mode)。二是驱动程序处理行内的编辑并向用户程序交付正确的行，这种思想则是基于行的，被叫做**熟模式**(cooked mode)，在POSIX里也叫**规范模式**(canonical mode)。

#### 两个任务

键盘驱动程序的第一个任务是收集字符。如果每次击键都产生中断，驱动程序就可以在中断过程中拿到字符。如果底层软件把中断转成了消息，则可以把新得到的字符放在消息里。也可以把字符放进缓冲区，再通过消息告诉驱动程序接收到了一些东西。

键盘驱动程序的第二个任务是处理字符。如果键盘传递的是键码而非字符码，则驱动程序需要利用表来把键码转换成字符码。仅有ASCII码是不够的，为了支持不同的语言，许多操作系统都提供了可装载的**键盘映射**(keymaps)或**码页**(code pages)，建立键码和字符码之间的映射。

不管是生模式还是熟模式，都要把字符缓冲起来。有两种字符缓冲的方法。

第一种缓冲方法是把缓冲区集中到一块，每个缓冲区大约容纳10个字符。与终端相关的数据结构只是包含缓冲区的指针。这种方法比较省空间但实现会复杂一点。

第二种方法是直接把缓冲区放在与终端相关的数据结构里。每个缓冲区大约容纳200个字符。这种方法是实现简单但占用空间比较大。

#### 几个问题

键盘驱动程序要考虑应用程序的输出、回显(echoing)、TAB键的问题。

- 程序把输入打印到屏幕上的操作叫**回显**(echoing)。要考虑回显和程序输出会冲突的问题。

- 驱动程序要处理TAB键回显的问题，它需要计算出光标的正确位置。

回车(carriage return)与换行(linefeed)的问题。

- 回车的确切含义是把光标移到第一列(还在同一行)。换行的确切含义是把光标移到下一行(还在同一列)。
- 对于类Unix系统，换行的意思是即回车又换行，这种情况下即使输入的是回车也应改为换行。
- 对于即需要回车又需要换行的系统，则不管输入的是回车还是换行，都需要转换成即有回车也有换行。
- 在某些系统上，回车或换行比其它字符花的时间要多。这就需要驱动程序在输出流里插入填充字符(filler character，就是假的空字符)或等一段时间。

#### 规范模式下的特殊字符

| 字符   | POSIX名 | 含义                          |
| ------ | ------- | ----------------------------- |
| Crtl+D | EOF     | 文件末尾                      |
|        | EOL     | 行末尾(末定义)                |
| Crtl+H | ERASE   | 回退一个字符                  |
| Crtl+C | INTR    | 中断进程                      |
| Crtl+U | KILL    | 删除整行                      |
| Crtl+\ | QUIT    | 强制内核转储(Force core dump) |
| Crtl+Z | SUSP    | 挂起(Suspend)                 |
| Crtl+Q | START   | 开始输出                      |
| Crtl+S | STOP    | 停止输出                      |
| Crtl+M | CR      | 回车(不可改变)                |
| Crtl+J | NL      | 换行(不可改变)                |



