偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

Linux 終端初始化 console_init 及 tty 驅(qū)動(dòng)框架

系統(tǒng) Linux
先前分析了 Linux 入口地址和 Linux 系統(tǒng)啟動(dòng)流程,本文詳細(xì)分析一下 Linux 啟動(dòng)流程中的 console_init 終端初始化函數(shù)。

[[427998]]

先前分析了 Linux 入口地址和 Linux 系統(tǒng)啟動(dòng)流程,本文詳細(xì)分析一下 Linux 啟動(dòng)流程中的 console_init 終端初始化函數(shù)。

上兩篇文章如下:

Linux 內(nèi)核入口分析

手把手教你分析 Linux 啟動(dòng)流程

講解終端初始化之前我們先講解一個(gè)概念:tty

在Linux系統(tǒng)中,終端是一類字符型設(shè)備,它包括多種類型,通常使用tty來(lái)簡(jiǎn)稱各種類型的終端設(shè)備。我們一般分為三類:

串口終端(/dev/ttyS*)

串口終端是使用計(jì)算機(jī)串口連接的終端設(shè)備。Linux 把每個(gè)串行端口都看作是一個(gè)字符設(shè)備。這些串行端口所對(duì)應(yīng)的設(shè)備名稱是 /dev/ttySAC0;/dev/ttySAC1……

控制臺(tái)終端(/dev/console)

在Linux系統(tǒng)中,計(jì)算機(jī)的輸出設(shè)備通常被稱為控制臺(tái)終端(Console),這里特指printk信息輸出到的設(shè)備。/dev/console是一個(gè)虛擬的設(shè)備,它需要映射到真正的tty(物理終端)上,比如通過(guò)內(nèi)核啟動(dòng)參數(shù)” console=ttySAC0”就把console映射到了串口0。

虛擬終端(/dev/tty*)

當(dāng)用戶登錄時(shí),使用的是虛擬終端。使用Ctcl+Alt+[F1—F6]組合鍵時(shí),我們就可以切換到tty1、tty2、tty3等上面去。tty1–tty6等稱為虛擬終端,而tty0則是當(dāng)前所使用虛擬終端的一個(gè)別名。

console_init 分析

Linux 啟動(dòng)函數(shù) start_kernel 會(huì)調(diào)用 console_init 函數(shù)。

linux4.14/kernel/printk/printk.c

linux4.14/drivers/tty/n_tty.c

我們可以看到,console_init 主要做了兩件事情:

1、n_tty_init 主要調(diào)用 tty_register_ldisc(N_TTY, &n_tty_ops) 注冊(cè) tty 線路規(guī)程。

  1. call = __con_initcall_start; 
  2.  while (call < __con_initcall_end) { 
  3.   (*call)(); 
  4.   call++; 
  5.  } 

這里主要是調(diào)用 __con_initcall_start 到 __con_initcall_end 之間的函數(shù)。

__con_initcall_start 和 __con_initcall_end 定義在:

linux4.14/include/asm-generic/vmlinux.lds.h

中間包含了 .con_initcall.init 段:

linux4.14/include/linux/init.h

我們通過(guò) console_init 聲明的驅(qū)動(dòng)模塊,就會(huì)出現(xiàn)在這個(gè)段中,被調(diào)用。普通我們聲明的驅(qū)動(dòng)模塊都是使用 module_init,如果我們寫的是串口驅(qū)動(dòng),可以使用console_init 聲明。

如果要看具體中間有什么函數(shù),可以查看編譯 Linux 內(nèi)核的輸出 System.map 文件,這個(gè)文件記載了從頭到尾 Linux 干了什么,具體的地址存儲(chǔ)了什么東西。

System.map 文件默認(rèn)在編譯后的 Linux 內(nèi)核根目錄下, 當(dāng)然我們也可以修改到其他目錄。

這里會(huì)有三列:地址,區(qū),函數(shù)名字。

如果后面我們使用 console_init(serial_5685_xxxx)去聲明我們的驅(qū)動(dòng),那么這個(gè) serial_5685_xxxx 就會(huì)出現(xiàn)在 __con_initcall_start 和 __con_initcall_end 之間,就會(huì)被調(diào)用。

initcall機(jī)制

注意上述流程,我們來(lái)理解一下 initcall 機(jī)制:

普通我們寫一個(gè)程序,想要它被調(diào)用,需要在主流程中調(diào)用這個(gè)函數(shù),才算被調(diào)用。

那么這種方式如果放在 Linux 中,是難以想象的,我們自己寫的代碼要在多少個(gè)地方聲明。

而你如果采用initcall機(jī)制,意思就是說(shuō),你使用一個(gè)字符串聲明你的驅(qū)動(dòng)初始化函數(shù),那么所有的驅(qū)動(dòng)初始化函數(shù)都存在內(nèi)存中一個(gè)連續(xù)的段中,系統(tǒng)啟動(dòng)以后,會(huì)從這個(gè)段的第一個(gè)函數(shù)開(kāi)始,一個(gè)一個(gè)遍歷,進(jìn)而一個(gè)一個(gè)調(diào)用,這就是 initcall 機(jī)制。這就是為什么我們寫驅(qū)動(dòng)只需要使用 module_init 聲明,編譯進(jìn)去即可自動(dòng)被調(diào)用的原因!!!

