控制檯¶
結構體 Console¶
-
enum cons_flags¶
通用控制檯標誌
常量
CON_PRINTBUFFER由新註冊的控制檯使用,以避免重複輸出已被引導控制檯顯示或使用者空間透過 syslog() 系統呼叫讀取的訊息。
CON_CONSDEV指示控制檯驅動程式正在支援 /dev/console。
CON_ENABLED指示是否允許控制檯列印記錄。 如果為 false,控制檯也不會前進到後面的記錄。
CON_BOOT將控制檯驅動程式標記為早期控制檯驅動程式,該驅動程式在啟動期間在真實驅動程式可用之前使用。 當註冊真實的控制檯驅動程式時,它將自動登出,除非使用“keep_bootcon”引數。
CON_ANYTIME一個用詞不當的歷史標誌,它告訴核心程式碼,傳統的 console::write 回撥可以在標記為 OFFLINE 的 CPU 上呼叫。 這是具有誤導性的,因為它表明呼叫回撥沒有上下文限制。 最初的動機是每個 CPU 區域的就緒狀態。
CON_BRL指示盲文裝置,出於顯而易見的原因,該裝置可以免於接收 printk 垃圾郵件。
CON_EXTENDED控制檯支援 /dev/kmesg 的擴充套件輸出格式,這需要更大的輸出緩衝區。
CON_SUSPENDED指示控制檯是否已掛起。 如果為 true,則不得呼叫列印回撥。
CON_NBCON控制檯可以在傳統的 console_lock 約束之外執行。
-
struct console¶
控制檯描述符結構
定義:
struct console {
char name[16];
void (*write)(struct console *co, const char *s, unsigned int count);
int (*read)(struct console *co, char *s, unsigned int count);
struct tty_driver *(*device)(struct console *co, int *index);
void (*unblank)(void);
int (*setup)(struct console *co, char *options);
int (*exit)(struct console *co);
int (*match)(struct console *co, char *name, int idx, char *options);
short flags;
short index;
int cflag;
uint ispeed;
uint ospeed;
u64 seq;
unsigned long dropped;
void *data;
struct hlist_node node;
void (*write_atomic)(struct console *con, struct nbcon_write_context *wctxt);
void (*write_thread)(struct console *con, struct nbcon_write_context *wctxt);
void (*device_lock)(struct console *con, unsigned long *flags);
void (*device_unlock)(struct console *con, unsigned long flags);
atomic_t __private nbcon_state;
atomic_long_t __private nbcon_seq;
struct nbcon_context __private nbcon_device_ctxt;
atomic_long_t __private nbcon_prev_seq;
struct printk_buffers *pbufs;
struct task_struct *kthread;
struct rcuwait rcuwait;
struct irq_work irq_work;
};
成員
name控制檯驅動程式的名稱
write用於輸出訊息的傳統寫入回撥(可選)
read用於控制檯輸入的讀取回調(可選)
device底層 TTY 裝置驅動程式(可選)
unblank用於取消消隱控制檯的回撥(可選)
setup用於初始化控制檯的回撥(可選)
exit用於拆卸控制檯的回撥(可選)
match用於匹配控制檯的回撥(可選)
flags控制檯標誌。 請參見
enum cons_flagsindex控制檯索引,例如埠號
cflagTTY 控制模式標誌
ispeedTTY 輸入速度
ospeedTTY 輸出速度
seq要列印的下一個環形緩衝區記錄的序列號
dropped未報告的丟棄的環形緩衝區記錄數
data驅動程式私有資料
node控制檯列表的 hlist 節點
write_atomic用於在任何上下文中寫出文字的 NBCON 回撥。(可選)
在呼叫此回撥時,控制檯已被獲取。 但是,預設情況下允許更高優先順序的上下文接管它。
回撥必須在任何接管不安全的程式碼周圍呼叫 nbcon_enter_unsafe() 和 nbcon_exit_unsafe(),例如,在操作序列埠暫存器時。
如果在該上下文失去控制檯所有權的同時,nbcon_enter_unsafe() 將失敗。 在這種情況下,不再允許回撥繼續進行。 它必須立即小心地退出。 緩衝區內容也不再可信,因為它不再屬於上下文。
回撥應在安全的情況下允許接管。 這增加了在系統出現問題時檢視訊息的機會。 如果驅動程式必須重新獲取所有權才能最終確定或恢復硬體更改,則可以使用 nbcon_reacquire_nobuf()。 但是,重新獲取後,緩衝區內容不再可用。 重新獲取不能用於恢復列印。
可以從任何上下文(包括 NMI)呼叫回撥。 因此,它必須避免使用任何鎖定,而是依靠控制檯所有權進行同步。
write_thread用於在任務上下文中寫出文字的 NBCON 回撥。
只能在任務上下文中呼叫此回撥,並且必須使用 NBCON_PRIO_NORMAL 獲取 device_lock() 和 nbcon 控制檯。
控制檯所有權驗證和不安全區域處理的規則與 write_atomic() 相同。
控制檯所有權處理對於與僅透過上下文同步的 write_atomic() 進行同步是必需的。
device_lock() 為裝置上的操作提供主要序列化。 它可以根據需要寬鬆(互斥)[*] 或緊密(停用搶佔和中斷)。 它允許 kthread 在限制最少的模式下執行 [**]。
- [*] 啟用了搶佔後,獨立的 nbcon_context_try_acquire() 不安全,請參閱 nbcon_owner_matches()。 但是,當始終在裝置鎖下的搶佔上下文中呼叫它時,它可以是安全的。
the preemption enabled, see nbcon_owner_matches(). But it can be safe when always called in the preemptive context under the device_lock().
- [**] device_lock() 確保 nbcon_context_try_acquire()
would never need to spin which is important especially with PREEMPT_RT.
device_lock用於開始與驅動程式程式碼同步的 NBCON 回撥。
控制檯驅動程式通常必須處理透過使用者輸入/輸出(例如互動式登入 shell)對硬體的訪問,以及透過
printk()呼叫輸出核心訊息。 每當 printk 子系統需要與驅動程式的硬體訪問同步時,都會呼叫此回撥。 應該實現它以使用驅動程式自身正在使用的任何同步機制(例如,用於 uart 序列控制檯的埠鎖)。始終從任務上下文中呼叫回撥。 它可以使用驅動程式所需的任何同步方法。
- 重要提示:回撥必須停用遷移。 控制檯驅動程式
may be using a synchronization mechanism that already takes care of this (such as spinlocks). Otherwise this function must explicitly call migrate_disable().
flags 引數作為驅動程式的便利提供。 它將再次傳遞給 device_unlock()。 如果驅動程式不需要它,則可以忽略它。
device_unlock用於完成與驅動程式程式碼同步的 NBCON 回撥。
它是 device_lock() 的對應項。
始終從任務上下文中呼叫此回撥。 它必須適當地重新啟用遷移(具體取決於 device_lock() 如何停用遷移)。
flags 引數是傳遞給 device_lock() 的同一變數的值。
nbcon_statenbcon 控制檯的狀態
nbcon_seqnbcon 要列印的下一條記錄的序列號
nbcon_device_ctxt可用於非列印操作的上下文
nbcon_prev_seq上次 nbcon 所有者被分配列印的序列號
pbufs指向 nbcon 私有緩衝區的指標
kthread此控制檯的印表機 kthread
rcuwait用於 kthread 喚醒的 RCU 安全等待物件
irq_work將 kthread 喚醒推遲到 IRQ 工作上下文
內部結構¶
-
struct nbcon_state¶
nbcon 控制檯的控制檯狀態
定義:
struct nbcon_state {
union {
unsigned int atom;
struct {
unsigned int prio : 2;
unsigned int req_prio : 2;
unsigned int unsafe : 1;
unsigned int unsafe_takeover : 1;
unsigned int cpu : 24;
};
};
};
成員
{unnamed_union}anonymous
atom用於原子操作的狀態欄位的複合
{unnamed_struct}anonymous
prio當前所有者的優先順序
req_prio切換請求的優先順序
unsafe控制檯在一個非接管區域中處於忙碌狀態
unsafe_takeover過去發生了不安全狀態下的惡意接管。 在重新初始化之前,控制檯無法安全。
cpu所有者在其上執行的 CPU
描述
用於讀取和準備儲存在 nbcon 狀態變數 console::nbcon_state 中的值。
prio 和 req_prio 欄位尤其重要,允許旋轉等待超時並放棄,而不會有等待者在放棄後被分配鎖的風險。
-
enum nbcon_prio¶
nbcon 控制檯的控制檯所有者優先順序
常量
NBCON_PRIO_NONE未使用
NBCON_PRIO_NORMAL正常(非緊急)使用
NBCON_PRIO_EMERGENCY緊急輸出 (WARN/OOPS...)
NBCON_PRIO_PANICPanic 輸出
NBCON_PRIO_MAX優先順序級別的數量
描述
當控制檯處於安全狀態時,更高優先順序的上下文可以接管控制檯。 在 panic() 中重新整理控制檯的最後一次嘗試甚至可以在不安全狀態下進行(希望和祈禱)。
-
struct nbcon_context¶
用於控制檯獲取/釋放的上下文
定義:
struct nbcon_context {
struct console *console;
unsigned int spinwait_max_us;
enum nbcon_prio prio;
unsigned int allow_unsafe_takeover : 1;
unsigned int backlog : 1;
struct printk_buffers *pbufs;
u64 seq;
};
成員
console關聯的控制檯
spinwait_max_us旋轉等待獲取的限制
prio上下文的優先順序
allow_unsafe_takeover即使不安全也允許執行接管。 只能與 NBCON_PRIO_PANIC prio 一起使用。 當稍後使用控制檯時,它可能會導致系統凍結。
backlog環形緩衝區具有待處理的記錄
pbufs指向此上下文的文字緩衝區的指標
seq要為此上下文列印的序列號
-
struct nbcon_write_context¶
傳遞給 nbcon 寫入回撥的上下文
定義:
struct nbcon_write_context {
struct nbcon_context __private ctxt;
char *outbuf;
unsigned int len;
bool unsafe_takeover;
};
成員
ctxt核心控制檯上下文
outbuf指向用於輸出的文字緩衝區的指標
len要寫入的長度
unsafe_takeover如果發生了不安全狀態下的惡意接管
結構體 Consw¶
-
struct consw¶
用於控制檯的回撥
定義:
struct consw {
struct module *owner;
const char *(*con_startup)(void);
void (*con_init)(struct vc_data *vc, bool init);
void (*con_deinit)(struct vc_data *vc);
void (*con_clear)(struct vc_data *vc, unsigned int y, unsigned int x, unsigned int count);
void (*con_putc)(struct vc_data *vc, u16 ca, unsigned int y, unsigned int x);
void (*con_putcs)(struct vc_data *vc, const u16 *s,unsigned int count, unsigned int ypos, unsigned int xpos);
void (*con_cursor)(struct vc_data *vc, bool enable);
bool (*con_scroll)(struct vc_data *vc, unsigned int top,unsigned int bottom, enum con_scroll dir, unsigned int lines);
bool (*con_switch)(struct vc_data *vc);
bool (*con_blank)(struct vc_data *vc, enum vesa_blank_mode blank, bool mode_switch);
int (*con_font_set)(struct vc_data *vc,const struct console_font *font, unsigned int vpitch, unsigned int flags);
int (*con_font_get)(struct vc_data *vc, struct console_font *font, unsigned int vpitch);
int (*con_font_default)(struct vc_data *vc, struct console_font *font, const char *name);
int (*con_resize)(struct vc_data *vc, unsigned int width, unsigned int height, bool from_user);
void (*con_set_palette)(struct vc_data *vc, const unsigned char *table);
void (*con_scrolldelta)(struct vc_data *vc, int lines);
bool (*con_set_origin)(struct vc_data *vc);
void (*con_save_screen)(struct vc_data *vc);
u8 (*con_build_attr)(struct vc_data *vc, u8 color,enum vc_intensity intensity, bool blink, bool underline, bool reverse, bool italic);
void (*con_invert_region)(struct vc_data *vc, u16 *p, int count);
void (*con_debug_enter)(struct vc_data *vc);
void (*con_debug_leave)(struct vc_data *vc);
};
成員
owner當使用此控制檯時,要獲取引用的模組
con_startup設定控制檯並返回其名稱(如 VGA、EGA 等)
con_init在 vc 上初始化控制檯。 對於在此 vc 上的第一次呼叫,init 為 true。
con_deinit從 vc 中取消初始化控制檯。
con_clear在 vc 上的 [x, y] 處擦除 count 個字元。 count >= 1。
con_putc使用屬性 ca 將一個字元傳送到 vc 上的 [x, y]。 (可選 -- 將呼叫 con_putcs)
con_putcs使用屬性 s 將 count 個字元傳送到 vc 上的 [x, y]。
con_cursor根據 enable 啟用/停用游標
con_scroll按 lines 在方向 dir 中將 top 到 bottom 的行移動。 如果不應進行通用處理,則返回 true。 由 csi_M 呼叫和列印到控制檯。
con_switch有關控制檯切換的通知器; 如果需要重繪,則應返回 true。
con_blank消隱/取消消隱控制檯。 目標模式在 blank 中傳遞。 如果從/向文字/圖形更改,則設定 mode_switch。 如果需要重繪,則掛鉤應返回 true。
con_font_set將控制檯 vc 字型設定為高度為 vpitch 的 font。 flags 可以是
KD_FONT_FLAG_DONT_RECALC。(可選)con_font_get在高度為 vpitch 的 vc 上獲取當前字型到 font 中。(可選)
con_font_default在 vc 上設定預設字型。 name 可以是
NULL或要搜尋的字型名稱。 可以將 font 填充回。(可選)con_resize將 vc 控制檯調整為 width x height。 當此更改來自使用者空間時,from_user 為 true。
con_set_palette將控制檯 vc 的調色盤設定為 table(可選)
con_scrolldelta控制檯的內容應按 lines 滾動。 由使用者呼叫。(可選)
con_set_origin設定 vc 的原點(請參閱
vc_data::vc_origin)。 如果未提供或返回 false,則原點設定為 vc->vc_screenbuf。(可選)con_save_screen將螢幕內容儲存到 vc->vc_screenbuf 中。 例如,在進入圖形時呼叫。(可選)
con_build_attr基於 color、intensity 和其他引數構建屬性。 結果用於普通字元和擦除字元。(可選)
con_invert_region反轉 vc 上從 p 開始的長度為 count 的區域。(可選)
con_debug_enter為偵錯程式準備控制檯。 這包括但不限於,取消消隱控制檯、載入適當的調色盤和允許偵錯程式生成的輸出。(可選)
con_debug_leave儘可能將控制檯恢復到除錯前的狀態。(可選)
控制檯函式¶
引數
const struct console *con要從中讀取標誌的控制檯的
struct console指標
描述
以無鎖方式讀取 con->flags 提供了 Read 一致的值,因為最多隻有一個 CPU 正在修改 con->flags,並且該 CPU 僅使用讀取-修改-寫入操作來執行此操作。
需要保持 console_srcu_read_lock,這意味著 con 可能是已註冊的控制檯。 保持 console_srcu_read_lock 的目的是保證控制檯狀態有效 (CON_SUSPENDED/CON_ENABLED),並且如果控制檯當前正在登出,則不會執行任何退出/清理例程。
如果呼叫方保持 console_list_lock,或者 _certain_ con 未註冊且不會變為已註冊,則呼叫方可以直接讀取 con->flags。
上下文
任何上下文。
返回
con->flags 欄位的當前值。
引數
struct console *con要寫入標誌的控制檯的
struct console指標short flags要寫入的新標誌值
描述
僅使用此函式為已註冊的控制檯寫入標誌。 它需要保持 console_list_lock。
上下文
任何上下文。
-
for_each_console_srcu¶
for_each_console_srcu (con)
遍歷已註冊的控制檯
引數
con用作循環遊標的
struct console指標
描述
儘管 SRCU 保證控制檯列表將保持一致,但在迭代時,struct console 欄位可能會被其他 CPU 更新。
需要保持 console_srcu_read_lock。 可以從任何上下文中呼叫。
-
for_each_console¶
for_each_console (con)
遍歷已註冊的控制檯
-
void clear_selection(void)¶
刪除當前選擇
引數
void無引數
描述
從保持選擇的控制檯中刪除當前選擇突出顯示(如果有)。
鎖定:呼叫方必須保持控制檯鎖。
-
int __vc_resize(struct vc_data *vc, unsigned int cols, unsigned int rows, bool from_user)¶
調整 VT 的大小
引數
struct vc_data *vc虛擬控制檯
unsigned int cols列
unsigned int rows行
bool from_user由使用者呼叫?
描述
從控制檯的角度來看,調整虛擬控制檯的大小。 我們使用通用的 vc_do_resize() 方法來更新結構。
鎖定:呼叫方必須保持控制檯 sem 以保護控制檯內部結構和 vc->port.tty。
引數
const struct consw *csw控制檯驅動程式
返回
如果未繫結,則為零; 如果已繫結,則為非零
描述
驅動程式可以呼叫此函式,如果為零,則應釋放 consw.con_startup() 上分配的所有資源
-
bool con_is_visible(const struct vc_data *vc)¶
檢查當前控制檯是否可見
引數
const struct vc_data *vc虛擬控制檯
返回
如果不可見,則為零; 如果可見,則為非零
-
void con_debug_enter(struct vc_data *vc)¶
為核心偵錯程式準備控制檯
引數
struct vc_data *vc虛擬控制檯
描述
當控制檯被核心偵錯程式接管時呼叫,此函式需要儲存當前控制檯狀態,然後將控制檯置於適合核心偵錯程式的狀態。
-
void con_debug_leave(void)¶
恢復控制檯狀態
引數
void無引數
描述
將控制檯狀態恢復到呼叫核心偵錯程式之前的狀態。
引數
const struct consw *csw控制檯驅動程式
描述
所有註冊到控制檯層的驅動程式都必須在退出時呼叫此函式,或者如果控制檯驅動程式處於無法處理控制檯服務的狀態,例如沒有載入幀緩衝驅動程式的幀緩衝控制檯。
驅動程式必須先取消繫結,然後才能登出。
內部結構¶
-
int sel_loadlut(u32 __user *lut)¶
載入 LUT 表
引數
u32 __user *lut使用者表
描述
從使用者空間載入 LUT 表。 建立一個臨時副本,以便部分更新不會造成混亂。
鎖定:已獲取控制檯鎖。
-
int set_selection_user(const struct tiocl_selection __user *sel, struct tty_struct *tty)¶
設定當前選擇。
引數
const struct tiocl_selection __user *sel使用者選擇資訊
struct tty_struct *tty控制檯 tty
描述
由 vt 層的 ioctl 控制代碼呼叫。
鎖定:整個選擇過程都在 console_lock 下進行管理。 它在鎖定下進行了很多處理,但這幾乎不是效能路徑。
-
int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, unsigned int cols, unsigned int lines, bool from_user)¶
tty 的調整大小方法
引數
struct tty_struct *tty正在調整大小的 tty
struct vc_data *vc虛擬控制檯私有資料
unsigned int cols列
unsigned int lines行數
bool from_user由使用者呼叫?
描述
調整虛擬控制檯的大小,根據實際約束進行裁剪。 如果呼叫者傳遞了一個 tty 結構,則更新 termios winsize 資訊並執行任何必要的訊號處理。
鎖定:呼叫者必須持有控制檯訊號量。 如果傳遞了 tty,則獲取 tty 的 termios rwsem 和 ctrl.lock。
-
int vt_resize(struct tty_struct *tty, struct winsize *ws)¶
調整 VT 的大小
引數
struct tty_struct *tty要調整大小的 tty
struct winsize *wswinsize 屬性
描述
調整虛擬終端的大小。 這是由 tty 層呼叫的,因為我們註冊了自己的調整大小處理程式。 互助助手完成了所有實際工作。
鎖定:獲取控制檯訊號量,然後被呼叫的方法按順序獲取 tty termios_rwsem 和 tty ctrl.lock。
-
enum vc_ctl_state¶
vt 的控制字元狀態
常量
ESnormal初始狀態,未解析控制字元
ESesc已解析 ESC
ESsquare已解析 CSI -- 預期修飾符/引數/控制字元
ESgetpars已解析 CSI -- 預期引數/控制字元
ESfunckey已解析 CSI [
EShash已解析 ESC #
ESsetG0已解析 ESC (
ESsetG1已解析 ESC )
ESpercent已解析 ESC %
EScsiignore已解析 CSI [0x20-0x3f]
ESnonstd已解析 OSC
ESpalette已解析 OSC P
ESosc已解析 OSC [0-9]
ESANSI_first用於忽略 ansi 控制序列的第一個狀態
ESapc已解析 ESC _
ESpm已解析 ESC ^
ESdcs已解析 ESC P
ESANSI_last用於忽略 ansi 控制序列的最後一個狀態
-
int vc_sanitize_unicode(const int c)¶
將無效的 Unicode 程式碼點替換為
U+FFFD
引數
const int c收到的程式碼點
-
int vc_translate_unicode(struct vc_data *vc, int c, bool *rescan)¶
在
vc_data.vc_utf_char中將 UTF-8 組合成 Unicode
引數
struct vc_data *vc虛擬控制檯
int c要翻譯的 UTF-8 位元組
bool *rescan如果 c 未在此處使用並且需要重新處理,則設定為 true
描述
vc_data.vc_utf_char是正在構建的 Unicode 程式碼點。vc_data.vc_utf_count是仍然期望到達的延續位元組數。vc_data.vc_npar是到目前為止到達的延續位元組數。
返回
-1- 到目前為止輸入正常,c 已使用,預期有更多位元組。0xFFFD- 可能性 1:輸入無效,可能已使用 c(請參閱rescan 的描述)。 可能性 2:輸入正常,已使用 c,
U+FFFD是生成的程式碼點。U+FFFD有效,REPLACEMENT CHARACTER。
否則 - 輸入正常,已使用 c,返回生成的程式碼點。
-
int vt_kmsg_redirect(int new)¶
設定/獲取核心訊息控制檯
引數
int new新的虛擬終端編號,如果控制檯應保持不變,則為 -1
描述
預設情況下,核心訊息始終列印在當前的虛擬控制檯上。 但是,使用者可以使用 TIOCL_SETKMSGREDIRECT ioctl 呼叫修改該預設值。
此函式將核心訊息控制檯設定為 new。 它返回舊的虛擬控制檯編號。 虛擬終端編號 0(作為引數和返回值)表示沒有重定向(即始終列印在當前活動的控制檯上)。
引數 -1 表示僅返回當前控制檯,但不修改該值。 在這種情況下,可以使用宏 vt_get_kmsg_redirect() 來使程式碼更易於理解。
如果核心在沒有 CONFIG_VT_CONSOLE 的情況下編譯,則此函式會忽略該引數並始終返回 0。