當(dāng)前位置:首頁 > 公眾號精選 > 21ic電子網(wǎng)
[導(dǎo)讀]前言 鍵盤可以說是我們最常使用的輸入硬件設(shè)備了,但身為程序員的你,你知道「鍵盤敲入 A 字母時(shí),操作系統(tǒng)期間發(fā)生了什么嗎」? 那要想知道這個發(fā)生的過程,我們得先了解了解「操作系統(tǒng)是如何管理多種多樣的的輸入輸出設(shè)備」的,等了解完這個后,我們再來看

鍵盤敲入 A 字母時(shí),操作系統(tǒng)期間發(fā)生了什么...

前言

鍵盤可以說是我們最常使用的輸入硬件設(shè)備了,但身為程序員的你,你知道「鍵盤敲入 A 字母時(shí),操作系統(tǒng)期間發(fā)生了什么嗎」?

那要想知道這個發(fā)生的過程,我們得先了解了解「操作系統(tǒng)是如何管理多種多樣的的輸入輸出設(shè)備」的,等了解完這個后,我們再來看看這個問題,你就會發(fā)現(xiàn)問題已經(jīng)被迎刃而解了。

鍵盤敲入 A 字母時(shí),操作系統(tǒng)期間發(fā)生了什么...

正文

設(shè)備控制器

我們的電腦設(shè)備可以接非常多的輸入輸出設(shè)備,比如鍵盤、鼠標(biāo)、顯示器、網(wǎng)卡、硬盤、打印機(jī)、音響等等,每個設(shè)備的用法和功能都不同,那操作系統(tǒng)是如何把這些輸入輸出設(shè)備統(tǒng)一管理的呢?

為了屏蔽設(shè)備之間的差異,每個設(shè)備都有一個叫設(shè)備控制器(Device Control 的組件,比如硬盤有硬盤控制器、顯示器有視頻控制器等。

因?yàn)檫@些控制器都很清楚的知道對應(yīng)設(shè)備的用法和功能,所以 CPU 是通過設(shè)備控制器來和設(shè)備打交道的。

設(shè)備控制器里有芯片,它可執(zhí)行自己的邏輯,也有自己的寄存器,用來與 CPU 進(jìn)行通信,比如:

  • 通過寫入這些寄存器,操作系統(tǒng)可以命令設(shè)備發(fā)送數(shù)據(jù)、接收數(shù)據(jù)、開啟或關(guān)閉,或者執(zhí)行某些其他操作。

  • 通過讀取這些寄存器,操作系統(tǒng)可以了解設(shè)備的狀態(tài),是否準(zhǔn)備好接收一個新的命令等。