System.map

編譯后的內(nèi)核根目錄 System.map 文件記載了所有的驅(qū)動(dòng)加載順序,如果你不確定驅(qū)動(dòng)的加載順序,在這里查看就可以,每次編譯 Linux 內(nèi)核就會(huì)產(chǎn)生一個(gè)新的 System.map。

tty 驅(qū)動(dòng)

我們不要把 tty 驅(qū)動(dòng)和 串口驅(qū)動(dòng) 弄混了,tty 驅(qū)動(dòng)架構(gòu)如下:

其中 tty driver 等價(jià)于我們普通寫的驅(qū)動(dòng),可以自己寫。

也就是說(shuō),在 tty 驅(qū)動(dòng)框架主要有三層:tty core、tty line discipline、tty driver,另外最上層是用戶空間,最下層是硬件。

tty core 稱之為 tty 核心,主要作用是向用戶提供統(tǒng)一的接口。

tty line discipline 稱之為 tty 線路規(guī)程,主要從上下兩層接收數(shù)據(jù),并按照一定協(xié)議進(jìn)行轉(zhuǎn)換,比如 ppp 或者藍(lán)牙協(xié)議,這樣你的 tty 終端就不止可以用普通的串口,還可以通過(guò)其他協(xié)議訪問(wèn)到我們的系統(tǒng)。比如手機(jī)鏈接 PCB 板子的 WiFi 接入系統(tǒng)控制終端,輸入 ls、cd 等命令。這一層并不是必須的,你可以直接使用驅(qū)動(dòng)和 tty core 進(jìn)行通信,但一般這一層都會(huì)有。

tty driver 就是我們常說(shuō)的串口驅(qū)動(dòng)。

在 console_init 函數(shù)中,它做的兩件事,就是注冊(cè) tty 線路規(guī)程,注冊(cè) tty 驅(qū)動(dòng),tty 核心是包含在內(nèi)核當(dāng)中的。tty 線路規(guī)程和 tty 驅(qū)動(dòng)可以有很多個(gè)。

有的人會(huì)有疑問(wèn),為什么有了 tty 驅(qū)動(dòng)了,還會(huì)有一個(gè) tty 線路規(guī)程。得益于 Linux 模塊化的思想,這里主要是為了分層與隔離。tty 驅(qū)動(dòng)只和硬件相關(guān),只解析基本的硬件信息,把硬件信息轉(zhuǎn)換成字符。所有的對(duì)字符的進(jìn)一步處理包括加入藍(lán)牙協(xié)議傳輸,監(jiān)控?cái)?shù)據(jù)等都放在 tty 線路規(guī)程當(dāng)中。這樣 tty 驅(qū)動(dòng)是可以完美復(fù)用和移植的。

分享一張彭大佬的圖,本文我只講了概念,彭大佬講解過(guò) tty 源碼:

這里只需要注意一點(diǎn),在右下角,tty driver 是沒(méi)有 read 函數(shù)的,tty driver 層有 buffer,輸入的數(shù)據(jù)會(huì)存儲(chǔ)在 buffer 中,被讀取。

原因很簡(jiǎn)單,對(duì)于 tty 來(lái)說(shuō),輸入設(shè)備和輸出設(shè)備不是同一個(gè)設(shè)備,輸入設(shè)備是鍵盤,輸出設(shè)備是屏幕,這和普通的 IIC、SPI 驅(qū)動(dòng)同一個(gè)設(shè)備不一樣。因此在設(shè)計(jì)上 tty driver 沒(méi)有 read 函數(shù)。

本文轉(zhuǎn)載自微信公眾號(hào)「嵌入式Linux系統(tǒng)開(kāi)發(fā)」

 

責(zé)任編輯:姜華 來(lái)源: 嵌入式Linux系統(tǒng)開(kāi)發(fā)
相關(guān)推薦

2021-02-05 12:04:45

LinuxUARTLinux系統(tǒng)

2020-11-13 10:06:47

XignCode3

2025-01-03 08:53:59

2011-03-31 16:46:10

LinuxMySQL

2023-11-12 23:08:17

C++初始化

2012-12-28 14:53:34

Android開(kāi)發(fā)初始化窗體事件

2010-02-24 15:41:19

Linux Light

2022-01-06 16:16:21

鴻蒙HarmonyOS應(yīng)用

2019-11-04 13:50:36

Java數(shù)組編程語(yǔ)言

2009-09-08 09:48:34

LINQ初始化數(shù)組

2009-11-11 15:29:15

ADO初始化

2010-07-28 10:22:33

FlexApplica

2021-03-12 10:30:11

SpringMVC流程初始化

2022-07-06 10:37:45

SpringServlet初始化

2020-12-03 09:50:52

容器IoC流程

2011-06-17 15:29:44

C#對(duì)象初始化器集合初始化器

2011-07-06 14:16:25

Linux服務(wù)器Shell腳本

2010-06-21 10:25:09

Linux APM

2024-01-15 06:34:09

Gin鏡像容器

2017-09-13 14:28:02

Linux初始化系統(tǒng)運(yùn)行級(jí)別
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)