




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第6章操作系統(tǒng)簡(jiǎn)介Dr.機(jī)的啟動(dòng)認(rèn)識(shí)操作系統(tǒng)操作系統(tǒng)對(duì)硬件資源管理操作系統(tǒng)對(duì)應(yīng)用程序提供較安全可靠的服務(wù)操作系統(tǒng)對(duì)多運(yùn)行環(huán)境的管理統(tǒng)2023/7/261第1節(jié)計(jì)算機(jī)的啟動(dòng)2023/7/26Dr.沙行勉2啟動(dòng)自檢階段初始化啟動(dòng)階段啟動(dòng)加載階段內(nèi)核裝載階段登錄階段計(jì)算機(jī)啟動(dòng)流程2023/7/26Dr.沙行勉3不論是臺(tái)式機(jī)、筆記本、手機(jī),所有設(shè)備在開機(jī)啟動(dòng)過程中都會(huì)包括三個(gè)共同的階段:?jiǎn)?dòng)自檢階段、初始化啟動(dòng)階段、啟動(dòng)加載階段。這三個(gè)階段主要由BIOS(BasicInputOutputSystem)來完成的。BIOS是一組程序,包括基本輸入輸出程序、系統(tǒng)設(shè)置信息、開機(jī)后自檢程序和系統(tǒng)自啟動(dòng)程序。1.1啟動(dòng)自檢階段2023/7/26Dr.沙行勉4加電自檢的功能是檢查電腦整體狀態(tài)是否良好。通常完整的POST自檢過程包括對(duì)CPU、ROM、主板、串并口、顯示卡及鍵盤進(jìn)行測(cè)試。一旦在自檢中發(fā)現(xiàn)問題,系統(tǒng)將給出提示信息或鳴笛警告。按一下電源按鈕,計(jì)算機(jī)就進(jìn)入啟動(dòng)自檢階段。如右圖。電腦剛接通電源,將讀取BIOS程序,并對(duì)硬件進(jìn)行檢測(cè)。這個(gè)檢測(cè)過程也叫做加電自檢(PowerOnSelfTest,簡(jiǎn)稱POST)。1.2初始化啟動(dòng)階段2023/7/26Dr.沙行勉5啟動(dòng)自檢階段結(jié)束之后,若自檢結(jié)果無異常,接下來計(jì)算機(jī)就進(jìn)入初始化啟動(dòng)階段。根據(jù)BIOS設(shè)定的啟動(dòng)順序,找到優(yōu)先啟動(dòng)的設(shè)備,比如本地磁盤,CDDriver,USB設(shè)備等等。然后準(zhǔn)備從這些設(shè)備啟動(dòng)系統(tǒng)。初始化啟動(dòng)階段還包括設(shè)置寄存器、對(duì)一些外部設(shè)備進(jìn)行初始化和檢測(cè)等。1.3啟動(dòng)加載階段2023/7/26Dr.沙行勉6初始化階段完成之后,接下來將讀取準(zhǔn)備啟動(dòng)的設(shè)備所需的相關(guān)數(shù)據(jù)。由于系統(tǒng)大多存放在硬盤中,所以BIOS會(huì)指定啟動(dòng)的設(shè)備來讀取硬盤中的操作系統(tǒng)核心文件。由于不同的操作系統(tǒng)具有不同的文件系統(tǒng)格式(如FAT32,NTFS,EXT4等等),因此需要一個(gè)啟動(dòng)管理程序來處理核心文件的加載,這個(gè)啟動(dòng)管理程序就被稱為BootLoader。BootLoader的作用主要有兩方面:首先,提供菜單讓用戶選擇不同的啟動(dòng)項(xiàng)目,通過不同的啟動(dòng)項(xiàng)目開啟計(jì)算機(jī)的不同系統(tǒng)。其次,能加載核心(Kernel)文件,直接指向可啟動(dòng)的程序區(qū)段來啟動(dòng)操作系統(tǒng)。1.4內(nèi)核裝載階段2023/7/26Dr.沙行勉7操作系統(tǒng)利用內(nèi)核程序,開始測(cè)試并驅(qū)動(dòng)各個(gè)外圍設(shè)備,包括存儲(chǔ)裝置、CPU、網(wǎng)卡、聲卡等等。在這個(gè)階段,有的操作系統(tǒng)會(huì)對(duì)硬件進(jìn)行重新檢測(cè)。在操作系統(tǒng)開始使用內(nèi)核程序測(cè)試和驅(qū)動(dòng)外圍設(shè)備時(shí),操作系統(tǒng)的核心才接管了BIOS的工作。1.5登錄階段2023/7/26Dr.沙行勉8登錄階段,計(jì)算機(jī)主要完成以下兩項(xiàng)任務(wù):?jiǎn)?dòng)機(jī)器上安裝的所有需要自動(dòng)啟動(dòng)的Windows服務(wù)顯示登錄界面練習(xí)題2023/7/26Dr.沙行勉9在安裝Windows系統(tǒng)的個(gè)人電腦中,將希望開機(jī)運(yùn)行的程序設(shè)置為開機(jī)自動(dòng)啟動(dòng)。要如何設(shè)置?假設(shè)你有多個(gè)操作系統(tǒng),如何使PC從指定windows7啟動(dòng)?BIOS的程序存放在ROM中,請(qǐng)思考Andriod手機(jī)中的ROM與BIOS的ROM有何區(qū)別?PC機(jī)刷BIOS與Andriod手機(jī)刷機(jī)、刷ROM有何區(qū)別?提示:手機(jī)Android的ROM,是整個(gè)操作系統(tǒng)和一些常用的程序。第2節(jié)認(rèn)識(shí)操作系統(tǒng)2023/7/26Dr.沙行勉10什么是操作系統(tǒng)?中斷什么是操作系統(tǒng)2023/7/26Dr.沙行勉11操作系統(tǒng)管理計(jì)算機(jī)資源,是軟件與硬件的中間接口。操作系統(tǒng)也是世界上最懶的管理者,因?yàn)樗鼰o時(shí)無刻不在“睡覺”。操作系統(tǒng)的常態(tài)是睡覺,它不會(huì)主動(dòng)做任何事的。它是被“中斷”后才起來做服務(wù)的,做完后又睡覺了。叫醒操作系統(tǒng)的方式叫做“中斷”。中斷的來源有三。有從硬件來的要求中斷,有從軟件來的要求中斷,也有運(yùn)行時(shí)碰到異常時(shí)來的要求中斷。操作系統(tǒng)不是神,它的執(zhí)行也需要CPU。它不過是一個(gè)復(fù)雜的軟件罷了(現(xiàn)在的Linux是個(gè)百萬行的程序),操作系統(tǒng)被叫醒后也需要CPU才能執(zhí)行。2.1中斷2023/7/26Dr.沙行勉12每當(dāng)需要操作系統(tǒng)處理事務(wù)時(shí),沉睡中的操作系統(tǒng)將會(huì)被喚醒,完成相應(yīng)事務(wù)的處理。喚醒操作系統(tǒng)的行為叫做“中斷”,你可以認(rèn)為是“中斷”操作系統(tǒng)的睡眠。比如用戶在從鍵盤按下“A”時(shí),鍵盤會(huì)發(fā)出中斷信號(hào)去叫醒操作系統(tǒng),告訴他:“嘿,鍵盤的A按鍵已經(jīng)按下去了,你處理一下吧”,這時(shí),操作系統(tǒng)醒來處理這個(gè)事件。又如用戶程序在執(zhí)行的過程中,需要讀寫文件,程序會(huì)產(chǎn)生一個(gè)中斷請(qǐng)求,叫醒操作系統(tǒng)去處理讀寫文件事務(wù)。另外,如果程序在運(yùn)行中出現(xiàn)了除以0等非正常事件,沉睡中的操作系統(tǒng)也會(huì)被喚醒,并處理相應(yīng)的異常事件。2.1中斷——中斷類型2023/7/26Dr.沙行勉13從鍵盤、文件,以及除以0等非正常事件發(fā)出的中斷分別對(duì)應(yīng)三種中斷類型,分別為:硬件中斷,軟件中斷以及異常。硬件中斷(HardwareInterrupt),顧名思義是由硬件發(fā)出的中斷,包括I/O設(shè)備發(fā)出的數(shù)據(jù)交換請(qǐng)求、時(shí)鐘中斷等等。軟件中斷(SoftwareInterrupt),指由應(yīng)用程序觸發(fā)的中斷,就是正在執(zhí)行的軟件需要操作系統(tǒng)提出服務(wù)。軟件中斷主要包括各種系統(tǒng)調(diào)用(systemcalls),為應(yīng)用程序提供不同的服務(wù)。異常(Exception),這類中斷是指當(dāng)系統(tǒng)運(yùn)行過程中出現(xiàn)了一些非正常事務(wù),需要操作系統(tǒng)進(jìn)行處理。例如用戶程序讀寫一個(gè)地址,而這地址被保護(hù)起來,是不能被用戶程序讀寫的,這也會(huì)發(fā)生異常中斷。但是,異常并不全是錯(cuò)誤。第3節(jié)操作系統(tǒng)對(duì)硬件資源管理2023/7/26Dr.沙行勉14操作系統(tǒng)對(duì)I/O設(shè)備管理 ——硬件中斷操作系統(tǒng)對(duì)CPU的管理 ——硬件中斷操作系統(tǒng)對(duì)內(nèi)存的管理 ——“異?!钡膽?yīng)用引言2023/7/26Dr.沙行勉15操作系統(tǒng)要管理的硬件資源最主要包括:各種各樣的I/O設(shè)備,計(jì)算資源和存儲(chǔ)資源。鍵盤,顯示器,U盤等這些常用的設(shè)備均為I/O設(shè)備,操作系統(tǒng)需要統(tǒng)一對(duì)這些硬件進(jìn)行管理。計(jì)算資源主要指CPU(CentralProcessingUnit,中央處理單元);存儲(chǔ)資源通常包括內(nèi)存和外存,內(nèi)存是CPU直接通過系統(tǒng)總線來訪問的,而外存是通過標(biāo)準(zhǔn)的I/O來管理的。CPU和內(nèi)存都是計(jì)算機(jī)內(nèi)部很多程序所共享的資源。操作系統(tǒng)有條不紊得對(duì)這三種中斷進(jìn)行處理,以管理系統(tǒng)資源。本節(jié)將首先介紹操作系統(tǒng)對(duì)I/O設(shè)備的管理,然后分別介紹CPU與內(nèi)存這兩類共享資源。什么是I/O設(shè)備?除了計(jì)算資源和內(nèi)存資源外,操作系統(tǒng)對(duì)其他資源都通過I/O來管理。如:鍵盤、鼠標(biāo)等輸入設(shè)備,
顯示器、打印機(jī)等輸出設(shè)備,
磁盤、閃存(U盤)等外存設(shè)備。隨著計(jì)算機(jī)相關(guān)領(lǐng)域的發(fā)展,I/O設(shè)備的種類繁多,諸如顯卡,磁盤,網(wǎng)卡,U盤,智能手機(jī)等,都是外接I/O設(shè)備,并且持續(xù)不斷的有新的I/O設(shè)備出現(xiàn)。3.1操作系統(tǒng)對(duì)I/O設(shè)備管理2023/7/26Dr.沙行勉163.1操作系統(tǒng)對(duì)I/O設(shè)備管理2023/7/26Dr.沙行勉17隨著計(jì)算機(jī)相關(guān)領(lǐng)域的發(fā)展,I/O設(shè)備的種類繁多,操作系統(tǒng)如何識(shí)別不同的I/O設(shè)備?操作系統(tǒng)定義了一個(gè)框架來容納各種各樣的I/O設(shè)備。除了一些專用操作系統(tǒng)以外,現(xiàn)代通用操作系統(tǒng)(如Windows、Linux等)都會(huì)提供一個(gè)I/O模型,允許設(shè)備廠商按照此模型編寫設(shè)備驅(qū)動(dòng)程序(DeviceDriver),并加載到操作系統(tǒng)中。I/O模型通常具有廣泛的適用性,能夠支持各種類型的設(shè)備,包括對(duì)硬件設(shè)備的控制能力,以及對(duì)數(shù)據(jù)傳輸?shù)闹С?。?jiǎn)單的理解I/O模型,它對(duì)計(jì)算機(jī)下層硬件設(shè)備提供了控制的能力,同時(shí)對(duì)上層應(yīng)用程序訪問硬件提供了一個(gè)標(biāo)準(zhǔn)接口。3.1操作系統(tǒng)對(duì)I/O設(shè)備管理2023/7/26Dr.沙行勉18CPU通常使用輪詢和硬件中斷兩種方式檢測(cè)設(shè)備的工作狀態(tài):CPU通過不停地查詢?cè)O(shè)備的狀態(tài)寄存器來獲知其工作狀態(tài),這種方式稱為輪詢方式。
如下圖所示:CPU向設(shè)備1發(fā)出詢問,如果設(shè)備1有I/O請(qǐng)求,則將I/O請(qǐng)求信息返回CPU,否則詢問設(shè)備2。3.1操作系統(tǒng)對(duì)I/O設(shè)備管理2023/7/26Dr.沙行勉19相比于輪詢方式,另外一個(gè)更有效的做法是使用硬件中斷類型碼來分別是哪個(gè)硬件發(fā)起中斷。當(dāng)某一個(gè)設(shè)備狀態(tài)發(fā)生變化時(shí),該設(shè)備能主動(dòng)地通知CPU并反映其當(dāng)前的狀態(tài),從而操作系統(tǒng)可以采取相應(yīng)的措,在硬件中斷發(fā)生時(shí),每一個(gè)中斷都有一個(gè)中斷類型碼(Interruptvector)作為設(shè)備的標(biāo)示符,使操作系統(tǒng)能區(qū)分來自不同的設(shè)備的中斷請(qǐng)求,以提供不同的服務(wù)。3.1操作系統(tǒng)對(duì)I/O設(shè)備管理2023/7/26Dr.沙行勉20從中斷類型碼連接到要操作系統(tǒng)要執(zhí)行的服務(wù)程序就要利用一個(gè)重要的表格,中斷向量表(Interruptvectortable)。中斷類型碼是中斷向量表的索引,所以n種中斷類型碼就代表在中斷向量表有n個(gè)行。每一行存著指向相關(guān)服務(wù)程序的起始位置,這個(gè)服務(wù)程序叫做中斷服務(wù)程序(Interruptservceroutine),每一個(gè)中斷類型碼都有一個(gè)自己的中斷服務(wù)程序。當(dāng)CPU收到了中斷類型碼,例如是9,就會(huì)自動(dòng)到中斷向量表第9行,找到它的中斷服務(wù)程序的起始位置,然后跳到此程序去執(zhí)行。3.1操作系統(tǒng)對(duì)I/O設(shè)備管理2023/7/26Dr.沙行勉21以鍵盤輸入產(chǎn)生的中斷為例,當(dāng)用戶在鍵盤按下一個(gè)按鍵時(shí),會(huì)產(chǎn)生一個(gè)鍵盤掃描碼,掃描碼被送入主板上的相關(guān)接口芯片的寄存器中。當(dāng)輸入到達(dá)后,鍵盤將會(huì)發(fā)出中斷類型碼為9的中斷信息。CPU檢測(cè)到中斷信息后,喚醒操作系統(tǒng),并查找中斷向量表的9號(hào)向量,進(jìn)而轉(zhuǎn)到中斷服務(wù)程序入口(函數(shù)調(diào)用),執(zhí)行中斷服務(wù)程序。中斷向量表和相關(guān)的中斷服務(wù)程序是極其重要的,需要特別保護(hù)起來,一般用戶是不可以改變它們的。這些都是放在操作系統(tǒng)的內(nèi)核(kernal)保護(hù)起來。3.2操作系統(tǒng)對(duì)CPU的管理2023/7/26Dr.沙行勉22計(jì)算機(jī)的多核時(shí)代已經(jīng)到來。為了滿足系統(tǒng)的性能要求,提高任務(wù)處理的效率,現(xiàn)在主流的計(jì)算機(jī)通常都有一個(gè)或多個(gè)CPU,每個(gè)CPU中又有多個(gè)核(Core)。然而核的數(shù)量是遠(yuǎn)遠(yuǎn)小于需要執(zhí)行的程序的數(shù)量。一個(gè)計(jì)算機(jī)系統(tǒng)普通有幾十個(gè)程序(或叫任務(wù)Task)在等待執(zhí)行。大家都搶著要CPU。所以,操作系統(tǒng)需要合理地安排和調(diào)度任務(wù),使得計(jì)算資源得以充分利用。在現(xiàn)代操作系統(tǒng)中,任務(wù)的數(shù)量遠(yuǎn)超過Core的數(shù)量,為了使多個(gè)任務(wù)可以較公平的地在系統(tǒng)中運(yùn)行,避免出現(xiàn)一個(gè)死循環(huán)導(dǎo)致整個(gè)系統(tǒng)崩潰的情況,就需要有一種機(jī)制能喚醒操作系統(tǒng),然后操作系統(tǒng)在不同的任務(wù)間進(jìn)行切換。注意操作系統(tǒng)的運(yùn)行是需要CPU的,而CPU正在被進(jìn)程的程序給占據(jù)著。操作系統(tǒng)要怎樣能搶到CPU呢?3.2操作系統(tǒng)對(duì)CPU的管理2023/7/26Dr.沙行勉23因?yàn)镃PU正在被其它程序所占據(jù),所以操作系統(tǒng)要獲得CPU就需要CPU之外的硬件來發(fā)中斷給CPU,這是通過timer(硬件)發(fā)出的中斷而實(shí)現(xiàn)的。操作系統(tǒng)為每一個(gè)任務(wù)分配一個(gè)定長(zhǎng)的時(shí)間片,在這個(gè)時(shí)間內(nèi),CPU由獲得該時(shí)間片的任務(wù)所占據(jù)。然而每當(dāng)這個(gè)時(shí)間片用完時(shí),timer硬件自動(dòng)發(fā)出一個(gè)中斷給CPU,經(jīng)過前一節(jié)所講述的硬件中斷過程,CPU會(huì)跳到timer的中斷服務(wù)程序去執(zhí)行,在此中斷服務(wù)程序里會(huì)調(diào)用操作系統(tǒng)的一個(gè)核心程序,叫做調(diào)度器scheduler。調(diào)度器程序根據(jù)當(dāng)時(shí)的任務(wù)執(zhí)行情況,將CPU合理地分配給任務(wù)來使用。3.2操作系統(tǒng)對(duì)CPU的管理2023/7/26Dr.沙行勉24因?yàn)榭赡苡卸鄠€(gè)任務(wù)在要求CPU的執(zhí)行,我們叫這些任務(wù)是就緒(readytorun)任務(wù)。操作系統(tǒng)會(huì)維護(hù)了一個(gè)就緒任務(wù)隊(duì)列(readytorunqueue)存放這些就緒的任務(wù),在這個(gè)隊(duì)列中,各個(gè)任務(wù)都在等待CPU資源。選擇哪一個(gè)任務(wù)去使用CPU是調(diào)度器的工作。如圖“Timer中斷”所示,(1)在timer發(fā)出中斷后(2)現(xiàn)在執(zhí)行的任務(wù)就會(huì)放到就緒對(duì)列中,(3)調(diào)度器(scheduler)會(huì)從就緒隊(duì)列中選擇一個(gè)任務(wù)來使用CPU。3.2操作系統(tǒng)對(duì)CPU的管理——初識(shí)進(jìn)程2023/7/26Dr.沙行勉25操作系統(tǒng)是世界上最懶惰的東西。他的正常狀態(tài)是睡覺,他不會(huì)自動(dòng)地起來工作。他都是被別人叫醒的(稱為中斷)。但是他也蠻可憐的。每隔一小段時(shí)間就會(huì)被timer鬧鐘叫醒。醒來后做調(diào)度。做完后又睡覺了。調(diào)度時(shí),有任務(wù)被調(diào)出CPU,有任務(wù)要移回給CPU執(zhí)行。帶來一個(gè)亟需解決的問題。這個(gè)問題的解決基礎(chǔ)造就了重要的“進(jìn)程”概念的開展。該問題是:每一個(gè)任務(wù)執(zhí)行中,一旦時(shí)間片消耗完,該任務(wù)有可能會(huì)被調(diào)度器切換出CPU,但是再次換進(jìn)來要如何恢復(fù)運(yùn)行呢?(1)程序從哪里開始執(zhí)行?(2)假設(shè)程序能恢復(fù)從切換出時(shí)的語句開始執(zhí)行,之前運(yùn)行的結(jié)果怎么恢復(fù)?如果解決不了這兩個(gè)問題,造成的后果是:程序一旦換出CPU,再次被換回CPU中準(zhǔn)備執(zhí)行時(shí),就不能恢復(fù)換出時(shí)的狀態(tài),這樣系統(tǒng)根本無法繼續(xù)執(zhí)行任務(wù)。3.2操作系統(tǒng)對(duì)CPU的管理——初識(shí)進(jìn)程2023/7/26Dr.沙行勉26為了解決這些問題,操作系統(tǒng)為每一個(gè)執(zhí)行中的程序(任務(wù))創(chuàng)建了一個(gè)“進(jìn)程”(Process),用以保存每個(gè)任務(wù)執(zhí)行時(shí)的所有環(huán)境信息。進(jìn)程中保存了程序計(jì)數(shù)器(PC)內(nèi)容,所有寄存器的內(nèi)容,程序運(yùn)行時(shí)所涉及的變量,堆,棧等等。進(jìn)程保存程序被切換出CPU時(shí)所執(zhí)行到的步驟以及運(yùn)行過程中產(chǎn)生的數(shù)據(jù)變量和當(dāng)時(shí)的堆棧等一切信息。每當(dāng)進(jìn)程切換出CPU時(shí),這些信息隨著進(jìn)程一起保存到了內(nèi)存,等到該進(jìn)程重新調(diào)入CPU時(shí),能夠根據(jù)保存的信息恢復(fù)到換出時(shí)的運(yùn)行環(huán)境,程序得以繼續(xù)執(zhí)行。這個(gè)一出一進(jìn)(叫做“交換”,swap)是比較花功夫的,我們希望減少swap的次數(shù)。所以調(diào)度的好壞就關(guān)乎整個(gè)系統(tǒng)的性能了。關(guān)于進(jìn)程的相關(guān)知識(shí)和操作,將在6.5節(jié)中進(jìn)行詳細(xì)介紹。3.3操作系統(tǒng)對(duì)內(nèi)存的管理2023/7/26Dr.沙行勉27程序執(zhí)行的錯(cuò)誤例如除以0,讀寫不應(yīng)該讀寫的區(qū)域等等會(huì)產(chǎn)生“異?!敝袛?Exception),然而更常發(fā)生異常中斷的情況不是程序的錯(cuò)誤,而是有情況需要操作系統(tǒng)起來管理內(nèi)存。一個(gè)任務(wù)執(zhí)行的時(shí)候需要內(nèi)存。內(nèi)存和CPU一樣都是珍貴的資源。操作系統(tǒng)管理內(nèi)存,使得多個(gè)任務(wù)能共享內(nèi)存資源。在一個(gè)任務(wù)結(jié)束時(shí),操作系統(tǒng)會(huì)將所分配的內(nèi)存資源進(jìn)行回收,為其他任務(wù)所使用。由于內(nèi)存資源有限,操作系統(tǒng)還需要對(duì)任務(wù)存在內(nèi)存中的數(shù)據(jù)進(jìn)行換入換出的管理,以應(yīng)對(duì)內(nèi)存不足的情形。換入的數(shù)據(jù)從硬盤加載進(jìn)內(nèi)存,而換出的數(shù)據(jù)將存到硬盤。變量被換出后,就不在內(nèi)存中了。假如一個(gè)程序需要換出的變量,CPU在讀取時(shí)候,發(fā)覺這個(gè)變量不在內(nèi)存,就會(huì)產(chǎn)生“異?!保僮飨到y(tǒng)就要被喚醒來處理這個(gè)異常中斷,會(huì)把這變量存在的一塊數(shù)據(jù)(叫做頁,Page)從硬盤載入到內(nèi)存里。3.3操作系統(tǒng)對(duì)內(nèi)存的管理2023/7/26Dr.沙行勉28試想在執(zhí)行某任務(wù)的某條語句時(shí),一個(gè)變量還沒有加載進(jìn)內(nèi)存,這時(shí)對(duì)該變量的訪問會(huì)產(chǎn)生一個(gè)異常,拋出“異?!敝袛啵ㄟ@類異常叫做“頁錯(cuò)誤”Pagefault)后,操作系統(tǒng)就被喚醒,跳到頁錯(cuò)誤處理程序(Pagefaulthandler)將該變量所處的部分(普通是一頁數(shù)據(jù),4K字組)加載進(jìn)內(nèi)存。因?yàn)檫@個(gè)頁錯(cuò)誤處理程序牽扯到硬盤的I/O操作,整個(gè)過程是花時(shí)間的。另外,假如內(nèi)存已經(jīng)沒有空位來存放這一頁,操作系統(tǒng)將采用不同的頁替換算法(pagereplacementalgorithms),來決定將內(nèi)存中的那個(gè)頁換出以騰出空間。最常用的算法是LRU(LeastRecentlyUsed)算法,就是將內(nèi)存中最長(zhǎng)時(shí)間不用的那一頁換出去。練習(xí)題2023/7/26Dr.沙行勉29假若中斷向量表或中斷服務(wù)程序沒有被保護(hù)好,請(qǐng)舉例解釋病毒可以如何利用這個(gè)弱點(diǎn)?假如timer不是硬件,而是一個(gè)軟件程序,能否達(dá)到保護(hù)CPU不被一個(gè)任務(wù)給獨(dú)占?假如你設(shè)計(jì)timer這個(gè)硬件,請(qǐng)描述timer這個(gè)硬件所含的基本元件和其功能。假如以Python程序來模擬timer,要如何做?討論進(jìn)程應(yīng)該包含哪些信息,使得進(jìn)程交換出去再進(jìn)來得以無礙地恢復(fù)執(zhí)行。為什么stack要保存?這個(gè)stack是指什么?提示:第三章講函數(shù)調(diào)用時(shí)構(gòu)建的環(huán)境。當(dāng)頁錯(cuò)誤處理程序要存入一頁數(shù)據(jù)到內(nèi)存時(shí),發(fā)覺內(nèi)存已經(jīng)占滿了,請(qǐng)討論要如何決定是哪一頁置換出內(nèi)存?標(biāo)準(zhǔn)為何?當(dāng)正在執(zhí)行的程序發(fā)生pagefault時(shí),這個(gè)程序會(huì)不會(huì)被非正常地結(jié)束?還是程序毫無所知?討論頁替換算法,什么是好結(jié)果?什么是壞結(jié)果?LRU(LeastRecentlyUsed)算法是將內(nèi)存中最長(zhǎng)時(shí)間不用的那一頁換出去。在什么前提下,這個(gè)算法會(huì)產(chǎn)生好結(jié)果?還有算法是LFU(LeastFrequentlyUsed),就是換出最少次數(shù)讀寫的頁。LRU和LFU一樣嗎?第4節(jié)操作系統(tǒng)對(duì)應(yīng)用程序提供較安全可靠的服務(wù)2023/7/26Dr.沙行勉30內(nèi)核態(tài)與用戶態(tài)系統(tǒng)調(diào)用(SystemCall)——軟件中斷常用系統(tǒng)調(diào)用系統(tǒng)調(diào)用實(shí)例:read系統(tǒng)調(diào)用引言2023/7/26Dr.沙行勉31各位將來開公司設(shè)計(jì)出任何的新硬件,這些新硬件如果要連接到計(jì)算機(jī)或手機(jī),你的公司都必須提供驅(qū)動(dòng)程序(DeviceDriver),這些驅(qū)動(dòng)程序都要通過安全檢測(cè),假如有病毒是要負(fù)法律責(zé)任的。用戶在使用新硬件前,都必須先安裝驅(qū)動(dòng)程序,這些驅(qū)動(dòng)程序就變成了操作系統(tǒng)的部分之一。所有的程序要使用這個(gè)硬件時(shí),都必須要經(jīng)過操作系統(tǒng)來實(shí)現(xiàn),這樣可以保證硬件不被有意或無意的破壞,也可以經(jīng)由操作系統(tǒng)來保證特權(quán)(privilege)的維護(hù),例如這個(gè)用戶只有權(quán)力做讀操作,而不能做寫操作等等。我們絕對(duì)要禁止用戶程序跳過操作系統(tǒng)直接使用硬件!但是要如何禁止呢?4.1內(nèi)核態(tài)與用戶態(tài)2023/7/26Dr.沙行勉32一個(gè)用戶程序可以直接讀寫某個(gè)硬件嗎?例如,小明和助教阿珍在一臺(tái)電腦上分別有各自的用戶賬號(hào),阿珍將期末考試試卷存放在自己的文件夾下,并且不允許其他用戶訪問,聽起來好像很安全。然而如果小明能直接讀寫硬盤,知道試卷文件在硬盤的物理位置,小明寫了一段匯編語言程序,如下圖所示,跳過操作系統(tǒng),直接去讀取硬盤硬件所存的二進(jìn)制數(shù)據(jù),操作系統(tǒng)所保證的安全性就蕩然無存了。所以我們絕對(duì)不允許用戶程序直接訪問硬件設(shè)備。但是如前所述,用戶小明的程序直接讀寫硬盤數(shù)據(jù),這要怎么防范呢?操作系統(tǒng)是軟件,在這個(gè)問題上軟件是沒有辦法防護(hù)的,必須要CPU提供硬件的支持。4.1內(nèi)核態(tài)與用戶態(tài)2023/7/26Dr.沙行勉33禁止用戶程序直接訪問硬件設(shè)備的基本思想是CPU將指令集分為需要特權(quán)的指令(privileged)和一般的指令(non-previleged)。而所有的I/O指令都是屬于需要特權(quán)的指令。一般用戶不能執(zhí)行這類privileged指令,必須是系統(tǒng)內(nèi)核才能執(zhí)行這類privileged指令。所以小明是沒有辦法直接讀寫硬盤的。然而CPU是怎么知道現(xiàn)在執(zhí)行的程序是操作系統(tǒng)內(nèi)核還是普通用戶進(jìn)程呢?在程序運(yùn)行時(shí),CPU會(huì)顯示出現(xiàn)在的運(yùn)行狀態(tài):內(nèi)核態(tài)(UserMode)還是用戶態(tài)(KernelMode)。在CPU有個(gè)特殊的寄存器叫做狀態(tài)寄存器(statusregister),其中顯示現(xiàn)在的CPU是在內(nèi)核態(tài)還是用戶態(tài)。假如CPU是在用戶態(tài),那么任何的privileged指令都不可以執(zhí)行,一旦執(zhí)行了,CPU就發(fā)生異常錯(cuò)誤。4.1內(nèi)核態(tài)與用戶態(tài)2023/7/26Dr.沙行勉34如下圖所示,當(dāng)用戶程序直接執(zhí)行privileged指令時(shí),CPU會(huì)檢測(cè)當(dāng)前狀態(tài)是否為內(nèi)核態(tài),假如當(dāng)前狀態(tài)為用戶態(tài),CPU就不會(huì)執(zhí)行該指令,CPU發(fā)生異常錯(cuò)誤。這些檢測(cè)不是軟件,是CPU硬件執(zhí)行每一個(gè)指令時(shí)自動(dòng)檢測(cè)的。4.1內(nèi)核態(tài)與用戶態(tài)2023/7/26Dr.沙行勉35CPU如何從用戶態(tài)轉(zhuǎn)成內(nèi)核態(tài)?CPU如何從用戶態(tài)轉(zhuǎn)成內(nèi)核態(tài),這是現(xiàn)代操作系統(tǒng)的一個(gè)重要的技術(shù):必須要使用“中斷”方式,只有中斷,CPU才會(huì)進(jìn)入內(nèi)核態(tài)。不管是哪種中斷,CPU就會(huì)自動(dòng)進(jìn)入內(nèi)核態(tài)模式。一個(gè)用戶程序當(dāng)要得到操作系統(tǒng)的服務(wù)時(shí),它執(zhí)行軟件中斷,最底層就是執(zhí)行一個(gè)特殊的叫做“int”的指令來實(shí)現(xiàn)的(每一種CPU有類似的指令,只是名字不一樣,intelx86指令集叫做int指令,ARM指令集叫做swi指令,在一些操作系統(tǒng)教科書叫做trap指令),用戶程序通過執(zhí)行該指令來獲取操作系統(tǒng)提供的服務(wù)。重點(diǎn)是在執(zhí)行這條指令時(shí),CPU會(huì)自動(dòng)的將狀態(tài)置為內(nèi)核態(tài)。操作系統(tǒng)會(huì)保存一個(gè)中斷向量表,每一行是存著中斷服務(wù)程序的起始位置。int指令會(huì)有一個(gè)參數(shù)#n,“int#n”。當(dāng)CPU執(zhí)行到int#n指令時(shí)時(shí),會(huì)將模式轉(zhuǎn)為內(nèi)核態(tài),讀取中斷向量表的第#n個(gè)記錄,跳到相對(duì)應(yīng)的中斷服務(wù)程序去執(zhí)行。4.1內(nèi)核態(tài)與用戶態(tài)2023/7/26Dr.沙行勉36軟件中斷例子以Linux的軟件中斷為例,首先將想要執(zhí)行的系統(tǒng)調(diào)用編號(hào)放入暫存器EAX中,例如read的編號(hào)是3,write的編號(hào)是4,open的編號(hào)是5,close的編號(hào)是6等等。然后執(zhí)行軟件中斷int80h(80h是16進(jìn)制)指令就行了。MSDOS,Windows等系統(tǒng)也是用相似的方式,只是int#n中的#n用不同的編號(hào),例如MSDOS,用int21h為軟件中斷,大家將來寫底層驅(qū)動(dòng)程序時(shí),或許需要知道這些細(xì)節(jié),一半的軟件設(shè)計(jì)者是不需要知道這些細(xì)節(jié),操作系統(tǒng)都有較方便的接口來給軟件調(diào)用。很多高階語言例如Python,Java等再包裝操作系統(tǒng)的接口,提供多種更高階、更方便的函數(shù)接口供軟件設(shè)計(jì)者來使用。4.1內(nèi)核態(tài)與用戶態(tài)2023/7/26Dr.沙行勉37使用int指令后,用戶程序就可以獲得操作系統(tǒng)提供的服務(wù)了,狀態(tài)也自動(dòng)變成內(nèi)核態(tài),此時(shí)可以執(zhí)行那些需要特權(quán)的指令。注意此時(shí)的程序是操作系統(tǒng)。而結(jié)束中斷服務(wù)程序后,調(diào)度器選擇一個(gè)用戶進(jìn)程執(zhí)行時(shí),CPU會(huì)將狀態(tài)轉(zhuǎn)變?yōu)橛脩魬B(tài)。注意此時(shí)的程序是用戶的程序。用這種方式就是能保證,沒有用戶能“跳過”操作系統(tǒng)去直接使用I/O了。這個(gè)過程如下圖所示。4.2系統(tǒng)調(diào)用(SystemCall)——軟件中斷2023/7/26Dr.沙行勉38操作系統(tǒng)中設(shè)置了一組用于實(shí)現(xiàn)系統(tǒng)功能的子程序,稱為系統(tǒng)調(diào)用函數(shù)。系統(tǒng)調(diào)用函數(shù)和普通函數(shù)調(diào)用非常相似,只是系統(tǒng)調(diào)用函數(shù)的操作一定是運(yùn)行于內(nèi)核態(tài),而普通的函數(shù)調(diào)用由函數(shù)庫或用戶自己提供,運(yùn)行于用戶態(tài)。當(dāng)程序需要使用操作系統(tǒng)的服務(wù)來完成某項(xiàng)功能時(shí),就需要使用系統(tǒng)調(diào)用函數(shù)。CPU運(yùn)行到系統(tǒng)調(diào)用函數(shù)時(shí),將會(huì)執(zhí)行int#n指令,CPU會(huì)產(chǎn)生軟件中斷,喚醒操作系統(tǒng),接下來再運(yùn)行操作系統(tǒng)提供的服務(wù)。注意,int#n的指令的目的是喚醒操作系統(tǒng)來提供服務(wù),“轉(zhuǎn)成內(nèi)核態(tài)”是“隱藏”在int指令里自動(dòng)做的事。所以,用戶的程序只能在調(diào)用系統(tǒng)調(diào)用函數(shù)時(shí),CPU才會(huì)轉(zhuǎn)成內(nèi)核態(tài),以正確地執(zhí)行操作系統(tǒng)里的內(nèi)核程序。系統(tǒng)調(diào)用結(jié)束后,將返回用戶模式,CPU寄存器的狀態(tài)位改為Usermode,繼續(xù)執(zhí)行用戶程序。也就是說用戶自己的程序是不可能在內(nèi)核態(tài)執(zhí)行的。4.2練習(xí)題2023/7/26Dr.沙行勉39討論能不能有一個(gè)指令“swith_to_kernel_mode”指令,目的是將狀態(tài)變成內(nèi)核態(tài)。有了這樣的指令,會(huì)有什么問題?請(qǐng)討論為什么利用這種內(nèi)核態(tài)和用戶態(tài)的保護(hù)方式,普通用戶程序不能利用int進(jìn)入內(nèi)核態(tài)后再胡作非為呢?提示:int的目的不是為了進(jìn)入內(nèi)核態(tài)。4.3常用系統(tǒng)調(diào)用2023/7/26Dr.沙行勉40常用的系統(tǒng)調(diào)用可分為:進(jìn)程控制,如:fork(),exit()等。文件系統(tǒng)操作控制,如:read(),write()等。系統(tǒng)控制,如:ioctl(),time()等。內(nèi)存管理,如:mmap(),mprotect()等。網(wǎng)絡(luò)管理控制,如:sethostname(),soket(),bind()等。用戶管理,如:getuid(),getgid()等。進(jìn)程間通信,如:signal(),kill()等。在今后的學(xué)習(xí)工作中,文件操作是最為常用,在此,將介紹關(guān)于文件的一些常用操作的系統(tǒng)調(diào)用,包括文件的打開、創(chuàng)建、讀、寫等系統(tǒng)調(diào)用。4.3常用系統(tǒng)調(diào)用——文件系統(tǒng)操作控制2023/7/26Dr.沙行勉41什么是文件?對(duì)于linux而言,諸如輸出設(shè)備顯示器、輸入設(shè)備鍵盤、磁盤文件、打印機(jī)、甚至網(wǎng)絡(luò),都被看作是文件,這樣做的好處就是統(tǒng)一了硬件與普通文件的管理與操作。使用以下提供的系統(tǒng)調(diào)用函數(shù)就能對(duì)這些“文件”進(jìn)行操作。系統(tǒng)調(diào)用功能所在庫文件參數(shù)返回值open打開文件fcntl.h路徑名,打開模式(只讀、讀寫等)一個(gè)文件描述符(類似與進(jìn)程PID)close關(guān)閉文件描述字unistd.h文件描述符成功返回0,出錯(cuò)返回-1read讀文件,存入緩存所指地址unistd.h文件描述符、緩存地址、讀入大小實(shí)際讀到的字節(jié)數(shù),出錯(cuò)返回-1write寫文件,將緩存內(nèi)容寫入文件unistd.h文件描述符、緩存地址、讀入大小實(shí)際寫入文件的字節(jié)數(shù),出錯(cuò)返回-1mkdir創(chuàng)建目錄sys/stat.hsys/types.h創(chuàng)建目錄路徑、權(quán)限成功返回0,出錯(cuò)返回-1rmdir刪除目錄同上所刪除目錄路徑成功返回0,出錯(cuò)返回-1rename文件改名stdio.h舊名,新名成功返回0,出錯(cuò)返回-14.4系統(tǒng)調(diào)用實(shí)例:read系統(tǒng)調(diào)用2023/7/26Dr.沙行勉42為了更清晰地理解系統(tǒng)調(diào)用的過程,我們來觀察read()系統(tǒng)調(diào)用的執(zhí)行過程。假設(shè)現(xiàn)在程序需要獲得由標(biāo)準(zhǔn)輸入設(shè)備(鍵盤)所按下的一個(gè)按鍵。首先需要了解一些基礎(chǔ)知識(shí)。(1)在Linux系統(tǒng)中,每一個(gè)文件都有一個(gè)文件描述符(fd,),在下一節(jié)講述文件的時(shí)候?qū)⒕唧w講述這部分內(nèi)容。對(duì)于鍵盤,顯示器等設(shè)備,也被看做是一個(gè)特殊的文件,對(duì)于鍵盤這類標(biāo)準(zhǔn)輸入,其fd值為0,標(biāo)準(zhǔn)輸出的fd值是1。(2)系統(tǒng)調(diào)用read的功能,是從打開的設(shè)備或文件中讀取數(shù)據(jù)。(3)read函數(shù)的參數(shù)為:read(intfd,void*buf,size_tcount)。表示將從文件描述符為fd的“文件”中,取出count大小的內(nèi)容,存放到buf的空間中去。因此,要完成從鍵盤獲取按下一個(gè)按鍵的值,我們需要進(jìn)行系統(tǒng)調(diào)用為:read(0,ch,1)。4.4系統(tǒng)調(diào)用實(shí)例:read系統(tǒng)調(diào)用2023/7/26Dr.沙行勉43假設(shè)ProcessA現(xiàn)在開始執(zhí)行read(0,ch,1)系統(tǒng)調(diào)用,其執(zhí)行過程如下圖。4.4系統(tǒng)調(diào)用實(shí)例:read系統(tǒng)調(diào)用2023/7/26Dr.沙行勉44首先進(jìn)入read系統(tǒng)調(diào)用函數(shù),圖中(A)步驟。進(jìn)入read的用戶接口程序后,將參數(shù)到傳遞到相關(guān)寄存器中(包括read系統(tǒng)調(diào)用號(hào)),使用int指令進(jìn)入內(nèi)核態(tài),圖中(B)步驟。在內(nèi)核態(tài),根據(jù)寄存器內(nèi)容找到read系統(tǒng)調(diào)用服務(wù)例程,執(zhí)行硬盤I./O的操作。這時(shí),ProcessA需要讓出CPU資源,進(jìn)入I/O等待隊(duì)列(阻塞態(tài),在6.5.2將進(jìn)行講解)。當(dāng)I/O完成后,鍵盤發(fā)出硬件中斷,將ProcessA換入就緒隊(duì)列(readytorunqueue),中斷服務(wù)程序調(diào)用scheduler函數(shù),將選擇一個(gè)ready-to-run進(jìn)程調(diào)入CPU執(zhí)行。ProcessA重新調(diào)入CPU,繼續(xù)執(zhí)行read系統(tǒng)調(diào)用服務(wù)例程,結(jié)束后,返回到用戶空間的用戶接口程序,圖中(C)步驟。最后,返回用戶程序繼續(xù)執(zhí)行,圖中(D)步驟。4小結(jié)2023/7/26Dr.沙行勉45軟件開發(fā)者如何統(tǒng)一的使用硬件資源?為了統(tǒng)一的使用硬件資源,軟件開發(fā)者通過操作系統(tǒng)提供的用戶接口程序,進(jìn)入內(nèi)核模式使用操作系統(tǒng)提供的服務(wù)來使用資源。也就是說,不論是QQ程序,或是Office程序,例如要讀取一個(gè)文件的內(nèi)容時(shí),都可以調(diào)用read系統(tǒng)調(diào)用。這種統(tǒng)一接口的實(shí)現(xiàn)方式有利于開發(fā)者進(jìn)行快速開發(fā)。只要開發(fā)者熟悉了操作系統(tǒng)所提供的系統(tǒng)調(diào)用后,便可進(jìn)行不同上層軟件的開發(fā)。操作系統(tǒng)如何為硬件系統(tǒng)提供安全保證?對(duì)于硬件系統(tǒng)安全保證,則是因?yàn)榭刂朴布牡讓映绦蚓刹僮飨到y(tǒng)提供,用戶有理由相信操作系統(tǒng)不會(huì)做毀壞自己的事。所以,系統(tǒng)一旦進(jìn)入內(nèi)核態(tài),就處于安全的狀態(tài)。而上層應(yīng)用軟件運(yùn)行自身代碼段(非系統(tǒng)調(diào)用函數(shù))時(shí),不能切換到內(nèi)核態(tài),所以,程序無法通過自身代碼段攻擊下層硬件。第5節(jié)操作系統(tǒng)對(duì)多運(yùn)行環(huán)境的管理2023/7/26Dr.沙行勉46進(jìn)程進(jìn)程狀態(tài)進(jìn)程調(diào)度引言2023/7/26Dr.沙行勉47在介紹了操作系統(tǒng)對(duì)CPU資源進(jìn)行管理時(shí)講到:如果有多道任務(wù)在同一個(gè)Core上進(jìn)行執(zhí)行時(shí),將由timer發(fā)出中斷換出正在執(zhí)行的任務(wù),換入其它可以執(zhí)行的任務(wù)。進(jìn)程從CPU中被換出時(shí),不能簡(jiǎn)簡(jiǎn)單單的剝奪CPU資源,要同時(shí)保存進(jìn)程的運(yùn)行狀態(tài)信息,以便進(jìn)程再次被換入CPU時(shí)能恢復(fù)到換出時(shí)的狀態(tài)繼續(xù)執(zhí)行。比如說,進(jìn)程被換出時(shí)的執(zhí)行位置需要保存。程序執(zhí)行的位置信息是保存在PC寄存器中,程序計(jì)數(shù)器PC的內(nèi)容是下一條運(yùn)行指令的地址。所以,為了恢復(fù)執(zhí)行,系統(tǒng)需要在進(jìn)程換出時(shí)保存程序計(jì)數(shù)器PC的值。當(dāng)進(jìn)程再次換入時(shí),將已保存的值重新傳入PC便能定位到換出時(shí)的位置。另外,在進(jìn)程換出時(shí),由已經(jīng)執(zhí)行完成的程序部分所產(chǎn)生的所有相關(guān)數(shù)據(jù)也需要保存起來以便進(jìn)程被再次換入執(zhí)行時(shí)能夠順利的繼續(xù)執(zhí)行。5.1進(jìn)程(Process)2023/7/26Dr.沙行勉48進(jìn)程是一個(gè)程序的一次執(zhí)行,包含了其執(zhí)行時(shí)所有的環(huán)境信息。程序源代碼只是按照各種程序語言的語法規(guī)則所編寫的,而一個(gè)程序要在計(jì)算機(jī)上“跑”起來,首先需要將源代碼轉(zhuǎn)化為可執(zhí)行程序,其次還需要操作系統(tǒng)為其提供一個(gè)運(yùn)行環(huán)境,而這個(gè)運(yùn)行環(huán)境就是進(jìn)程。一個(gè)進(jìn)程可以用右圖描述:5.1進(jìn)程(Process)2023/7/26Dr.沙行勉49一個(gè)進(jìn)程包含了代碼段、數(shù)據(jù)段、棧、堆、BSS段以及進(jìn)程控制塊等部分。代碼段(Codesegment/Textsegment)通常是指用來存放程序執(zhí)行代碼的一塊內(nèi)存區(qū)域。數(shù)據(jù)段(Datasegment)通常是指用來存放程序中已經(jīng)初始化的全局變量的一塊內(nèi)存區(qū)域。棧(Stack)是用戶存放程序臨時(shí)創(chuàng)建的局部變量區(qū)域。除此以外,在函數(shù)被調(diào)用時(shí),其參數(shù)也會(huì)被壓入發(fā)起調(diào)用的進(jìn)程棧中,并且等到函數(shù)調(diào)用結(jié)束后,函數(shù)的返回值也會(huì)被存放回棧中。由于棧這種數(shù)據(jù)結(jié)構(gòu)具有先進(jìn)后出特點(diǎn),所以棧能夠特別方便用于保存/恢復(fù)調(diào)用現(xiàn)場(chǎng)。堆(Heap)是用于存放進(jìn)程運(yùn)行中動(dòng)態(tài)分配的內(nèi)存段,它的大小并不固定,可根據(jù)進(jìn)程運(yùn)行的需要?jiǎng)討B(tài)擴(kuò)張或縮減。例如所有的類對(duì)象(objects)是存放在這個(gè)區(qū)域的。BSS段(BlockStartedbySymbol)通常是指用來存放程序中未初始化的全局變量的一塊內(nèi)存區(qū)域。另外,操作系統(tǒng)為了統(tǒng)一管理進(jìn)程,專門設(shè)置了一個(gè)數(shù)據(jù)結(jié)構(gòu),即進(jìn)程控制塊(ProcessControlBlock,PCB),用來記錄進(jìn)程的特征信息,描述進(jìn)程運(yùn)動(dòng)變化的過程。PCB是操作系統(tǒng)感知進(jìn)程存在的唯一標(biāo)識(shí),進(jìn)程與PCB是一一對(duì)應(yīng)的。5.2進(jìn)程狀態(tài)2023/7/26Dr.沙行勉50在多道程序系統(tǒng)中,進(jìn)程在一個(gè)處理器上交替運(yùn)行,進(jìn)程狀態(tài)也會(huì)隨之不斷發(fā)生變化。本節(jié)介紹最基礎(chǔ)的“三狀態(tài)模型”?!叭隣顟B(tài)模型”中,三種基本狀態(tài)分別為運(yùn)行態(tài)(Running)、就緒態(tài)(Readytorun)和阻塞態(tài)(Blocking),三個(gè)狀態(tài)的轉(zhuǎn)換關(guān)系如下圖所示。5.2進(jìn)程狀態(tài)2023/7/26Dr.沙行勉51運(yùn)行態(tài):當(dāng)一個(gè)進(jìn)程在處理機(jī)上運(yùn)行時(shí),則稱該進(jìn)程處于運(yùn)行狀態(tài)。每個(gè)時(shí)刻,處于運(yùn)行態(tài)的進(jìn)程數(shù)目不能超過系統(tǒng)中處理器的數(shù)目。對(duì)于單處理機(jī)系統(tǒng),每個(gè)時(shí)刻只能有一個(gè)進(jìn)程處于運(yùn)行狀態(tài)。如果在某一時(shí)刻系統(tǒng)中沒有可執(zhí)行的進(jìn)程(例如所有進(jìn)程都在阻塞狀態(tài)),CPU通常會(huì)自動(dòng)執(zhí)行系統(tǒng)的空閑進(jìn)程。就緒態(tài):當(dāng)一個(gè)進(jìn)程獲得了除處理機(jī)以外的一切所需資源,一旦得到處理機(jī)即可運(yùn)行,則稱此進(jìn)程處于就緒狀態(tài)。阻塞態(tài):也稱為等待或睡眠狀態(tài)。一個(gè)進(jìn)程正在等待某一事件發(fā)生(例如請(qǐng)求I/O而等待I/O完成等)而暫時(shí)停止運(yùn)行。在這個(gè)時(shí)刻,即使把CPU分配給該進(jìn)程,它也無法運(yùn)行,故稱該進(jìn)程處于阻塞狀態(tài)。5.2進(jìn)程狀態(tài)2023/7/26Dr.沙行勉52簡(jiǎn)單起見,僅考慮操作系統(tǒng)對(duì)一個(gè)Core的管理。在某一時(shí)刻,處于就緒態(tài)的進(jìn)程常常不止一個(gè),所以,操作系統(tǒng)維護(hù)了一個(gè)就緒隊(duì)列,存放所有處于就緒態(tài)的進(jìn)程。在單核的系統(tǒng)里僅有一個(gè)進(jìn)程處于運(yùn)行態(tài),其它已準(zhǔn)備好可執(zhí)行的進(jìn)程則位于就緒隊(duì)列。當(dāng)正在運(yùn)行的進(jìn)程時(shí)間片消耗完后,這個(gè)進(jìn)程被換出CPU,進(jìn)入就緒隊(duì)列,或者該進(jìn)程需要等待某事件(例如I/O),這個(gè)進(jìn)程也被換出CPU,進(jìn)入阻塞態(tài)的等待隊(duì)列。這樣,可以以使其它處于就緒隊(duì)列的進(jìn)程共享地使用CPU資源。這時(shí),操作系統(tǒng)的調(diào)度器會(huì)從就緒隊(duì)列中選擇一個(gè)進(jìn)程進(jìn)入CPU執(zhí)行,并將此進(jìn)程置于運(yùn)行態(tài)。處于阻塞態(tài)的進(jìn)程將在其所等事件完成后,重新被調(diào)入到就緒隊(duì)列,等待調(diào)度器的選擇以繼續(xù)執(zhí)行。5.3進(jìn)程調(diào)度(Scheduling)——衡量指標(biāo)2023/7/26Dr.沙行勉53不同的進(jìn)程調(diào)度策略會(huì)給系統(tǒng)帶來不同的影響。要衡量調(diào)度策略的好壞,需要引入一些評(píng)價(jià)指標(biāo)。對(duì)一個(gè)進(jìn)程來說,一個(gè)重要的指標(biāo)是進(jìn)程的執(zhí)行所需時(shí)間,用“周轉(zhuǎn)時(shí)間”來刻畫。周轉(zhuǎn)時(shí)間(Turnaroundtime)指從進(jìn)程首次進(jìn)入就緒隊(duì)列到完成的時(shí)間間隔,它刻畫了用戶需要等待輸出結(jié)果的時(shí)間。對(duì)于一個(gè)進(jìn)程而言,周轉(zhuǎn)時(shí)間越小越好。對(duì)于多個(gè)進(jìn)程,衡量的指標(biāo)為“平均周轉(zhuǎn)時(shí)間”。平均周轉(zhuǎn)時(shí)間即為所有進(jìn)程的周轉(zhuǎn)時(shí)間之和除以進(jìn)程數(shù),系統(tǒng)的平均周轉(zhuǎn)時(shí)間越小越好。評(píng)價(jià)系統(tǒng)好壞的另一個(gè)重要指標(biāo)為吞吐量(Throughput),是指系統(tǒng)在單位時(shí)間內(nèi)完成任務(wù)的數(shù)量。例如,對(duì)于一個(gè)系統(tǒng)而言,每小時(shí)完成50個(gè)任務(wù)的調(diào)度算法優(yōu)于每小時(shí)完成40個(gè)任務(wù)的調(diào)度算法。5.3進(jìn)程調(diào)度——先來先服務(wù)(FCFS)2023/7/26Dr.沙行勉54先來先服務(wù)調(diào)度算法是按照進(jìn)程進(jìn)入就緒隊(duì)列的先后次序來選擇。先進(jìn)入系統(tǒng)的進(jìn)程優(yōu)先進(jìn)入CPU執(zhí)行。這種算法容易實(shí)現(xiàn),但效率可能不高。優(yōu)缺點(diǎn)有:先來先服務(wù)的進(jìn)程調(diào)度算法有利于有利于長(zhǎng)作業(yè)進(jìn)程,而不利于短作業(yè)。如果一個(gè)長(zhǎng)作業(yè)先進(jìn)入就緒隊(duì)列,那么就會(huì)使就緒隊(duì)列中的短作業(yè)等待較長(zhǎng)的時(shí)間。例如,程序A需要100分鐘執(zhí)行,它先到達(dá)就緒隊(duì)列,程序B只需要1分鐘執(zhí)行,但是后到達(dá)就緒隊(duì)列。根據(jù)先到先服務(wù)的算法,程序A先執(zhí)行,程序B后執(zhí)行,那么程序B要等待100分后才能執(zhí)行,所以B的周轉(zhuǎn)時(shí)間為101,而程序A的周轉(zhuǎn)時(shí)間為100,平均周轉(zhuǎn)時(shí)間為100.5。如果先執(zhí)行程序B,那么B的周轉(zhuǎn)時(shí)間為1,A的周轉(zhuǎn)時(shí)間為101,平均周轉(zhuǎn)時(shí)間為51。FCFS算法不利于短作業(yè)而有利于長(zhǎng)作業(yè),并且FCFS會(huì)使得平均周轉(zhuǎn)時(shí)間變長(zhǎng)。5.3進(jìn)程調(diào)度——短作業(yè)優(yōu)先(SJF)2023/7/26Dr.沙行勉55短作業(yè)優(yōu)先調(diào)度是對(duì)預(yù)計(jì)執(zhí)行時(shí)間短的作業(yè)優(yōu)先分配處理資源,它克服了FCFS的缺點(diǎn),并且易于實(shí)現(xiàn)。優(yōu)先調(diào)用短作業(yè)的策略將降低作業(yè)的平均等待時(shí)間,有利于提高系統(tǒng)吞吐量。比如說,對(duì)一個(gè)需要同時(shí)處理大量短作業(yè)和長(zhǎng)作業(yè)的系統(tǒng),如果調(diào)度算法總是運(yùn)行短作業(yè),不運(yùn)行長(zhǎng)作業(yè),系統(tǒng)將獲得極好的吞吐量(每個(gè)小時(shí)完成作業(yè)的數(shù)量)。但是,短作業(yè)優(yōu)先調(diào)度存在三個(gè)缺點(diǎn):一是系統(tǒng)需要預(yù)先知道作業(yè)的執(zhí)行時(shí)間,然而,執(zhí)行時(shí)間有時(shí)是難以預(yù)測(cè);二是該調(diào)度算法忽略了作業(yè)的等待時(shí)間,尤其是長(zhǎng)作業(yè)的等待時(shí)間。短作業(yè)優(yōu)先調(diào)度算法對(duì)于長(zhǎng)作業(yè)來講,是不公平的,這些長(zhǎng)作業(yè)可能長(zhǎng)時(shí)間得不到執(zhí)行,它們的周轉(zhuǎn)時(shí)間十分長(zhǎng),出現(xiàn)饑餓現(xiàn)象(指的是進(jìn)程一直得不到系統(tǒng)資源);三是短作業(yè)優(yōu)先調(diào)度策略未考慮作業(yè)的緊迫程度。5.3進(jìn)程調(diào)度——短作業(yè)優(yōu)先(SJF)2023/7/26Dr.沙行勉56考慮以下例子,表中給出了一批任務(wù),包括每個(gè)任務(wù)到達(dá)系統(tǒng)的時(shí)間,執(zhí)行時(shí)間等信息。該系統(tǒng)時(shí)間片為5個(gè)時(shí)間單位。在第0時(shí)刻,進(jìn)程2,3到達(dá)系統(tǒng),使用短作業(yè)優(yōu)先調(diào)度策略,進(jìn)程3優(yōu)先調(diào)度;在時(shí)刻5時(shí),進(jìn)程4,5都已到達(dá),現(xiàn)在的最短任務(wù)是進(jìn)程5,所以進(jìn)程5開始執(zhí)行;第10時(shí)刻,進(jìn)程5執(zhí)行完成,現(xiàn)在就緒隊(duì)列中,4號(hào)進(jìn)程的執(zhí)行時(shí)間最短,所以調(diào)入4號(hào)進(jìn)程;第20時(shí)刻,4號(hào)進(jìn)程執(zhí)行完成,讓出CPU,重新調(diào)入3號(hào)進(jìn)程;最后,調(diào)入2號(hào)進(jìn)程執(zhí)行。進(jìn)程PID到達(dá)時(shí)間執(zhí)行時(shí)間2020301544105555.3進(jìn)程調(diào)度2023/7/26Dr.沙行勉57如果使用先來先服務(wù)調(diào)度,那么系統(tǒng)將依次執(zhí)行任務(wù)2,3,4,5。根據(jù)以上兩個(gè)調(diào)度策略,以及之前介紹的周轉(zhuǎn)時(shí)間的計(jì)算,可以得到下表的任務(wù)執(zhí)行信息。使用短作業(yè)優(yōu)先調(diào)度的系統(tǒng),執(zhí)行完這4個(gè)任務(wù)的平均周轉(zhuǎn)時(shí)間為25.25,而使用先來先服務(wù)調(diào)度策略的系統(tǒng)平均周轉(zhuǎn)時(shí)間為35.25。從表中還可以觀察到,短作業(yè)優(yōu)先調(diào)度對(duì)長(zhǎng)作業(yè)不利,如任務(wù)2,使用SJF策略的周轉(zhuǎn)時(shí)間相比于FCFS策略的周轉(zhuǎn)時(shí)間較長(zhǎng)。但是SJF策略得到的系統(tǒng)平均周轉(zhuǎn)時(shí)間相比于FCFS,得到明顯得提高。任務(wù)PID短作業(yè)優(yōu)先調(diào)度先來先服務(wù)調(diào)度開始執(zhí)行時(shí)間結(jié)束時(shí)間周轉(zhuǎn)時(shí)間開始執(zhí)行時(shí)間結(jié)束時(shí)間周轉(zhuǎn)時(shí)間230505002020303030203535410201635454155105455045第6節(jié)文件系統(tǒng)()2023/7/26Dr.沙行勉58文件基本概念目錄樹結(jié)構(gòu)Python中的文件操作學(xué)生實(shí)例的擴(kuò)展引言2023/7/26Dr.沙行勉59現(xiàn)代計(jì)算機(jī)系統(tǒng)中,需要用到大量的程序和數(shù)據(jù)。通過前面的學(xué)習(xí)知道,內(nèi)存的速度雖然遠(yuǎn)遠(yuǎn)大于外存,但其容量有限,且不能長(zhǎng)期保存程序和數(shù)據(jù)信息。因此,系統(tǒng)將這些程序和數(shù)據(jù)組織成文件,存儲(chǔ)在外存設(shè)備(硬盤、光盤、U盤等)中。例如,在本書之前章節(jié)中編寫的Python代碼都會(huì)存儲(chǔ)到一個(gè)文件中。平時(shí)生活中聽的音樂,拍的照片,也都會(huì)以2進(jìn)制信息存儲(chǔ)于一個(gè)文件之中。對(duì)于存儲(chǔ)在外存設(shè)備的文件,使用時(shí)需要先要調(diào)入內(nèi)存。如果由用戶直接管理這些文件,不僅要求用戶熟悉外存特性,了解各個(gè)需要使用文件的屬性,還要知道這些文件在外存中存儲(chǔ)的位置。顯然,這些繁雜得工作不能交付給用戶完成。于是,對(duì)文件的管理順理成章地交付給了操作系統(tǒng)。操作系統(tǒng)中有一個(gè)文件系統(tǒng),專門負(fù)責(zé)管理外存上的文件。這不僅方便了用戶對(duì)文件的操作,同時(shí)保證了系統(tǒng)中文件的安全性。6.1文件基本概念2023/7/26Dr.沙行勉60文件命名各個(gè)操作系統(tǒng)的文件命名規(guī)則有所不同,文件名的格式和長(zhǎng)度因系統(tǒng)而異。常見的文件名由兩部分構(gòu)成,格式為:“文件名.擴(kuò)展名”。文件名與擴(kuò)展名都是由字母或數(shù)字組成的字符串,通常文件的文件名可以由用戶自定義,而文件的后綴名則是代表不同的文件類型。例如在Windows下,可執(zhí)行文件為“文件名.exe”,Python文件多以“.py”結(jié)尾,常見的音視頻文件如:“文件名.mp3”,“文件名.mp4”,“文件名.avi”等。6.1文件基本概念2023/7/26Dr.沙行勉61文件的類型在前面兩個(gè)小節(jié)中已經(jīng)介紹,Linux中將顯示器、打印機(jī)等外設(shè)也看作是一個(gè)文件,而系統(tǒng)根據(jù)文件所具有的不同類型,能夠區(qū)分普通文件與外設(shè)文件以及各個(gè)不同種類的外設(shè)。具體來講,Linux中支持如下幾種文件類型:普通文件:指存儲(chǔ)于外存設(shè)備上,通常意義上的文件,包括用戶建立的源程序(python、C、C++)文件,數(shù)據(jù)(照片、音視頻等)文件,庫(提供系統(tǒng)調(diào)用)文件、可執(zhí)行程序文件等。目錄文件:統(tǒng)一管理普通文件等(類似Windows文件夾)。一個(gè)目錄文件可包含多個(gè)普通文件,也可包含目錄文件,它為文件系統(tǒng)形成了一個(gè)邏輯上的結(jié)構(gòu)。塊設(shè)備文件:用于管理磁盤、光盤等塊設(shè)備,并提供相應(yīng)的I/O操作字符設(shè)備文件:用于管理打印機(jī)等支付設(shè)備,并提供相應(yīng)I/O操作除了以上類型的文件之外,Linux文件類型還包括套接字文件(用于網(wǎng)絡(luò)通信),命名管道文件(用于進(jìn)程間通信)。6.2目錄樹結(jié)構(gòu)2023/7/26Dr.沙行勉62如何實(shí)現(xiàn)多個(gè)文件具有相同的文件名。目錄樹結(jié)構(gòu)解決了這個(gè)問題。在文件系統(tǒng)目錄樹中,最頂層的節(jié)點(diǎn)為根目錄,從根目錄向下,每一個(gè)有分支的節(jié)點(diǎn)是一個(gè)子目錄,而樹葉節(jié)點(diǎn)(沒有分支)就是一個(gè)文件。例如,下圖所示,“/”所示節(jié)點(diǎn)為根節(jié)點(diǎn),該節(jié)點(diǎn)為一個(gè)目錄文件,其下有dev、bin、usr三個(gè)目錄文件,usr目錄下,又有阿珍的目錄,小明的目錄以及本教材文件。這樣,即便阿珍和小明有同名的文件,兩個(gè)文件所在路徑是不同的,就可以區(qū)分這兩個(gè)文件了。6.2目錄樹結(jié)構(gòu)2023/7/26Dr.沙行勉63目錄查找是文件系統(tǒng)的一項(xiàng)很重要的工作,每當(dāng)需要使用系統(tǒng)調(diào)用open打開文件時(shí),必須要求給出路徑名及文件名。例如,要打開小明寫的名為os.py的Python文件,需要使用fd=open(“/usr/Ming/os.py”)進(jìn)行打開,有了文件描述符fd后,就可以對(duì)該文件進(jìn)行一系列操作了。路徑通常可以分為兩類:絕對(duì)路徑與相對(duì)路徑。絕對(duì)路徑是指從根向下直到具體文件的完整路徑,如上述例子“/usr/Ming/os.py”就是一個(gè)絕對(duì)路徑。但是,隨著文件系統(tǒng)層次的增加,使用絕對(duì)路徑變得十分繁瑣。更糟的情況是,在某文件系統(tǒng)下寫的程序要到另一個(gè)文件系統(tǒng)下去運(yùn)行,如果使用絕對(duì)路徑,要求兩個(gè)文件系統(tǒng)有相同的目錄樹結(jié)構(gòu),這是不靈活的。為了解決這一系列的問題,在程序中除了使用絕對(duì)路徑外,還可以使用相對(duì)路徑。相對(duì)路徑就是指目標(biāo)文件的位置與當(dāng)前所在目錄的路徑關(guān)系。相對(duì)路徑中包含兩個(gè)符號(hào)“.”、“..”,其中“.”表示當(dāng)前目錄,而“..”表示父節(jié)點(diǎn)目錄。例如,在/usr/Ming/os.py中,“./”表示“/usr/Ming”目錄,而“../”表示“/usr”目錄。6.2目錄樹結(jié)構(gòu)2023/7/26Dr.沙行勉64普通我們讀寫一個(gè)文件的順序是(1)open這個(gè)文件,參數(shù)包含了路徑。(2)用一個(gè)循環(huán)來讀/寫(read/write)文件里的數(shù)據(jù)。為什么要先做open,而不是在每次在讀寫操作的時(shí)候去尋找路徑呢?open的目的是什么?仔細(xì)研究open函數(shù),就會(huì)發(fā)覺open是個(gè)很花時(shí)間的操作,尤其是當(dāng)路徑要經(jīng)過多重目錄的時(shí)候。每一層目錄都要做硬盤I/O操作,尋找下一個(gè)子目錄,一層層地找下去,open包含了這么多I/O操作是花時(shí)間的。我們希望花時(shí)間的操作在循環(huán)之前只做一次,而不要在每次循環(huán)中都做一次。所以我們?cè)谘h(huán)前做open操作是有利的。而open操作的目的是(1)最終獲得此文件數(shù)據(jù)在硬盤中的位置,(2)在路徑遍歷過程中,檢查用戶是否有權(quán)限來做此文件的操作。(3)當(dāng)有多個(gè)進(jìn)程要讀寫相同的文件時(shí),有時(shí)需要利用open在讀寫前鎖住文件,以取得文件的一致性。所以open的功用是多樣的。6.2目錄樹結(jié)構(gòu)2023/7/26Dr.沙行勉65Python語言給編程者提供了一系列方便的文件讀寫操作函數(shù),而這些文件操作函數(shù)的具體實(shí)現(xiàn)中,會(huì)調(diào)用之前所介紹的系統(tǒng)調(diào)用(軟件中斷)來要求操作系統(tǒng)提供服務(wù),就是執(zhí)行int指令。這些調(diào)用操作系統(tǒng)的細(xì)節(jié)較為復(fù)雜,一般用戶是不需要知道細(xì)節(jié)的,用戶只要享受Python所提供方便的文件讀寫函數(shù)就好了。所以,當(dāng)小明要在os.py中打開Task1文件,只要了解Python為編程者提供了哪些文件操作函數(shù)就好了。下一小節(jié)將對(duì)此展開進(jìn)行介紹。6.3Python中的文件操作2023/7/26Dr.沙行勉66Python提供了文件對(duì)象,并內(nèi)置了open函數(shù)來獲取一個(gè)文件對(duì)象。Open函數(shù)的使用:=open(path,mode)。其中,是調(diào)用open函數(shù)后得到的文件對(duì)象;path是一個(gè)字符串,代表要打開文件的路徑;而mode是打開文件的模式,常用的模式如下表所示。小明在os.py中要打開Task1文件進(jìn)行讀寫,需要使用r+模式,實(shí)現(xiàn)如下:f=open('./Task1','r+')。簡(jiǎn)單一個(gè)語句便實(shí)現(xiàn)了打開文件的操作,之后對(duì)該文件的操作只需對(duì)新得到的文件對(duì)象f,使用文件對(duì)象提供的方法即可。文件模式解釋r以只讀方式打開:只允許對(duì)文件進(jìn)行讀操作,不允許寫操作。(默認(rèn)方式)w以寫方式打開:文件不為空時(shí)清空文件,文件不存在時(shí)新建文件。a追加模式:文件存在則在寫入時(shí)將內(nèi)容添加到末尾。r+以讀寫模式打開:打開的文件即可讀又可寫6.3Python中的文件操作——常用方法2023/7/26Dr.沙行勉67下表給出了文件對(duì)象提供的常用方法,同第四章,參數(shù)中的[]符號(hào)表示括號(hào)中的值可以傳遞也可以不傳遞:讀寫操作是文件操作的最主要的操作,下面將主要講解表中的f.readline()、f.readlines()和f.writelines(list)方法。方法作用/返回參數(shù)f.close()關(guān)閉文件:用open()打開文件后使用close關(guān)閉。無f.read([count])讀出文件:讀出count個(gè)字節(jié)。如果沒有參數(shù),讀取整個(gè)文件[count]f.readline()讀出一行信息,保存于list:每讀完一行,移至下一行開頭。無f.readlines()讀出所有行,保存在字符串列表中。無f.truncate([size])截取文件,使文件的大小為size。[size]f.write(string)把string字符串寫入文件。字符串f.writelines(list)把list中的字符串寫入文件,是連續(xù)寫入文件,沒有換行。字符串6.3Python中的文件操作——讀取文件內(nèi)容2023/7/26Dr.沙行勉68#<程序:讀取文件os.py>f=open("./Task1.txt",'r');fls=f.readlines()forlineinfls: line=line.strip();print(line)f.close()當(dāng)小明打開文件Task1.txt后,想要讀取該文件的內(nèi)容,并打印出來。那么,os.py的實(shí)現(xiàn)如右方所示。使用readlines方法后,返回一個(gè)list,該list的每一個(gè)元素為文件的一行信息。需要注意的是,文件的每行信息包括了最后的換行符“\n”,在進(jìn)行字符串處理時(shí),通常需要使用strip方法將頭尾的空白和換行符號(hào)等等去掉。6.3Python中的文件操作——寫入文件2023/7/26Dr.沙行勉69#<程序:讀取文件os.py,計(jì)算并寫回>f=open("./Task1.txt",'r+');fls=f.readlines()forlineinfls: line=line.strip()
lstr=line.split() iflstr[0]=='3': res=0 foreinlstr[1:]: res+=int(e)f.write('\n4'+str(res));f.close()實(shí)例1將文件Task1的內(nèi)容全部讀入到fls列表中。實(shí)例二要將文件首字符為“3”的行中每一個(gè)數(shù)字加起來,不包括3,即“105192037”;然后,將結(jié)果寫入到文件末尾。分析:首先要獲取首字符3,為此,可以用split()函數(shù)將每一行字符串按空格分解為每個(gè)元素不包含空格的list。然后判斷l(xiāng)ist[0]是不是字符3。然后需要計(jì)算該list從1號(hào)元素開始的所有元素的和。最后,需要將結(jié)果寫回文件,所以,文件的打開方式應(yīng)為“r+”。6.3Python中的文件操作——經(jīng)驗(yàn)談2023/7/26Dr.沙行勉70經(jīng)驗(yàn)談open()與close()成對(duì)出現(xiàn):在使用文件操作時(shí),首先需要使用open()打開文件,每次對(duì)文件操作完成后,不要遺忘c(diǎn)lose()操作,將打開并操作完成的文件關(guān)閉。養(yǎng)成這個(gè)習(xí)慣可以避免程序出現(xiàn)很多奇怪的BUG。事實(shí)上,每個(gè)進(jìn)程打開文件的數(shù)量是有限的,每次系統(tǒng)打開文件后會(huì)占用一個(gè)文件描述符,而關(guān)閉文件時(shí)會(huì)釋放這個(gè)文件描述符,以便系統(tǒng)打開其它文件。6.4學(xué)生實(shí)例的擴(kuò)展2023/7/26Dr.沙行勉71回顧本書第四章里Python面向?qū)ο缶幊虒?shí)例,該例中實(shí)現(xiàn)了學(xué)生類與課程類,以及模擬考試等內(nèi)容。但是每一學(xué)期的信息不能只在Python運(yùn)行一次就結(jié)束,因此需要將學(xué)期結(jié)束后學(xué)生信息保存到文件,以方便管理。對(duì)于統(tǒng)計(jì)后的成績(jī),需要為班主任查詢學(xué)生成績(jī)信息的接口,也要為學(xué)生提供個(gè)人成績(jī)查詢的接口。本小節(jié)將實(shí)現(xiàn)一些常用的功能,例如班主任要查看GPA小于3.0的同學(xué),或者選擇學(xué)分不足13學(xué)分的學(xué)生等操作。首先,以下程序?qū)W(xué)生考試結(jié)果存儲(chǔ)到命名為班級(jí)1的文件class1.txt中:根據(jù)文件操作相關(guān)方法,先將需要存入文件的內(nèi)容存放至一個(gè)list(SaveToFile變量)中。然后使用open打開文件,設(shè)置為w模式,即文件打開可以進(jìn)行寫操作。接著,通過SaveToFile,將內(nèi)容寫入到打開的文件中。最后關(guān)閉所打開的文件。6.4學(xué)生實(shí)例的擴(kuò)展——存儲(chǔ)考試結(jié)果2023/7/26Dr.沙行勉72#<程序:存儲(chǔ)考試結(jié)果到class1.txt文件>…… #第四章<程序:學(xué)生數(shù)據(jù)庫主程序>SaveToFile=["ID","","Name","","Credit","","GPA","\n"]forstuinStudentDict.values(): SaveTo(str(stu.StuID)) SaveTo("") SaveTo(str()) SaveTo("") SaveTo(str(stu.Credit)) SaveTo("") SaveTo(str(stu.GPA)) SaveTo("\n")f=open("class1.txt","w")f.writelines(SaveToFile)f.close()請(qǐng)注意程序中StudentDict.values()返回的是
class'dict_values',即dict_values對(duì)象。該對(duì)象支持遍歷(iterable)但不支持索引(indexable)。也就是說,可以使用for循環(huán)進(jìn)行遍歷,但是不能使用下標(biāo)操作(索引)。在第四章中,因?yàn)?/p>
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2020-2022年北京市初三一模道德與法治試題匯編:做守法的公民
- 廣東省深圳市寶安區(qū)文匯學(xué)校2019-2020學(xué)年八年級(jí)第二學(xué)期(3月份)月考數(shù)學(xué)試卷-含解析
- 物理-陜西省安康市2025屆高三下學(xué)期第二次質(zhì)量聯(lián)考(安康二模)試題和答案
- 油漆噴涂施工方案
- 座椅安裝施工方案
- 職業(yè)西藥師知識(shí)培訓(xùn)課件
- 北京征地拆遷合同范例
- 勞務(wù)分包安全合同范例
- 農(nóng)業(yè)社團(tuán)實(shí)踐與體驗(yàn)安排計(jì)劃
- 人力資源部的內(nèi)部安全管理計(jì)劃
- 《食品安全抽樣檢驗(yàn)工作規(guī)范》附件文書2024
- 《數(shù)據(jù)庫應(yīng)用基礎(chǔ)(Access 2010)》中職全套教學(xué)課件
- 2024兒童青少年抑郁治療與康復(fù)痛點(diǎn)調(diào)研報(bào)告 -基于患者家長(zhǎng)群體的調(diào)研
- 蕪湖2024年安徽蕪湖傳媒中心招聘編外工作人員5人筆試歷年典型考題及考點(diǎn)附答案解析
- AED使用指南課件
- JT-T-445-2021汽車底盤測(cè)功機(jī)
- 醫(yī)療場(chǎng)所消防安全檢查
- 江蘇省建筑與裝飾工程計(jì)價(jià)定額(2014)電子表格版
- 我畫的動(dòng)漫形象說課
- 會(huì)計(jì)科研方法與研究前沿
- 東北三省三校2024年高三二模(第二次聯(lián)合模擬考試)英語試卷(含標(biāo)準(zhǔn)答案)
評(píng)論
0/150
提交評(píng)論