實(shí)際上,控制器是有三類寄存器,它們分別是狀態(tài)寄存器(Status Register、 命令寄存器(Command Register以及數(shù)據(jù)寄存器(Data Register,如下圖:

鍵盤敲入 A 字母時(shí),操作系統(tǒng)期間發(fā)生了什么...

這三個寄存器的作用:

  • 數(shù)據(jù)寄存器,CPU 向 I/O 設(shè)備寫入需要傳輸?shù)臄?shù)據(jù),比如要打印的內(nèi)容是「Hello」,CPU 就要先發(fā)送一個 H 字符給到對應(yīng)的 I/O 設(shè)備。

  • 命令寄存器,CPU 發(fā)送一個命令,告訴 I/O 設(shè)備,要進(jìn)行輸入/輸出操作,于是就會交給 I/O 設(shè)備去工作,任務(wù)完成后,會把狀態(tài)寄存器里面的狀態(tài)標(biāo)記為完成。

  • 狀態(tài)寄存器,目的是告訴 CPU ,現(xiàn)在已經(jīng)在工作或工作已經(jīng)完成,如果已經(jīng)在工作狀態(tài),CPU 再發(fā)送數(shù)據(jù)或者命令過來,都是沒有用的,直到前面的工作已經(jīng)完成,狀態(tài)寄存標(biāo)記成已完成,CPU 才能發(fā)送下一個字符和命令。

CPU 通過讀、寫設(shè)備控制器中的寄存器來控制設(shè)備,這可比 CPU 直接控制輸入輸出設(shè)備,要方便和標(biāo)準(zhǔn)很多。

另外, 輸入輸出設(shè)備可分為兩大類 :塊設(shè)備(Block Device字符設(shè)備(Character Device。

  • 塊設(shè)備,把數(shù)據(jù)存儲在固定大小的塊中,每個塊有自己的地址,硬盤、USB 是常見的塊設(shè)備。

  • 字符設(shè)備,以字符為單位發(fā)送或接收一個字符流,字符設(shè)備是不可尋址的,也沒有任何尋道操作,鼠標(biāo)是常見的字符設(shè)備。

塊設(shè)備通常傳輸?shù)臄?shù)據(jù)量會非常大,于是控制器設(shè)立了一個可讀寫的數(shù)據(jù)緩沖區(qū)。

  • CPU 寫入數(shù)據(jù)到控制器的緩沖區(qū)時(shí),當(dāng)緩沖區(qū)的數(shù)據(jù)囤夠了一部分,才會發(fā)給設(shè)備。

  • CPU 從控制器的緩沖區(qū)讀取數(shù)據(jù)時(shí),也需要緩沖區(qū)囤夠了一部分,才拷貝到內(nèi)存。

這樣做是為了,減少對設(shè)備的操作次數(shù)。

那 CPU 是如何與設(shè)備的控制寄存器和數(shù)據(jù)緩沖區(qū)進(jìn)行通信的?存在兩個方法:

  • 端口 I/O,每個控制寄存器被分配一個 I/O 端口,可以通過特殊的匯編指令操作這些寄存器,比如 in/out類似的指令。

  • 內(nèi)存映射 I/O,將所有控制寄存器映射到內(nèi)存空間中,這樣就可以像讀寫內(nèi)存一樣讀寫數(shù)據(jù)緩沖區(qū)。


I/O 控制方式

在前面我知道,每種設(shè)備都有一個設(shè)備控制器,控制器相當(dāng)于一個小 CPU,它可以自己處理一些事情,但有個問題是,當(dāng) CPU 給設(shè)備發(fā)送了一個指令,讓設(shè)備控制器去讀設(shè)備的數(shù)據(jù),它讀完的時(shí)候,要怎么通知 CPU 呢?

控制器的寄存器一般會有狀態(tài)標(biāo)記位,用來標(biāo)識輸入或輸出操作是否完成。于是,我們想到第一種輪詢等待的方法,讓 CPU 一直查寄存器的狀態(tài),直到狀態(tài)標(biāo)記為完成,很明顯,這種方式非常的傻瓜,它會占用 CPU 的全部時(shí)間。

那我們就想到第二種方法 —— 中斷,通知操作系統(tǒng)數(shù)據(jù)已經(jīng)準(zhǔn)備好了。我們一般會有一個硬件的中斷控制器,當(dāng)設(shè)備完成任務(wù)后觸發(fā)中斷到中斷控制器,中斷控制器就通知 CPU,一個中斷產(chǎn)生了,CPU 需要停下當(dāng)前手里的事情來處理中斷。

另外,中斷有兩種,一種軟中斷,例如代碼調(diào)用 INT指令觸發(fā),一種是硬件中斷,就是硬件通過中斷控制器觸發(fā)的。

但中斷的方式對于頻繁讀寫數(shù)據(jù)的磁盤,并不友好,這樣 CPU 容易經(jīng)常被打斷,會占用 CPU 大量的時(shí)間。對于這一類設(shè)備的問題的解決方法是使用 DMA(Direct Memory Access 功能,它可以使得設(shè)備在 CPU 不參與的情況下,能夠自行完成把設(shè)備 I/O 數(shù)據(jù)放入到內(nèi)存。那要實(shí)現(xiàn) DMA 功能要有 「DMA 控制器」硬件的支持。

鍵盤敲入 A 字母時(shí),操作系統(tǒng)期間發(fā)生了什么...

DMA 的工作方式如下:

  • CPU 需對 DMA 控制器下發(fā)指令,告訴它想讀取多少數(shù)據(jù),讀完的數(shù)據(jù)放在內(nèi)存的某個地方就可以了;

  • 接下來,DMA 控制器會向磁盤控制器發(fā)出指令,通知它從磁盤讀數(shù)據(jù)到其內(nèi)部的緩沖區(qū)中,接著磁盤控制器將緩沖區(qū)的數(shù)據(jù)傳輸?shù)絻?nèi)存;

  • 當(dāng)磁盤控制器把數(shù)據(jù)傳輸?shù)絻?nèi)存的操作完成后,磁盤控制器在總線上發(fā)出一個確認(rèn)成功的信號到 DMA 控制器;

  • DMA 控制器收到信號后,DMA 控制器發(fā)中斷通知 CPU 指令完成,CPU 就可以直接用內(nèi)存里面現(xiàn)成的數(shù)據(jù)了;

