?? tty_io.c
字號(hào):
/* passed* linux/kernel/tty_io.c** (C) 1991 Linus Torvalds*/#include <set_seg.h>
/** 'tty_io.c'給tty 一種非相關(guān)的感覺(jué),是控制臺(tái)還是串行通道。該程序同樣* 實(shí)現(xiàn)了回顯、規(guī)范(熟)模式等。** Kill-line,謝謝John T Kahl。*/#include <ctype.h> // 字符類(lèi)型頭文件。定義了一些有關(guān)字符類(lèi)型判斷和轉(zhuǎn)換的宏。#include <errno.h> // 錯(cuò)誤號(hào)頭文件。包含系統(tǒng)中各種出錯(cuò)號(hào)。(Linus 從minix 中引進(jìn)的)。#include <signal.h> // 信號(hào)頭文件。定義信號(hào)符號(hào)常量,信號(hào)結(jié)構(gòu)以及信號(hào)操作函數(shù)原型。// 下面給出相應(yīng)信號(hào)在信號(hào)位圖中的對(duì)應(yīng)比特位。#define ALRMMASK (1<<(SIGALRM-1)) // 警告(alarm)信號(hào)屏蔽位。#define KILLMASK (1<<(SIGKILL-1)) // 終止(kill)信號(hào)屏蔽位。#define INTMASK (1<<(SIGINT-1)) // 鍵盤(pán)中斷(int)信號(hào)屏蔽位。#define QUITMASK (1<<(SIGQUIT-1)) // 鍵盤(pán)退出(quit)信號(hào)屏蔽位。#define TSTPMASK (1<<(SIGTSTP-1)) // tty 發(fā)出的停止進(jìn)程(tty stop)信號(hào)屏蔽位。#include <linux/sched.h> // 調(diào)度程序頭文件,定義了任務(wù)結(jié)構(gòu)task_struct、初始任務(wù)0 的數(shù)據(jù),// 還有一些有關(guān)描述符參數(shù)設(shè)置和獲取的嵌入式匯編函數(shù)宏語(yǔ)句。#include <linux/tty.h> // tty 頭文件,定義了有關(guān)tty_io,串行通信方面的參數(shù)、常數(shù)。#include <asm/segment.h> // 段操作頭文件。定義了有關(guān)段寄存器操作的嵌入式匯編函數(shù)。#include <asm/system.h> // 系統(tǒng)頭文件。定義了設(shè)置或修改描述符/中斷門(mén)等的嵌入式匯編宏。#define _L_FLAG(tty,f) ((tty)->termios.c_lflag & f) // 取termios 結(jié)構(gòu)中的本地模式標(biāo)志。#define _I_FLAG(tty,f) ((tty)->termios.c_iflag & f) // 取termios 結(jié)構(gòu)中的輸入模式標(biāo)志。#define _O_FLAG(tty,f) ((tty)->termios.c_oflag & f) // 取termios 結(jié)構(gòu)中的輸出模式標(biāo)志。// 取termios 結(jié)構(gòu)中本地模式標(biāo)志集中的一個(gè)標(biāo)志位。#define L_CANON(tty) _L_FLAG((tty),ICANON) // 取本地模式標(biāo)志集中規(guī)范(熟)模式標(biāo)志位。#define L_ISIG(tty) _L_FLAG((tty),ISIG) // 取信號(hào)標(biāo)志位。#define L_ECHO(tty) _L_FLAG((tty),ECHO) // 取回顯字符標(biāo)志位。#define L_ECHOE(tty) _L_FLAG((tty),ECHOE) // 規(guī)范模式時(shí),取回顯擦出標(biāo)志位。#define L_ECHOK(tty) _L_FLAG((tty),ECHOK) // 規(guī)范模式時(shí),取KILL 擦除當(dāng)前行標(biāo)志位。#define L_ECHOCTL(tty) _L_FLAG((tty),ECHOCTL) // 取回顯控制字符標(biāo)志位。#define L_ECHOKE(tty) _L_FLAG((tty),ECHOKE) // 規(guī)范模式時(shí),取KILL 擦除行并回顯標(biāo)志位。// 取termios 結(jié)構(gòu)中輸入模式標(biāo)志中的一個(gè)標(biāo)志位。#define I_UCLC(tty) _I_FLAG((tty),IUCLC) // 取輸入模式標(biāo)志集中大寫(xiě)到小寫(xiě)轉(zhuǎn)換標(biāo)志位。#define I_NLCR(tty) _I_FLAG((tty),INLCR) // 取換行符NL 轉(zhuǎn)回車(chē)符CR 標(biāo)志位。#define I_CRNL(tty) _I_FLAG((tty),ICRNL) // 取回車(chē)符CR 轉(zhuǎn)換行符NL 標(biāo)志位。#define I_NOCR(tty) _I_FLAG((tty),IGNCR) // 取忽略回車(chē)符CR 標(biāo)志位。// 取termios 結(jié)構(gòu)中輸出模式標(biāo)志中的一個(gè)標(biāo)志位。#define O_POST(tty) _O_FLAG((tty),OPOST) // 取輸出模式標(biāo)志集中執(zhí)行輸出處理標(biāo)志。#define O_NLCR(tty) _O_FLAG((tty),ONLCR) // 取換行符NL 轉(zhuǎn)回車(chē)換行符CR-NL 標(biāo)志。#define O_CRNL(tty) _O_FLAG((tty),OCRNL) // 取回車(chē)符CR 轉(zhuǎn)換行符NL 標(biāo)志。#define O_NLRET(tty) _O_FLAG((tty),ONLRET) // 取換行符NL 執(zhí)行回車(chē)功能的標(biāo)志。#define O_LCUC(tty) _O_FLAG((tty),OLCUC) // 取小寫(xiě)轉(zhuǎn)大寫(xiě)字符標(biāo)志。// tty 數(shù)據(jù)結(jié)構(gòu)的tty_table 數(shù)組。其中包含三個(gè)初始化項(xiàng)數(shù)據(jù),分別對(duì)應(yīng)控制臺(tái)、串口終端1 和// 串口終端2 的初始化數(shù)據(jù)。struct tty_struct tty_table[] = {{ {//termios
ICRNL, /* 將輸入的CR 轉(zhuǎn)換為NL */ OPOST | ONLCR, /* 將輸出的NL 轉(zhuǎn)CRNL */ 0, // 控制模式標(biāo)志初始化為0。 ISIG | ICANON | ECHO | ECHOCTL | ECHOKE, // 本地模式標(biāo)志。 0, /* 控制臺(tái)termio。 */ INIT_C_CC // 控制字符數(shù)組。
}, 0, /* 所屬初始進(jìn)程組。 */ 0, /* 初始停止標(biāo)志。 */ con_write, // tty 寫(xiě)函數(shù)指針。 {0, 0, 0, 0, ""}, /* console read-queue */// tty 控制臺(tái)讀隊(duì)列。 {0, 0, 0, 0, ""}, /* console write-queue */// tty 控制臺(tái)寫(xiě)隊(duì)列。 {0, 0, 0, 0, ""} /* console secondary queue */// tty 控制臺(tái)輔助(第二)隊(duì)列。}, { {
0, /* no translation */// 輸入模式標(biāo)志。0,無(wú)須轉(zhuǎn)換。 0, /* no translation */// 輸出模式標(biāo)志。0,無(wú)須轉(zhuǎn)換。 B2400 | CS8, // 控制模式標(biāo)志。波特率2400bps,8 位數(shù)據(jù)位。 0, // 本地模式標(biāo)志0。 0, // 行規(guī)程0。 INIT_C_CC
}, // 控制字符數(shù)組。 0, // 所屬初始進(jìn)程組。 0, // 初始停止標(biāo)志。 rs_write, // 串口1 tty 寫(xiě)函數(shù)指針。 {0x3f8, 0, 0, 0, ""}, /* rs 1 */// 串行終端1 讀緩沖隊(duì)列。 {0x3f8, 0, 0, 0, ""}, // 串行終端1 寫(xiě)緩沖隊(duì)列。 {0, 0, 0, 0, ""} // 串行終端1 輔助緩沖隊(duì)列。}, { {
0, /* no translation */// 輸入模式標(biāo)志。0,無(wú)須轉(zhuǎn)換。 0, /* no translation */// 輸出模式標(biāo)志。0,無(wú)須轉(zhuǎn)換。 B2400 | CS8, // 控制模式標(biāo)志。波特率2400bps,8 位數(shù)據(jù)位。 0, // 本地模式標(biāo)志0。 0, // 行規(guī)程0。 INIT_C_CC
}, // 控制字符數(shù)組。 0, // 所屬初始進(jìn)程組。 0, // 初始停止標(biāo)志。 rs_write, // 串口2 tty 寫(xiě)函數(shù)指針。 {0x2f8, 0, 0, 0, ""}, /* rs 2 */// 串行終端2 讀緩沖隊(duì)列。 {0x2f8, 0, 0, 0, ""}, // 串行終端2 寫(xiě)緩沖隊(duì)列。 {0, 0, 0, 0, ""} // 串行終端2 輔助緩沖隊(duì)列。}};/** 下面是匯編程序使用的緩沖隊(duì)列地址表。通過(guò)修改你可以實(shí)現(xiàn)* 偽tty 終端或其它終端類(lèi)型。目前還沒(méi)有這樣做。*/// tty 緩沖隊(duì)列地址表。rs_io.s 匯編程序使用,用于取得讀寫(xiě)緩沖隊(duì)列地址。struct tty_queue *table_list[] = { &tty_table[0].read_q, &tty_table[0].write_q, // 控制臺(tái)終端讀、寫(xiě)緩沖隊(duì)列地址。 &tty_table[1].read_q, &tty_table[1].write_q, // 串行口1 終端讀、寫(xiě)緩沖隊(duì)列地址。 &tty_table[2].read_q, &tty_table[2].write_q // 串行口2 終端讀、寫(xiě)緩沖隊(duì)列地址。};//// tty 終端初始化函數(shù)。// 初始化串口終端和控制臺(tái)終端。void tty_init (void){ rs_init (); // 初始化串行中斷程序和串行接口1 和2。(serial.c, 37) con_init (); // 初始化控制臺(tái)終端。(console.c, 617)}//// tty 鍵盤(pán)終端字符處理函數(shù)。// 參數(shù):tty - 相應(yīng)tty 終端結(jié)構(gòu)指針;mask - 信號(hào)屏蔽位。void tty_intr (struct tty_struct *tty, int mask){ int i;// 如果tty 所屬組號(hào)小于等于0,則退出。 if (tty->pgrp <= 0) return;// 掃描任務(wù)數(shù)組,向tty 相應(yīng)組的所有任務(wù)發(fā)送指定的信號(hào)。 for (i = 0; i < NR_TASKS; i++) { // 如果該項(xiàng)任務(wù)指針不為空,并且其組號(hào)等于tty 組號(hào),則設(shè)置該任務(wù)指定的信號(hào)mask。 if (task[i] && task[i]->pgrp == tty->pgrp) task[i]->signal |= mask;
}}//// 如果隊(duì)列緩沖區(qū)空則讓進(jìn)程進(jìn)入可中斷的睡眠狀態(tài)。// 參數(shù):queue - 指定隊(duì)列的指針。// 進(jìn)程在取隊(duì)列緩沖區(qū)中字符時(shí)調(diào)用此函數(shù)。static voidsleep_if_empty (struct tty_queue *queue){ cli (); // 關(guān)中斷。// 若當(dāng)前進(jìn)程沒(méi)有信號(hào)要處理并且指定的隊(duì)列緩沖區(qū)空,則讓進(jìn)程進(jìn)入可中斷睡眠狀態(tài),并讓// 隊(duì)列的進(jìn)程等待指針指向該進(jìn)程。 while (!current->signal && EMPTY (*queue)) interruptible_sleep_on (&queue->proc_list); sti (); // 開(kāi)中斷。}//// 若隊(duì)列緩沖區(qū)滿(mǎn)則讓進(jìn)程進(jìn)入可中斷的睡眠狀態(tài)。// 參數(shù):queue - 指定隊(duì)列的指針。// 進(jìn)程在往隊(duì)列緩沖區(qū)中寫(xiě)入時(shí)調(diào)用此函數(shù)。static voidsleep_if_full (struct tty_queue *queue){// 若隊(duì)列緩沖區(qū)不滿(mǎn),則返回退出。 if (!FULL (*queue)) return; cli (); // 關(guān)中斷。// 如果進(jìn)程沒(méi)有信號(hào)需要處理并且隊(duì)列緩沖區(qū)中空閑剩余區(qū)長(zhǎng)度<128,則讓進(jìn)程進(jìn)入可中斷睡眠狀態(tài),// 并讓該隊(duì)列的進(jìn)程等待指針指向該進(jìn)程。 while (!current->signal && LEFT (*queue) < 128) interruptible_sleep_on (&queue->proc_list); sti (); // 開(kāi)中斷。}//// 等待按鍵。// 如果控制臺(tái)的讀隊(duì)列緩沖區(qū)空則讓進(jìn)程進(jìn)入可中斷的睡眠狀態(tài)。void wait_for_keypress (void){ sleep_if_empty (&tty_table[0].secondary);}//// 復(fù)制成規(guī)范模式字符序列。// 將指定tty 終端隊(duì)列緩沖區(qū)中的字符復(fù)制成規(guī)范(熟)模式字符并存放在輔助隊(duì)列(規(guī)范模式隊(duì)列)中。// 參數(shù):tty - 指定終端的tty 結(jié)構(gòu)。void copy_to_cooked (struct tty_struct *tty){ signed char c;// 如果tty 的讀隊(duì)列緩沖區(qū)不空并且輔助隊(duì)列緩沖區(qū)為空,則循環(huán)執(zhí)行下列代碼。 while (!EMPTY (tty->read_q) && !FULL (tty->secondary)) {// 從隊(duì)列尾處取一字符到c,并前移尾指針。 GETCH (tty->read_q, c);// 下面對(duì)輸入字符,利用輸入模式標(biāo)志集進(jìn)行處理。// 如果該字符是回車(chē)符CR(13),則:若回車(chē)轉(zhuǎn)換行標(biāo)志CRNL 置位則將該字符轉(zhuǎn)換為換行符NL(10);// 否則若忽略回車(chē)標(biāo)志NOCR 置位,則忽略該字符,繼續(xù)處理其它字符。 if (c == 13) { if (I_CRNL (tty)) c = 10; else if (I_NOCR (tty)) continue; else;// 如果該字符是換行符NL(10)并且換行轉(zhuǎn)回車(chē)標(biāo)志NLCR 置位,則將其轉(zhuǎn)換為回車(chē)符CR(13)。 } else if (c == 10 && I_NLCR (tty)) c = 13;// 如果大寫(xiě)轉(zhuǎn)小寫(xiě)標(biāo)志UCLC 置位,則將該字符轉(zhuǎn)換為小寫(xiě)字符。 if (I_UCLC (tty)) c = tolower (c);// 如果本地模式標(biāo)志集中規(guī)范(熟)模式標(biāo)志CANON 置位,則進(jìn)行以下處理。 if (L_CANON (tty)) {// 如果該字符是鍵盤(pán)終止控制字符KILL(^U),則進(jìn)行刪除輸入行處理。 if (c == KILL_CHAR (tty)) {/* deal with killing the input line *//* 刪除輸入行處理 */// 如果tty 輔助隊(duì)列不空,或者輔助隊(duì)列中最后一個(gè)字符是換行NL(10),或者該字符是文件結(jié)束字符// (^D),則循環(huán)執(zhí)行下列代碼。 while (!(EMPTY (tty->secondary) || (c = LAST (tty->secondary)) == 10 || c == EOF_CHAR (tty))) {// 如果本地回顯標(biāo)志ECHO 置位,那么:若字符是控制字符(值<32),則往tty 的寫(xiě)隊(duì)列中放入擦除// 字符ERASE。再放入一個(gè)擦除字符ERASE,并且調(diào)用該tty 的寫(xiě)函數(shù)。 if (L_ECHO (tty)) { if (c < 32) PUTCH (127, tty->write_q); PUTCH (127, tty->write_q); tty->write (tty); }// 將tty 輔助隊(duì)列頭指針后退1 字節(jié)。 DEC (tty->secondary.head); } continue; // 繼續(xù)讀取并處理其它字符。 }// 如果該字符是刪除控制字符ERASE(^H),那么: if (c == ERASE_CHAR (tty)) {// 若tty 的輔助隊(duì)列為空,或者其最后一個(gè)字符是換行符NL(10),或者是文件結(jié)束符,繼續(xù)處理// 其它字符。 if (EMPTY (tty->secondary) || (c = LAST (tty->secondary)) == 10 || c == EOF_CHAR (tty)) continue;// 如果本地回顯標(biāo)志ECHO 置位,那么:若字符是控制字符(值<32),則往tty 的寫(xiě)隊(duì)列中放入擦除// 字符ERASE。再放入一個(gè)擦除字符ERASE,并且調(diào)用該tty 的寫(xiě)函數(shù)。 if (L_ECHO (tty)) { if (c < 32) PUTCH (127, tty->write_q); PUTCH (127, tty->write_q); tty->write (tty); }// 將tty 輔助隊(duì)列頭指針后退1 字節(jié),繼續(xù)處理其它字符。 DEC (tty->secondary.head); continue;
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -