《操作系统真象还原》-阅读笔记(中)
第七章
操作系統(tǒng)是由中斷驅(qū)動的。
中斷分為外部中斷和內(nèi)部中斷。
外部中斷分為可屏蔽中斷和不可屏蔽中斷,內(nèi)部中斷分為軟中斷和異常。
外部中斷
來自CPU外部的中斷。
可屏蔽中斷:通過INTR引腳進(jìn)入CPU,外部設(shè)備如硬盤、網(wǎng)卡、打印機(jī)等發(fā)出的中斷
CPU可以不理會,因?yàn)椴粫礄C(jī)。
Linux把中斷分為上半部和下半部分開處理,把中斷立即需要執(zhí)行的部分劃分到上半部,不緊急的部分劃分到下半部。上半部是在關(guān)中斷的情況下執(zhí)行的。
不可屏蔽中斷:通過NMI引腳進(jìn)入CPU,它表示系統(tǒng)發(fā)生了致命的錯(cuò)誤。
三種常見原因:1.內(nèi)存讀寫錯(cuò)誤 2電源掉電 3總線奇偶校驗(yàn)錯(cuò)誤
內(nèi)部中斷
軟中斷:軟件主動發(fā)起的中斷
異常:指令執(zhí)行期間CPU內(nèi)部產(chǎn)生的錯(cuò)誤引起的。
中斷描述符表(IDT)
IDT中有中斷描述符,還有任務(wù)門描述符和陷阱門描述符。
這些描述符都是門,門是通往另一段程序的入口。門描述符中添加了各種屬性,就是進(jìn)門的條件。
中斷處理過程:
CPU外:
CPU內(nèi):
1.處理器根據(jù)中斷向量號定位中斷描述符
2.處理器進(jìn)行特權(quán)級檢查
3執(zhí)行中斷處理程序
如下圖:
?
這里我突然想起個(gè)問題,訪問內(nèi)核地址空間不需要經(jīng)過頁表嗎?因?yàn)閮?nèi)核地址空間一般是連續(xù)的。
答案是也需要,不過是內(nèi)核頁表。一旦CPU進(jìn)入了保護(hù)模式,開啟分頁機(jī)制,不管在內(nèi)核空間,還是用戶空間,都是使用虛擬地址進(jìn)行尋址了。
在32位的系統(tǒng),內(nèi)核頁表記錄內(nèi)核對高端內(nèi)存訪問而進(jìn)行的映射關(guān)系。因?yàn)楝F(xiàn)代 CPU 的尋址不能繞過 MMU。不過內(nèi)核空間和用戶空間不同,它一般不做 swap,也就沒有 page fault,而且它一般不會把連續(xù)的虛擬地址空間映射成不連續(xù)的物理空間,一般只是做一個(gè) offset。
8259A編程
一個(gè)中斷控制器
8253編程
一個(gè)定時(shí)器,打節(jié)拍,最重要功能:定時(shí)向處理器發(fā)時(shí)間中斷
第八章
makefile編寫
略
實(shí)現(xiàn)ASSERT
因?yàn)橐蛴∑聊?#xff0c;所以最好關(guān)中斷
開中斷:原理是執(zhí)行sti指令把eflags中的IF位置1
關(guān)中斷:原理是執(zhí)行cli指令把eflags中的IF位置0
實(shí)現(xiàn)字符串操作函數(shù)
包括memset、memcpy、strcpy、strlen、strcmp、strcat、strchr(從左到右查找字符串str中首次出現(xiàn)字符ch的地址)、strchrs(查找在字符串str中ch出現(xiàn)的次數(shù))
位圖實(shí)現(xiàn)
略
內(nèi)存管理
每個(gè)任務(wù)(內(nèi)核和用戶)都要維護(hù)自己的虛擬地址池。
聲明了一個(gè)叫virtual_addr的結(jié)構(gòu)體用來表示虛擬內(nèi)存池,存儲一個(gè)位圖結(jié)構(gòu)和虛擬地址起始地址。
實(shí)現(xiàn)了malloc_page函數(shù),2個(gè)參數(shù),一個(gè)是pf,用來指明內(nèi)存池(內(nèi)核還是用戶),一個(gè)是pg_cnt,用來指明頁數(shù),此函數(shù)的功能是在pf指向的內(nèi)存池中分配pg_cnt個(gè)頁,成功則返回虛擬地址,失敗則返回NULL。
此函數(shù)干了三件事:
1.通過vaddr_get在虛擬內(nèi)存池中申請?zhí)摂M地址
2.通過palloc在物理內(nèi)存池中申請物理頁
3.通過page_table_add將上兩步得到的虛擬地址和物理地址在頁表中完成映射
tips
在ubuntu下用gcc編譯鏈接,出現(xiàn)錯(cuò)誤
undefined reference to `__stack_chk_fail’
解決方法:
add -fno-stack-protector to your CFLAGS.
第九章
PCB
每個(gè)進(jìn)程都有自己的PCB,所有PCB放到一張表格中維護(hù),這就是進(jìn)程表。調(diào)度器可以根據(jù)這張表選擇處理器運(yùn)行的進(jìn)程。
這里寫圖片描述
寄存器映像用來保存進(jìn)程的現(xiàn)場,用于進(jìn)程切換。
PCB最頂端為線程在0特權(quán)級下所用的棧。
實(shí)現(xiàn)線程
兩種實(shí)現(xiàn)方式
1.用戶空間實(shí)現(xiàn),線程表就在用戶進(jìn)程中,用戶進(jìn)程要專門寫個(gè)線程用作線程調(diào)度器。
優(yōu)點(diǎn):
調(diào)度算法自己實(shí)現(xiàn)
線程切換不用陷入內(nèi)核態(tài)裝載寄存器映像
缺點(diǎn):
某個(gè)線程出現(xiàn)阻塞,整個(gè)進(jìn)程都會阻塞(操作系統(tǒng)不知道進(jìn)程中存在線程)
2.內(nèi)核空間實(shí)現(xiàn),線程表就在內(nèi)核中,該線程由操作系統(tǒng)一調(diào)度,無論線程屬于內(nèi)核還是用戶空間。
優(yōu)點(diǎn):
內(nèi)核提供的線程相當(dāng)于讓進(jìn)程多占用了處理器資源(因?yàn)橐粋€(gè)進(jìn)程有多個(gè)線程可以放上調(diào)度器),提速明顯。
進(jìn)程中某一線程阻塞后,只會阻塞這一個(gè)線程,變相提速。
缺點(diǎn):
會陷入內(nèi)核態(tài),增加了一些保護(hù)現(xiàn)場的操作,但比起提速可以忽略。
本文用第二種實(shí)現(xiàn)方法,Linux中嚴(yán)格來說,用戶空間是沒有Thread這個(gè)概念的,Thread的相關(guān)實(shí)現(xiàn)是gcc等提供的模擬thread, gcc是使用了clone這個(gè)系統(tǒng)調(diào)用,利用linux的輕量級進(jìn)程實(shí)現(xiàn)了類似thread的庫。下面的鏈接有詳細(xì)介紹
http://www.360doc.com/content/13/1008/11/13047933_319789998.shtml
線程PCB由雙向鏈表串聯(lián)
?
任務(wù)調(diào)度
在 schedule 中要判斷當(dāng)前線程是出于什么原因才“淪落到”要被換下處理器
的地步 。 是線程的時(shí)間片到期了?還是線程時(shí)間片未到,但它被阻塞了,以至于不得不換下處理器?其實(shí)這就是查看線程的狀態(tài),如果線程的狀態(tài)為TASK RUNNING ,這說明時(shí)間片到期了,將其 ticks 重新賦值為它的優(yōu)先級 prio ,將其狀態(tài)由 TASK_RUNNING 置為 TASK_READY ,并將其加入到就緒隊(duì)列的末尾。如果狀態(tài)為其他,這不需要任何操作,因?yàn)檎{(diào)度器是從就緒隊(duì)列中取出下一個(gè)線程,而當(dāng)前運(yùn)行的錢程并不在就緒隊(duì)列中。
完整的調(diào)度需要三部分的配合:
1.時(shí)鐘中斷函數(shù)
2.調(diào)度器schedule
3.任務(wù)切換函數(shù)switch_to
第十章
出現(xiàn)GP錯(cuò)誤原因:多個(gè)線程訪問光標(biāo)寄存器,一個(gè)線程更新完高8位后被換下,另一個(gè)線程通知顯卡馬上要寫來的是寄存器高8位,這時(shí)被換下,第一個(gè)線程繼續(xù)寫低8位,但顯卡認(rèn)為這是高8位。需要實(shí)現(xiàn)鎖來同步
信號量
一個(gè)全局共享變量,變量的加減必須是原子操作,需要關(guān)中斷來保證
鎖
本文的鎖是用二元信號量實(shí)現(xiàn)的
--------------------- ?
作者:月黑風(fēng)高云游詩人 ?
來源:CSDN ?
原文:https://blog.csdn.net/lqygame/article/details/73824702 ?
版權(quán)聲明:本文為博主原創(chuàng)文章,轉(zhuǎn)載請附上博文鏈接!
總結(jié)
以上是生活随笔為你收集整理的《操作系统真象还原》-阅读笔记(中)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 会成真吗?专家建议废除汽车购置税
- 下一篇: 男子吃野菇拿银镯试毒进医院 网友:是镯