可以看到, CPU 當(dāng)要讀取磁盤數(shù)據(jù)的時(shí)候,只需給 DMA 控制器發(fā)送指令,然后返回去做其他事情,當(dāng)磁盤數(shù)據(jù)拷貝到內(nèi)存后,DMA 控制機(jī)器通過中斷的方式,告訴 CPU 數(shù)據(jù)已經(jīng)準(zhǔn)備好了,可以從內(nèi)存讀數(shù)據(jù)了。僅僅在傳送開始和結(jié)束時(shí)需要 CPU 干預(yù)。


設(shè)備驅(qū)動程序

雖然設(shè)備控制器屏蔽了設(shè)備的眾多細(xì)節(jié),但每種設(shè)備的控制器的寄存器、緩沖區(qū)等使用模式都是不同的,所以為了屏蔽「設(shè)備控制器」的差異,引入了設(shè)備驅(qū)動程序。

設(shè)備控制器不屬于操作系統(tǒng)范疇,它是屬于硬件,而設(shè)備驅(qū)動程序?qū)儆诓僮飨到y(tǒng)的一部分,操作系統(tǒng)的內(nèi)核代碼可以像本地調(diào)用代碼一樣使用設(shè)備驅(qū)動程序的接口,而設(shè)備驅(qū)動程序是面向設(shè)備控制器的代碼,它發(fā)出操控設(shè)備控制器的指令后,才可以操作設(shè)備控制器。

不同的設(shè)備控制器雖然功能不同,但是設(shè)備驅(qū)動程序會提供統(tǒng)一的接口給操作系統(tǒng),這樣不同的設(shè)備驅(qū)動程序,就可以以相同的方式接入操作系統(tǒng)。如下圖:

鍵盤敲入 A 字母時(shí),操作系統(tǒng)期間發(fā)生了什么...

前面提到了不少關(guān)于中斷的事情,設(shè)備完成了事情,則會發(fā)送中斷來通知操作系統(tǒng)。那操作系統(tǒng)就需要有一個地方來處理這個中斷,這個地方也就是在設(shè)備驅(qū)動程序里,它會及時(shí)響應(yīng)控制器發(fā)來的中斷請求,并根據(jù)這個中斷的類型調(diào)用響應(yīng)的中斷處理程序進(jìn)行處理。

通常,設(shè)備驅(qū)動程序初始化的時(shí)候,要先注冊一個該設(shè)備的中斷處理函數(shù)。

鍵盤敲入 A 字母時(shí),操作系統(tǒng)期間發(fā)生了什么...

我們來看看,中斷處理程序的處理流程:

  1. 在 I/O 時(shí),設(shè)備控制器如果已經(jīng)準(zhǔn)備好數(shù)據(jù),則會通過中斷控制器向 CPU 發(fā)送中斷請求;

  2. 保護(hù)被中斷進(jìn)程的 CPU 上下文;

  3. 轉(zhuǎn)入相應(yīng)的設(shè)備中斷處理函數(shù);

  4. 進(jìn)行中斷處理;

  5. 恢復(fù)被中斷進(jìn)程的上下文;


通用塊層

對于塊設(shè)備,為了減少不同塊設(shè)備的差異帶來的影響,Linux 通過一個統(tǒng)一的通用塊層,來管理不同的塊設(shè)備。

