-
CPU
-
CPU和各個存儲器
- 寄存器:接近于CPU的工作頻率,是CPU的本地存儲器,位于運算器和控制器中,在進程的切換時,寄存器會被清空
- 一級緩存:比寄存器稍慢,頻率同樣接近于CPU,只能用于緩存數據,不能像寄存器一樣修改數據,各個核心都有自己的私有一級緩存,進程切換時不被清空
- 二級緩存:比一級緩存慢,多個核心都有自己私有的二級緩存
-
三級緩存:比二級緩存慢,如果有多個核心的CPU,那么三級緩存為多個核心的共享區域
- 多顆cpu共享三級緩存或是內存的時候,就會出現了一個問題,即資源征用。
-
現在在很多CPU上都引入了NUMA機制(非一致性內存訪問):
- 將三級緩存分割,分別讓不同的CPU占用不同的內存地址,這樣我們可以理解他們都有自己的三級緩存區域,不會存在資源搶奪的問題,但是要注意的是他們還是同一塊三級緩存。就好像北京市有朝陽區,豐臺區,大興區,海淀區等等
- 那么問題來了,基于重新負載的結果,如果cpu1運行的進程被掛起,其地址在他自己的緩存中是有記錄的,但是當cpu2再次運行這個程式的時候被CPU2中的緩存沒有該進程的緩存,又是如何處理的呢?
- 這就沒法了,只能從CPU1的三級區域中復制一份地址過來或是移動過來一份讓CPU2來處理,這個時候是需要一定時間的。所以說重新負載均衡會導致CPU性能降低。這個時候我們就可以用進程綁定來實現,讓再次處理該進程的時候還是用之前處理的CPU來處理。即進程和CPU的親緣性
- 內存:比CPU的頻率慢的多,如果直接讓內存和CPU相連,那么會導致計算機性能很差,因為CPU發出取指令的信息后,需要等待很長時間后內存才吐出數據給CPU,假設CPU的工作頻率在1ns一次那么需要等10個時鐘周期內存才能響應,內存的工作頻率為10ns,所以需要加中間層來按照程式的局部特性緩存數據
- 固態硬盤或機械硬盤
-
程式局部性原理:
- 空間局部性:程式是由指令和數據組成的??臻g局部性指的是一個數據被訪問到之后,那么離這個數據很近的其他數據隨后也可能會被訪問到
- 時間局部性:一般而言當一個程式執行完畢后,可能很快會被訪問到。數據也是同樣的原理,一個數據的被訪問到,很可能會再次訪問到
- 正是因為程式局部性的存在,所以使得無論是在空間局部性或者時間的局部性的角度來考慮,一般而言我們都需要對數據做緩存
-
CPU和各個存儲器的工作邏輯
- CPU能操作數據是在寄存器中操作的,操作動作如:1+1修改某個變量的值,修改的值最終被存儲在內存中,內存再同步到磁盤(磁盤為外部的IO設備可以不用考慮,因為計算機的核心就是運算器、控制器和存儲器)
-
首先寄存器中需要從一級緩存中取數據,如果1級沒有到2級取,2級沒有到3級,直到內存。寄存器將數據修改完成,會將結果保存到1級,2級,3級,內存;CPU在處理完數據后,會有兩種寫數據的方式到緩存或內存
- 通寫:寫到內存中,CPU才能繼續其他工作,因為結果保存在1級或2級那么如果該進程被調度到其他核心上,那么就找不到上一次運行的結果了,所以需要讓數據盡快的寫到內存中
- 回寫:寫到一級緩存中,就告訴CPU完成,性能很好
-
CPU多核心和進程線程
- 多核心的CPU的每個核心都相當于一個CPU,如果在一個web服務器上,有100個進程,其中97個進程是長時間處于睡眠狀態,2個進程需要偶爾運行一下,1個處于超級繁忙狀態,別的進程都不需要工作,就這一個web進程需要占用大量的額CPU時間,但CPU有4個核心,這4個核心就不能得到充分利用,因此如果要某個服務器上只有單個進程繁忙時,發揮CPU的最大用途,就需要程式并行編程,讓這個進程產生多個線程跑在多個核心的CPU上
- 線程的產生是將進程中串行的指令執行流做成多個并行的指令執行流,多個執行流互不相關,比如400個指令的進程,將它分為100個一組的4個線程,這樣的編程叫做并行編程。但這樣存在著問題,因為線程與線程之間存在著一定程度上的聯系,比如1.第二個線程可能需要第一個線程的結果,2.線程之間是共享進程資源的,如進程打開的文件描述符,當一個線程在操作一個文件的時候,另外的線程只能是等待狀態。所以程式員都必須要精細的設計程式,否則一個進程中的多個線程可能彼此之間協調就不流暢。比如在我們的網路IO模型中,web服務器的一個進程生成多個線程來處理用戶請求時,好在大多用戶的請求都是get讀操作,那么多個線程就可以同時讀取數據,掙用資源的時間并不多,所以這樣的程式設計模式,就實現了網絡IO模型中的多路復用模型
- 當CPU將某個線程中的指令調度到某個核心中執行完后,下一次調度可能會不在同一個核心,這樣導致緩存無法命中,因為在執行指令時,因為內存速度相對于CPU的速度是很慢的,所以在獲取數據時先從一級緩存中獲取,如果沒有然后2級,再沒有最后從內存中獲取,如果調往另外的核心,那么另外核心上的123級的緩存中將沒有之前程式需要的緩存數據,所以需要實現進程和CPU綁定的機制,相當于是nginx中的會話綁定一樣
- 多核心CPU在調度線程來運行時,通常都相同于nginx中的調度一樣,CPU的哪個核心閑就往哪個核心上調度,并且每一秒中balance一次,每個核心上都有兩個進程隊列(等待隊列和空閑隊列),如果有400個進程每個核心上有100個進程在排隊,如果某個時刻后,一個核心上的進程全部運行完畢,而一個核心上依然有很多進程沒有運行完,那么內核會rebalance一次
-
進程的上下文切換:
- 在一個進程要調度到CPU上來運行的過程查看
- 當進程A的運行時間片結束后,會有另外一個進程B調度到CPU上運行,而進程A的運行的狀態信息(如在運算器中執行的哪條指令,在控制器中下一條指令的地址),都會被保存到進程的PCB(PCB存在于內存)中,第二次將進程A調度到CPU上運行時,會從內存中A的PCB的現場狀態信息取到CPU中的寄存器中,繼續之前的操作,這個叫進程的上下文切換,進程的上下文切換的過程是很繁瑣的
- HTTPD的prefork模型是1個進程處理1個用戶的請求,如果有1000個用戶并發訪問,那么進程的上下文切換會很頻繁,而nginx由一個進程來處理多個用戶的請求,所以不用再切換省去了大量的切換時間
-
CPU和各個存儲器
-
IO設備:
- 由設備控制器和設備本身組成,相對于CPU和內存,這樣的設備屬于外部設備
-
設備控制器:集成在主板的一塊芯片活一組芯片。負責從操作系統接收命令,并完成命令的執行。比如操作系統要讀取磁盤的某個文件,控制器在接收到命令后,將命令轉化為對應物理設備的物理操作
- 設備控制器的驅動程式:設備控制器將操作系統的命令轉化為對應物理設備的電氣操作,是依賴于控制器中的驅動程式來完成的(而不是內核),所以驅動程式應該由設備生產商來研發,但是由于有些驅動程式過于通用,所以很多驅動程式被集成在了內核中
- 設備控制器的寄存器:每個控制器都有少量的用于通信的寄存器(幾個到幾十個不等)。這個寄存器是直接集成到設備控制器內部的。如:磁盤控制器,它內部都會有一些空間用于存儲指定磁盤地址,扇區計數,讀寫方向等相關操作信息,這些空間都是寄存器。所以任何時候想要激活控制器,設備驅動程式從操作系統中接收操作指令,然后將它轉換成對應設備的電氣操作指令,并把這樣的操作指令放置在寄存器中,硬件設備才能完成操作。
- 設備本身:其有自己的接口,但是設備本身的接口并不可用,它只是一個物理接口。如IDE接口
- 磁盤緩存:又稱磁盤快取,實際上就是將下載到的數據先保存于系統為軟件分配的內存空間中(這個內存空間被稱之為“內存池”),當保存到內存池中的數據達到一個程度時,便將數據保存到硬盤中。這樣可以減少實際的磁盤操作,有效的保護磁盤免于重復的讀寫操作而導致的損壞
- 從內存寫數據到磁盤同樣有兩種方式:通寫(內核控制內存中的數據寫入到磁盤的某個位置則完成工作)、回寫(內核控制內存中的數據寫入到磁盤緩存,內核則釋放,之后磁盤控制器自己將磁盤緩存中的數據寫入磁盤)
-
實現輸入和輸出
- 每個寄存器表現為一個IO地址端口。所有的寄存器組合稱為設備的I/O地址空間,也叫I/O端口空間,設備的I/O端口沒法事前分配,因為各個主板的型號不一致,所以我們需要做到動態指定。電腦在開機的時候,每個IO設備都要向總線的I/o端口空間注冊使用I/O端口。能注冊的動態端口有2^16次方個,即65535個端口,他們形成了設備的I/O地址空間
-
實現I/O設備的輸入和輸出的方式:
-
輪詢:
- CPU要不斷地查詢外設的狀態,當外設未準備好數據時,CPU就只能循環等待,不能執行其它程序,這樣就浪費了CPU的大量時間,降低了主機的利用率
-
中斷:
- 為了解決以上這個矛盾,我們提出了中斷傳送方式,即當CPU進行主程序操作時,外設的數據已存入輸入端口的數據寄存器;或端口的數據輸出寄存器已空,由外設通過中斷控制器向CPU發出中斷請求信號,CPU在滿足一定的條件下,暫停執行當前正在執行的主程序,轉入執行相應能夠進行輸入/輸出操作的子程序,待輸入/輸出操作執行完畢之后CPU即返回繼續執行原來被中斷的主程序。這樣CPU就避免了把大量時間耗費在等待、查詢狀態信號的操作上,使其工作效率得以大大地提高。 能夠向CPU發出中斷請求的設備或事件稱為中斷源,這個過程叫中斷處理
- 主板通常有一個獨特的設備,叫做可編程中斷控制器。這個中斷控制器可以通過某個針腳和CPU直接進行通信,能夠觸發CPU發生某個位置偏轉,進而讓CPU知道某個信號到達。中斷控制器上會有一個中斷向量(每一個I/O設備在啟動時,要向中斷控制器注冊一個中斷號,這個號通常是唯一的。通常中斷向量的每一個針腳都是可以識別多個中斷號的),中斷向量也可以叫中斷號
-
設備向中斷控制器發出中斷請求,中斷控制器通過中斷向量識別這個請求是哪個設備發來的,然后通過某種方式通知給CPU,讓CPU知道具體哪個設備中斷請求到達了。這個時候CPU可以根據設備注冊使用I/O端口號,從而就能獲取到設備的數據了。(注意:CPU在接收到中斷請求后,會暫停當前進程的執行,內核開始調入到CPU上運行,之后內核會發出響應的指令,讓相應的設備寄存器上的數據讀入內存)
- 例:一個網卡接收到外來IP的請求,數據先到達網卡自己的緩存區,CPU中斷當前進程,轉為內核工作,內核將網卡緩存中的數據復制到內核的內存空間中,發現這個是網絡報文,就開始判斷IP是不是本機,如果是就開始拆報文,最后會獲取到一個端口號,然后轉為該端口對應的進程在CPU上運行
-
內核中斷處理分為兩步:
- 中斷上半部分,當用戶請求到達網卡時,CPU中斷開始,網卡緩存區的數據會被立即復制到內存中,如果不立即處理網卡發出的中斷信號將會消失,之后不發再獲取網卡緩存中的數據,這個我們稱之為中斷的上半部分
- 中斷下半部分,將數據復制到內存后不一定立即處理,因為很有可能繼續處理之前中斷的進程,而真正處理這個請求報文的過程叫做下半部份
-
DMA:
- 中斷的問題:如果某個請求是上傳請求,發送的是一個壓縮包,如果有10M,單個報文只能傳送1000個Byte,所以就只能被封裝為很多的數據包,每個數據包到達網卡都發送中斷請求,那么CPU會不斷的處理中斷。因為中斷存在的問題,所以有了直接內存訪問DMA
- 為了不讓網卡收到每一個數據包時都發送一個中斷請求,內核通過CPU告訴網卡,在內核內存中有一大段空間,讓網卡自己將數據復制到這段空間,這樣的話網卡就需要有使用總線的權限和功能,即能對在總線上能尋址,發送控制信息,和數據傳輸,但CPU是總線的控制者,在某一時刻到底,哪個I/O設備能使用總線是由CPU的控制器來決定的。那么就和CPU爭用總線了
- 因此,I/O設備自帶的一個具有智能型的控制芯片(稱之為直接內存訪問控制器),當某一個時刻需要處理中斷上半部分時,內核會告知某一個DMA設備,接下來總線歸這個DMA設備使用,并且告知其可以使用的內存空間,用于將I/O設備的數據讀取到內存空間中去。當DMA的I/O設備將數據讀取完成后,會發送消息告訴內核以及完成了讀取操作,而中斷下半部分的處理就來交個內核處理?,F在大多數設備都是用DMA控制器的,比如:網卡,硬盤等等
-
輪詢:
-
總線:
- 總線(Bus)由導線組成的傳輸線束,是一種內部結構, 它是cpu、內存、輸入、輸出設備傳遞信息的公用通道,主機的各個部件通過總線相連接,外部設備通過相應的接口電路再與總線相連接,從而形成了計算機硬件系統。按照計算機所傳輸的信息種類,計算機的總線可以劃分為數據總線(傳輸數據信息)、地址總線(傳輸數據地址,完成對設備的尋址功能)和控制總線(傳輸控制信號,協調各個設備使用總線)
- 使用多寬的總線是由CPU字長(CPU的字長:CPU在單位時間內(同一時間)能一次處理的二進制數的位數)決定,比如32bit字長的CPU,就只能使用32bit的地址總線(表示虛擬地址空間是 0 – 2^32,也就是最大4GByte的空間)、32bit的數據總線和32bit的控制總線
- 工作原理:如果說主板(Mother Board)是一座城市,那么總線就像是城市里的公共汽車(bus),能按照固定行車路線,傳輸來回不停運作的比特(bit)。這些線路在同一時間內都僅能負責傳輸一個比特。因此,必須同時采用多條線路才能傳送更多數據,而總線可同時傳輸的數據數就稱為寬度(width),以比特為單位,總線寬度愈大,傳輸性能就愈佳??偩€的帶寬(即單位時間內可以傳輸的總數據數)為:總線帶寬 = 頻率 x 寬度(Bytes/sec)。當總線空閑(其他器件都以高阻態形式連接在總線上)且一個器件要與目的器件通信時,發起通信的器件驅動總線,發出地址和數據。其他以高阻態形式連接在總線上的器件如果收到(或能夠收到)與自己相符的地址信息后,即接收總線上的數據。發送器件完成通信,將總線讓出(輸出變為高阻態)
- 內存:
-
以32bit地址空間為例,如果應用程式空間只有一個進程在運行,那么這個進程可以隨意使用這段空間,即想申請哪段空間就申請哪段空間,但有兩個問題:
- 一個進程使用時,而應用程式申請了超出物理內存空間范圍,但在尋址范圍內時,如:物理內存只提供了2G,但是32bit的CPU分析程式的指令后,尋址到了第3G的那個空間,這樣的問題在早些年是無法解決的,所以程序員在開發程式的時候,需要按照物理內存的寬度來開發
- 多個進程同時使用這段空間時:這樣進程所使用的空間中的數據,有可能被其他進程所修改
-
虛擬內存空間:對于以上存在的問題,所以有了虛擬內存空間
-
只要不是內核使用的物理內存空間我們稱之為用戶空間。內核會把用戶空間的物理內存切割成固定大小的頁框(即page frame),就是切割成一個固定大小的存儲單位,比默認的單個存儲單元(默認是一個字節,即8bit)要大.通常每4k一個存儲單位。每一個頁框作為一個獨立的單元向外進行分配,且每一個頁框也都有其編號?!九e個例子:假設有4G空間可用,每一個頁框是4K,一共有1M個頁框?!窟@些頁框要分配給不同的進程使用。
-
頁框(page frame):
- 內存管理的概念,CPU中添加了能自動把虛擬內存(即邏輯地址)地址轉化為物理內存地址的電路,為了簡化這種電路,就把RAM劃分為長度為4KB或8KB的塊,這種塊就叫頁框
- 內核以頁框為基本單位管理物理內存,分頁單元中,頁指一組數據,而存放這組數據的物理內存就是頁框,當這組數據被釋放后,若有其他數據請求訪問此內存,那么頁框中的頁將會改變
-
頁框(page frame):
-
對于每個進程來說,它使用到的都是虛擬地址,每個進程都看到一樣的虛擬地址空間(一個連續完整的地址空間),虛擬地址空間不需要和物理地址空間一樣大小。進程實際上是分配到了物理內存中,MMU將進程的虛擬內存地址轉化成物理內存地址將其分別存儲到地址所指向的位置。進程進行寫入內存是被離散存儲到物理內存。哪有空余內存就往哪存取
- 假設有4G內存,操作系統占用了1個G,剩余的3G物理內存分配給用戶空間使用。對于32位計算機系統來說,它的虛擬地址空間是 0 – 2^32,也就是0 – 4G。對于64位的計算機系統來說,理論的虛擬地址空間是 0 – 2^64,遠高于目前常見的物理內存空間
- 每一個進程在運行時,不會把程式都裝載到內存,而是只加載一部分指令到內存,雖然可用3G但不會使用到3G,如圖:僅將一些代碼,所用到的數據和變量,打開的文件加載到內存,即代碼段、數據段、堆和棧,并不需要太多的空間,大概幾個頁面(虛擬空間劃分的存儲單位叫頁面,同物理空間劃分的頁框一樣)
-
進程空間結構:
- 預留空間
- 棧(變量存放處)
- 共享庫
- 堆(打開的文件,文件中的數據流存放處)
- 數據段(全局的靜態變量存放處)
- 代碼段
-
只要不是內核使用的物理內存空間我們稱之為用戶空間。內核會把用戶空間的物理內存切割成固定大小的頁框(即page frame),就是切割成一個固定大小的存儲單位,比默認的單個存儲單元(默認是一個字節,即8bit)要大.通常每4k一個存儲單位。每一個頁框作為一個獨立的單元向外進行分配,且每一個頁框也都有其編號?!九e個例子:假設有4G空間可用,每一個頁框是4K,一共有1M個頁框?!窟@些頁框要分配給不同的進程使用。
-
CPU在執行進程的指令時獲取其數據時有以下幾步:
- 進程指令中地址都是虛擬地址,把進程指令使用的虛擬地址通過MMU轉換成物理地址
- 把物理地址映射到高速緩存的緩存行,如1,2,3級緩存,即在這些高速緩存中查找有沒有該物理地址對應的數據
- 如果高速緩存命中就返回
- 如果不命中,就產生一個緩存缺失中斷,從主存相應的物理地址取值,并加載到高速緩存中。數據拿到后CPU從中斷中恢復,繼續執行中斷前的指令,所以高速緩存是和物理地址相映射的
-
進程
-
進程運行實際上就是把有限的抽象資源(cpu,memory等等)分配給進程。我們把這些抽象資源統稱為資源集,資源集包括:
- cpu時間片;
- 內存地址:抽象成虛擬地址空間 ( 如32位操作系統,支持4G空間,內核占用1G空間,進程也會默認自己有3G可用,事實上未必有3G空間,因為你的電腦可能會是小于4G的內存。)
- I/O:Linux中所有的對象都被抽象為文件,一個進程運行時,將會使用到比如IO設備、普通文件(實際上是數據流)、套接字(socket文件)之類的,所以需要打開的多個文件,即是通過fd(文件描述符,file descriptor)打開指定的文件,有三個的fd是固定的,每個進程都需要標準的輸入輸出,即0、1、2。我們把文件分為三類:正常文件、設備文件、管道文件
-
進程運行實際上就是把有限的抽象資源(cpu,memory等等)分配給進程。我們把這些抽象資源統稱為資源集,資源集包括:
-
MMU
- 現代操作系統普遍采用虛擬內存管理(Virtual Memory Management)機制,這需要處理器中的MMU(Memory Management Unit,內存管理單元)提供支持
- 首先引入兩個概念,虛擬地址和物理地址。如果處理器沒有MMU,或者有MMU但沒有啟用,CPU執行單元發出的內存地址將直接傳到芯片引腳上,被內存芯片(以下稱為物理內存,以便與虛擬內存區分)接收,這稱為物理地址(Physical Address,以下簡稱PA),如下圖所示。
- 如果處理器啟用了MMU,CPU執行單元發出的內存地址將被MMU截獲,從CPU到MMU的地址稱為虛擬地址(Virtual Address,以下簡稱VA),而MMU將這個地址翻譯成另一個地址發到CPU芯片的外部地址引腳上,也就是將VA映射成PA,如下圖所示。
- 如果是32位處理器,則內地址總線是32位的,與CPU執行單元相連(圖中只是示意性地畫了4條地址線),而經過MMU轉換之后的外地址總線則不一定是32位的。也就是說,虛擬地址空間和物理地址空間是獨立的,32位處理器的虛擬地址空間是4GB,而物理地址空間既可以大于也可以小于4GB。
- MMU將VA映射到PA是以頁(Page)為單位的,32位處理器的頁尺寸通常是4KB。例如,MMU可以通過一個映射項將VA的一頁0xb7001000~0xb7001fff映射到PA的一頁0x2000~0x2fff,如果CPU執行單元要訪問虛擬地址0xb7001008,則實際訪問到的物理地址是0x2008。物理內存中的頁稱為物理頁面或者頁幀(Page Frame)。虛擬內存的哪個頁面映射到物理內存的哪個頁幀是通過頁表(Page Table)來描述的,頁表保存在物理內存中,MMU會查找頁表來確定一個VA應該映射到什么PA。
-
操作系統和MMU是這樣配合的:
- 操作系統在初始化或分配、釋放內存時會執行一些指令在物理內存中填寫頁表,然后用指令設置MMU,告訴MMU頁表在物理內存中的什么位置。
- 設置好之后,CPU每次執行訪問內存的指令都會自動引發MMU做查表和地址轉換操作,地址轉換操作由硬件自動完成,不需要用指令控制MMU去做。
- 我們在程式中使用的變量和函數都有各自的地址,程式被編譯后,這些地址就成了指令中的地址,指令中的地址被CPU解釋執行,就成了CPU執行單元發出的內存地址,所以在啟用MMU的情況下,程式中使用的地址都是虛擬地址,都會引發MMU做查表和地址轉換操作。那為什么要設計這么復雜的內存管理機制呢?多了一層VA到PA的轉換到底換來了什么好處?All problems in computer science can be solved by another level of indirection.還記得這句話嗎?多了一層間接必然是為了解決什么問題的,等講完了必要的預備知識之后,將在MMU(二)討論虛擬內存管理機制的作用。
- MMU除了做地址轉換之外,還提供內存保護機制。各種體系結構都有用戶模式(User Mode)和特權模式(Privileged Mode)之分,操作系統可以在頁表中設置每個內存頁面的訪問權限,有些頁面不允許訪問,有些頁面只有在CPU處于特權模式時才允許訪問,有些頁面在用戶模式和特權模式都可以訪問,訪問權限又分為可讀、可寫和可執行三種。這樣設定好之后,當CPU要訪問一個VA時,MMU會檢查CPU當前處于用戶模式還是特權模式,訪問內存的目的是讀數據、寫數據還是取指令,如果和操作系統設定的頁面權限相符,就允許訪問,把它轉換成PA,否則不允許訪問,產生一個異常(Exception)。異常的處理過程和中斷類似,不同的是中斷由外部設備產生而異常由CPU內部產生,中斷產生的原因和CPU當前執行的指令無關,而異常的產生就是由于CPU當前執行的指令出了問題,例如訪問內存的指令被MMU檢查出權限錯誤,除法指令的除數為0等都會產生異常。
-
處理器模式
- 通常操作系統把虛擬地址空間劃分為用戶空間和內核空間,例如x86平臺的Linux系統虛擬地址空間是0x00000000~0xffffffff,前3GB(0x00000000~0xbfffffff)是用戶空間,后1GB(0xc0000000~0xffffffff)是內核空間。用戶程式加載到用戶空間,在用戶模式下執行,不能訪問內核中的數據,也不能跳轉到內核代碼中執行。這樣可以保護內核,如果一個進程訪問了非法地址,頂多這一個進程崩潰,而不會影響到內核和整個系統的穩定性。CPU在產生中斷或異常時不僅會跳轉到中斷或異常服務程式,還會自動切換模式,從用戶模式切換到特權模式,因此從中斷或異常服務程式可以跳轉到內核代碼中執行。事實上,整個內核就是由各種中斷和異常處理程式組成的。總結一下:在正常情況下處理器在用戶模式執行用戶程式,在中斷或異常情況下處理器切換到特權模式執行內核程式,處理完中斷或異常之后再返回用戶模式繼續執行用戶程式。
-
段錯誤我們已經遇到過很多次了,它是這樣產生的:
- 用戶程式要訪問的一個VA,經MMU檢查無權訪問。
- MMU產生一個異常,CPU從用戶模式切換到特權模式,跳轉到內核代碼中執行異常服務程式。
- 內核把這個異常解釋為段錯誤,把引發異常的進程終止掉。
本文來自投稿,不代表Linux運維部落立場,如若轉載,請注明出處:http://www.www58058.com/94265