基本上,內核是如何阻止我做這樣的事情的?在單核心機器上,如果編譯代碼直接在處理器上執行,內核如何對進程施加限制(內存等)?
char *p = (char *) 0xfea80650; // or any random point in memory
*p = 0;
我想知道的是,一次只能在處理器上運行一件事。所以當這個程序轉向時,有什麼可以阻止它呢?
基本上,內核是如何阻止我做這樣的事情的?在單核心機器上,如果編譯代碼直接在處理器上執行,內核如何對進程施加限制(內存等)?
char *p = (char *) 0xfea80650; // or any random point in memory
*p = 0;
我想知道的是,一次只能在處理器上運行一件事。所以當這個程序轉向時,有什麼可以阻止它呢?
現代機器使用虛擬內存管理將程序使用的地址映射到DRAM中的實際地址。因此,如果您沒有在該地址分配內存,地址轉換表中將不會有任何條目,並且虛擬內存管理器將引導您離開系統。
內核不會阻止您修改它,處理器會阻止您根據內核將其保留在名爲頁表的受保護數據結構中的指令修改某些內存位置。當前正在執行的代碼違反了其中一個規則時,處理器切換回保護模式,並通知內核允許內核按照自己的喜好進行操作。
有道理。如果我翻轉GPIO引腳的情況下,處理器是否也在這種情況下提醒內核? – user3483247
@ user3483247:我對物理和電子硬件知之甚少,但是從我從維基百科文章中獲得的信息中可以得知,GPIO引腳可以用作IRQ(基本上是一箇中斷標識符),我認爲是的是答案。 – Linuxios
你是對的,在某種程度上。內核不能阻止你這麼做,除非處理器有阻止你這麼做的功能 - 在這種情況下,內核可以激活處理器功能。所有現代的臺式機/筆記本電腦/服務器計算機都有具有此類功能的處理器並非所有的都是電腦 - 嵌入式處理器在洗碗機等設備中非常常見,不需要任何保護功能。
在每次內存訪問之前,處理器會在稱爲「頁表」的數據結構中查找內存地址。每個進程都有自己的頁面表。頁表確定哪個虛擬地址(你的程序使用什麼)映射到哪個物理地址(RAM芯片的哪個部分)。
在您的示例中,處理器將在頁面表中查找0xfea80650
。它可能會看到這個虛擬地址沒有被分配 - 即沒有被告知哪個RAM芯片的哪一部分對應於這個地址。所以它會導致程序崩潰。實際上,處理器不會讓程序崩潰。處理器只是在內核中調用一個函數,這樣內核就知道一個程序訪問了一個無效地址。內核將停止你的程序並輸出一條錯誤信息,因爲沒有別的辦法可以做到這一點。
或者,內核可能使用地址0xfea80650
。處理器將在頁表中查找地址,並查看只有內核被允許訪問它,並看到你不是內核。同樣的結果。
由於提到user3386109
,您將使用虛擬內存。虛擬內存由硬件處理。當您的機器嘗試訪問不在其虛擬內存轉換表中的內存時,它將生成硬件中斷。這將停止您的用戶空間程序立即運行,並將執行切換到中斷處理程序。中斷處理程序反過來安排Linux下半部分運行。底部半部分知道用戶空間程序試圖訪問無效的內存位置,因此它殺死了用戶空間應用程序,並導致調度程序重新安排下一個最高優先級的用戶空間應用程序。所以當下半部分退出時,原來的用戶空間應用程序將永遠不會再運行。
我明白了。這個虛擬內存管理器是用硬件實現的嗎?我不明白當處理器忙於完全相同的指令時,如何停止指令。 – user3483247
@ user3483247:內存管理器是處理器的一部分,所有訪問內存的請求都經過它。如果一個請求違反了頁表,一個錯誤(我認爲 - 不確定 - 是一種硬件中斷)被髮送。 – Linuxios