通用塊層是處于文件系統(tǒng)和磁盤驅(qū)動中間的一個塊設(shè)備抽象層,它主要有兩個功能:

  • 第一個功能,向上為文件系統(tǒng)和應(yīng)用程序,提供訪問塊設(shè)備的標(biāo)準(zhǔn)接口,向下把各種不同的磁盤設(shè)備抽象為統(tǒng)一的塊設(shè)備,并在內(nèi)核層面,提供一個框架來管理這些設(shè)備的驅(qū)動程序;

  • 第二功能,通用層還會給文件系統(tǒng)和應(yīng)用程序發(fā)來的 I/O 請求排隊(duì),接著會對隊(duì)列重新排序、請求合并等方式,也就是 I/O 調(diào)度,主要目的是為了提高磁盤讀寫的效率。

Linux 內(nèi)存支持 5 種 I/O 調(diào)度算法,分別是:

  • 沒有調(diào)度算法

  • 先入先出調(diào)度算法

  • 完全公平調(diào)度算法

  • 優(yōu)先級調(diào)度

  • 最終期限調(diào)度算法

第一種,沒有調(diào)度算法,是的,你沒聽錯,它不對文件系統(tǒng)和應(yīng)用程序的 I/O 做任何處理,這種算法常用在虛擬機(jī) I/O 中,此時(shí)磁盤 I/O 調(diào)度算法交由物理機(jī)系統(tǒng)負(fù)責(zé)。

第二種,先入先出調(diào)度算法,這是最簡單的 I/O 調(diào)度算法,先進(jìn)入 I/O 調(diào)度隊(duì)列的 I/O 請求先發(fā)生。

第三種,完全公平調(diào)度算法,大部分系統(tǒng)都把這個算法作為默認(rèn)的 I/O 調(diào)度器,它為每個進(jìn)程維護(hù)了一個 I/O 調(diào)度隊(duì)列,并按照時(shí)間片來均勻分布每個進(jìn)程的 I/O 請求。

第四種,優(yōu)先級調(diào)度算法,顧名思義,優(yōu)先級高的 I/O 請求先發(fā)生, 它適用于運(yùn)行大量進(jìn)程的系統(tǒng),像是桌面環(huán)境、多媒體應(yīng)用等。

第五種,最終期限調(diào)度算法,分別為讀、寫請求創(chuàng)建了不同的 I/O 隊(duì)列,這樣可以提高機(jī)械磁盤的吞吐量,并確保達(dá)到最終期限的請求被優(yōu)先處理,適用于在 I/O 壓力比較大的場景,比如數(shù)據(jù)庫等。


存儲系統(tǒng) I/O 軟件分層

前面說到了不少東西,設(shè)備、設(shè)備控制器、驅(qū)動程序、通用塊層,現(xiàn)在再結(jié)合文件系統(tǒng)原理,我們來看看 Linux 存儲系統(tǒng)的 I/O 軟件分層。

可以把 Linux 存儲系統(tǒng)的 I/O 由上到下可以分為三個層次,分別是文件系統(tǒng)層、通用塊層、設(shè)備層。他們整個的層次關(guān)系如下圖:

鍵盤敲入 A 字母時(shí),操作系統(tǒng)期間發(fā)生了什么...

這三個層次的作用是:

  • 文件系統(tǒng)層,包括虛擬文件系統(tǒng)和其他文件系統(tǒng)的具體實(shí)現(xiàn),它向上為應(yīng)用程序統(tǒng)一提供了標(biāo)準(zhǔn)的文件訪問接口,向下會通過通用塊層來存儲和管理磁盤數(shù)據(jù)。

  • 通用塊層,包括塊設(shè)備的 I/O 隊(duì)列和 I/O 調(diào)度器,它會對文件系統(tǒng)的 I/O 請求進(jìn)行排隊(duì),再通過 I/O 調(diào)度器,選擇一個 I/O 發(fā)給下一層的設(shè)備層。

  • 設(shè)備層,包括硬件設(shè)備、設(shè)備控制器和驅(qū)動程序,負(fù)責(zé)最終物理設(shè)備的 I/O 操作。

有了文件系統(tǒng)接口之后,不但可以通過文件系統(tǒng)的命令行操作設(shè)備,也可以通過應(yīng)用程序,調(diào)用 read、write函數(shù),就像讀寫文件一樣操作設(shè)備,所以說設(shè)備在 Linux 下,也只是一個特殊的文件。

但是,除了讀寫操作,還需要有檢查特定于設(shè)備的功能和屬性。于是,需要 ioctl接口,它表示輸入輸出控制接口,是用于配置和修改特定設(shè)備屬性的通用接口。

另外,存儲系統(tǒng)的 I/O 是整個系統(tǒng)最慢的一個環(huán)節(jié),所以 Linux 提供了不少緩存機(jī)制來提高 I/O 的效率。

  • 為了提高文件訪問的效率,會使用頁緩存、索引節(jié)點(diǎn)緩存、目錄項(xiàng)緩存等多種緩存機(jī)制,目的是為了減少對塊設(shè)備的直接調(diào)用。

  • 為了提高塊設(shè)備的訪問效率, 會使用緩沖區(qū),來緩存塊設(shè)備的數(shù)據(jù)。


鍵盤敲入字母時(shí),期間發(fā)生了什么?

看完前面的內(nèi)容,相信你對輸入輸出設(shè)備的管理有了一定的認(rèn)識,那接下來就從操作系統(tǒng)的角度回答開頭的問題「鍵盤敲入字母時(shí),操作系統(tǒng)期間發(fā)生了什么?」

CPU 里面的內(nèi)存接口,直接和系統(tǒng)總線通信,然后系統(tǒng)總線再接入一個 I/O 橋接器,這個 I/O 橋接器,另一邊接入了內(nèi)存總線,使得 CPU 和內(nèi)存通信。再另一邊,又接入了一個 I/O 總線,用來連接 I/O 設(shè)備,比如鍵盤、顯示器等。

那當(dāng)用戶輸入了鍵盤字符,鍵盤控制器就會產(chǎn)生掃描碼數(shù)據(jù),并將其緩沖在鍵盤控制器的寄存器中,緊接著鍵盤控制器通過總線給 CPU 發(fā)送中斷請求

CPU 收到中斷請求后,操作系統(tǒng)保存被中斷進(jìn)程的 CPU 上下文,然后調(diào)用鍵盤的中斷處理程序。

鍵盤的中斷處理程序是在鍵盤驅(qū)動程序初始化時(shí)注冊的,那鍵盤中斷處理函數(shù)的功能就是從鍵盤控制器的寄存器的緩沖區(qū)讀取掃描碼,再根據(jù)掃描碼找到用戶在鍵盤輸入的字符,如果輸入的字符是顯示字符,那就會把掃描碼翻譯成對應(yīng)顯示字符的  ASCII 碼,比如用戶在鍵盤輸入的是字母 A,是顯示字符,于是就會把掃描碼翻譯成 A 字符的 ASCII 碼。

得到了顯示字符的 ASCII 碼后,就會把 ASCII 碼放到「讀緩沖區(qū)隊(duì)列」,接下來就是要把顯示字符顯示屏幕了,顯示設(shè)備的驅(qū)動程序會定時(shí)從「讀緩沖區(qū)隊(duì)列」讀取數(shù)據(jù)放到「寫緩沖區(qū)隊(duì)列」,最后把「寫緩沖區(qū)隊(duì)列」的數(shù)據(jù)一個一個寫入到顯示設(shè)備的控制器的寄存器中的數(shù)據(jù)緩沖區(qū),最后將這些數(shù)據(jù)顯示在屏幕里。

顯示出結(jié)果后,恢復(fù)被中斷進(jìn)程的上下文。


免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點(diǎn),不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!

21ic電子網(wǎng)

掃描二維碼,關(guān)注更多精彩內(nèi)容

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術(shù)解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關(guān)鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競爭優(yōu)勢...

關(guān)鍵字: 通信 BSP 電信運(yùn)營商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術(shù)學(xué)會聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(shù)(集團(tuán))股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