中國科學院大學操作系統考試思考題答案_第1頁
中國科學院大學操作系統考試思考題答案_第2頁
中國科學院大學操作系統考試思考題答案_第3頁
中國科學院大學操作系統考試思考題答案_第4頁
中國科學院大學操作系統考試思考題答案_第5頁
已閱讀5頁,還剩6頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、1. 為什么計算機啟動最開始的時候執行的是BIOS代碼而不是操作系統自身的代碼?答:通常我們用C語言寫的用戶程序,必須在操作系統的平臺上執行,即操作系統為應用程序創建進程并把應用程序的可執行代碼加載到內存。計算機啟動的時候,操作系統并沒有在內存中,我們首先要把操作系統加載到內存,而這個工作最開始的部分,就是由bios 程序來實現的。所以計算機啟動最開始執行的是 bios 代碼2. 為什么BIOS只加載了一個扇區,后續扇區卻是由bootsect代碼加載?為什么BIOS沒有把所有需要加載的扇區都加載?答:對 BIOS 而言,“約定”在接到啟動操作系統的命令后,“定位識別”只從啟動扇區把代碼加載到

2、0x7c00 這個位置。后續扇區則由 bootsect 代碼加載,這些代碼由編寫系統的用戶負責,與 BIOS 無關。這樣構建的好處是站在整個體系的高度,統一設計和統一安排,簡單而有效。BIOS 和操作系統的開發都可以遵循這一約定,靈活地進行各自的設計。例如, BIOS可以不用知道內核鏡像的大小以及其在軟盤的分布等等信息,減輕了 BIOS 程序的復雜度,降低了硬件上的開銷。而操作系統的開發者也可以按照自己的意愿,內存的規劃,等等都更為靈活。另外,如果要使用BIOS進行加載,而且加載完成之后再執行,則需要很長的時間,因此Linux采用的是邊執行邊加載的方法。3. 為什么BIOS把bootsect加

3、載到0x07c00,而不是0x00000?加載后又馬上挪到0x90000處,是何道理?為什么不一次加載到位?答:因為BIOS首先會把中斷向量表加載到0x00000-0x003ff的1KB的內存空間,在加載bootsect時約定加載到0x07c00處,符合內存布局,如下。加載之后挪到0x90000處的原因如下:首先內核會使用啟動扇區中的一些數據,如第 508、509 字節處的 ROOT_DEV;其次,依據系統對內存的規劃,內核占用 0x0000 開始的空間,因此 0x7c00 可能會被覆蓋。因為加載到0x07c00是BIOS約定好的,操作系統只能遵守這個約定。4. bootsect、setup、

4、head程序之間是怎么銜接的?給出代碼證據。答:bootsect首先利用int 0x13中斷分別加載setup程序及system模塊,待bootsect程序的任務完成之后,執行jmpi 0,SETUPSEG由于 bootsect 將 setup 段加載到了 SETUPSEG:0 的地方,在實模式下,該指令跳轉到setup段的第一條指令。 setup 執行了之后,內核被移到了0x00000處,系統進入了保護模式,并加載了中斷描述符表和全局描述符表lidt idt_48lgdt gdt_48在保護模式下,一個重要的特征就是根據GDT決定后續執行哪里的程序。開啟保護模式后,執行jmpi 0, 8根據

5、保護模式的機制,該指令執行后跳轉到以GDT第2項中的 base_addr 為基地址,以0為偏移量的地方,其中base_addr為0。由于head放置在內核的頭部,因此程序跳轉到head中執行5. setup程序里的cli是為了什么?答:cli是關中斷指令。因為此時需要由16位實模式向32位保護模式轉變,即將進行實模式下的中斷向量表和保護模式下中斷描述符表的交接工作,在保護模式的中斷機制尚未完成時不允許響應中斷,以免發生未知的錯誤。6. setup程序的最后是jmpi 0,8 為什么這個8不能簡單的當作阿拉伯數字8看待?答:這里 8 要看成二進制 1000,最后兩位00表示內核特權級,第三位0表

6、示 GDT 表,第四位1表示根據GDT中的第2項來確定代碼段的段基址和段限長等信息。這樣,我們可以得到代碼是從段基址 0x00000000、偏移為 0 處開始執行的,即 head 的開始位置。注意到已經開啟了保護模式的機制,這里的8是保護模式下的段選擇符,而不能當成簡單的阿拉伯數字8來看待。7. 打開A20和打開pe究竟是什么關系,保護模式不就是32位的嗎?為什么還要打開A20?有必要嗎?答:有必要。A20是cpu的第 21 位地址線,A20 未打開的時候,實模式下的最大尋址為 1MB+64KB,而第21根地址線被強制為0,所以相當于 cpu“回滾”到內存地址起始處尋址。打開A20僅僅意味著C

7、PU可以進行32位尋址,且最大尋址空間是4GB,而打開PE是使能保護模式。打開A20是打開PE的必要條件;而打開A20不一定非得打開PE。打開PE是說明系統處于保護模式下,如果不打開A20的話,可以訪問的內存只能是奇數1M段,若要真正在保護模式下工作,必須打開A20,實現32位尋址。8. Linux是用C語言寫的,為什么沒有從main還是開始,而是先運行3個匯編程序,道理何在?答:通常用 C 語言編寫的程序都是用戶應用程序,這類程序的執行必須在操作系統上執行,也就是說要由操作系統為應用程序創建進程,并把應用程序的可執行代碼從硬盤加載到內存。而在計算機剛剛加電時,內存中沒有操作系統程序,只有BI

8、OS 程序在運行,需要借助BIOS分別加載bootsect、setup及system模塊,然后利用這3個程序來完成內存規劃、建立IDT和GDT、設置分頁機制等等,并實現從開機時的16位實模式到 main 函數執行需要的32位保護模式之間的轉換。當計算機處在32 位的保護模式狀態下時,調用main的條件才算準備完畢。9. 為什么不用call,而是用ret“調用”main函數?畫出調用路線圖,給出代碼證據。答:CALL 指令會將 EIP 的值自動壓棧,保護返回現場,然后執行被調函數,檔執行到被調函數的ret指令時,自動出棧給 EIP 并還原現場,繼續執行CALL 的下一行指令。在由head程序向m

9、ain函數跳轉時,是不需要main函數返回的;同時由于main函數已經是最底層的函數了,沒有更底層的支撐函數支持其返回。所以要達到既調用 main又不需返回,就不采用 call 而是選擇了 ret“調用”了。調用線路圖見P42 圖1-46。代碼如下:(見P36 最下面)setup_paging:ret10. 保護模式的“保護”體現在哪里?答:打開了保護模式后,CPU 的尋址模式發生了變化,需要依賴于 GDT 去獲取代碼或數據段的基址。從 GDT 可以看出,保護模式除了段基址外,還有段限長,這樣相當于增加了一個段位寄存器。既有效地防止了對代碼或數據段的覆蓋,又防止了代碼段自身的訪問超限,明顯增強

10、了保護作用。同時,保護模式中特權級的引入對于操作系統內核提供了強有力的保護。Intel 從硬件上禁止低特權級代碼段使用一些關鍵性指令,還提供了機會允許操作系統設計者通過一些特權級的設置,禁止用戶進程使用 cli、sti 等對掌控局面至關重要的指令。有了這些基礎,操作系統可以把內核設計成最高特權級,把用戶進程設計成最低特權級。這樣,操作系統可以訪問 GDT、LDT、TR,而 GDT、LDT 是邏輯地址形成線性地址的關鍵,因此操作系統可以掌控線性地址。物理地址是由內核將線性地址轉換而成的,所以操作系統可以訪問任何物理地址,而用戶進程只能使用邏輯地址。 11. 特權級的目的和意義是什么?為什么特權級

11、是基于段的?答:特權級是操作系統為了更好地管理內存空間及其訪問控制而設的,提高了系統的安全性。保護模式中特權級的引入對于操作系統內核提供了強有力的保護。Intel 從硬件上禁止低特權級代碼段使用一些關鍵性指令,還提供了機會允許操作系統設計者通過一些特權級的設置,禁止用戶進程使用 cli、sti 等對掌控局面至關重要的指令。有了這些基礎,操作系統可以把內核設計成最高特權級,把用戶進程設計成最低特權級。這樣,操作系統可以訪問 GDT、LDT、TR,而 GDT、LDT 是邏輯地址形成線性地址的關鍵,因此操作系統可以掌控線性地址。物理地址是由內核將線性地址轉換而成的,所以操作系統可以訪問任何物理地址,

12、而用戶進程只能使用邏輯地址。 在操作系統設計中,一般一個段實現的功能相對完整,可以把代碼放在一個段,數據放在一個段,并通過段選擇符(包括 CS、SS、DS、ES、FS 和 GS)獲取段的基址和特權級等信息。特權級基于段,這樣當段選擇子具有不匹配的特權級時,按照特權級規則判斷是否可以訪問。特權級基于段,是結合了程序的特點和硬件實現的一種考慮。12. 在setup程序里曾經設置過一次gdt,為什么在head程序中將其廢棄,又重新設置了一個?為什么折騰兩次,而不是一次搞好?答:見P33 點評。13. 在head程序執行結束的時候,在idt的前面有184個字節的head程序的剩余代碼,剩余了什么?為什

13、么要剩余?答:在idt前面有184個字節的剩余代碼,包含了after_page_tables、 ignore_int 和 setup_paging代碼段,其中after_page_tables往棧中壓入了些參數,ignore_int 用做初始化中斷時的中斷處理函數,setup_paging 則是初始化分頁。剩余的原因:after_page_tables 中壓入了一些參數,為內核進入 main 函數的跳轉做準備。為了謹慎起見,設計者在棧中壓入了 L6,以使得系統可能出錯時,返回到 L6 處執行。ignore_int 為中斷處理函數,使用 ignore_int 將 idt 全部初始化,因此如果中斷

14、開啟后,可能使用了未設置的中斷向量,那么將默認跳轉到 ignore_int 處執行。這樣做的好處是使得系統不會跳轉到隨機的地方執行錯誤的代碼,所以 ignore_int 不能被覆蓋。setup_paging 用于分頁,在該函數中對 0x0000 和 0x5000 的進行了初始化操作。該代碼需要“剩余”用于跳轉到 main,即執行”ret ”指令。14. 進程0的task_struct在哪?具體內容是什么?給出代碼證據。答:進程0的task_struct是操作系統設計者事先寫好的,位于內核數據區,存儲在user_stack中。(因為在進程0未激活之前,使用的是boot階段的user_stack。

15、)static union task_union init_task=INIT_TASK;具體內容如下:包含了進程 0 的進程狀態、進程 0 的 LDT、進程 0 的 TSS 等等。其中 ldt 設置了代碼段和堆棧段的基址和限長(640KB),而 TSS 則保存了各種寄存器的值,包括各個段選擇符。代碼如下:INIT_TASK的定義見P68。15. 進程0創建進程1時,為進程1建立了自己的task_struct、內核棧,第一個頁表,分別位于物理內存16MB的頂端倒數第一頁、第二頁。請問,這個了頁究竟占用的是誰的線性地址空間,內核、進程0、進程1、還是沒有占用任何線性地址空間(直接從物理地址分配)

16、?說明理由并給出代碼證據。答:占用的是內核的線性地址空間。(先理解清楚,稍后補充)16. 假設:經過一段時間的運行,操作系統中已經有5個進程在運行,且內核分別為進程4、進程5分別創建了第一個頁表,這兩個頁表在誰的線性地址空間?用圖表示這兩個頁表在線性地址空間和物理地址空間的映射關系。答:在內核的線性地址空間。(圖片自己畫,參考如下圖)17. 進程0開始創建進程1,調用了fork(),跟蹤代碼時我們發現,fork代碼執行了兩次,第一次,跳過init()直接執行了for(;) pause(),第二次執行fork代碼后,執行了init()。奇怪的是,我們在代碼中并沒有看見向后的goto語句,也沒有看

17、到循環語句,是什么原因導致反復執行?請說明理由,并給出代碼證據。答:進程 0 創建進程1采用了中斷機制,在中斷發生時由硬件將 ss,esp,eflags,cs,eip的值壓入了內核棧,其中 eip 的值指向了 int 0x80 的下一條指令。在執行fork時,通過0x80號系統調用,內核執行copy_process函數,為進程1準備其管理結構(task_struct),設置進程1的線性地址空間及物理頁面,其中設置了進程1的 TSS 中 eax 的值為 0,狀態為TASK_RUNNING,以及利用中斷壓棧的寄存器值設置進程 1 的 ss,esp,eflags,cs,eip。copy_proces

18、s:p->pid = last_pid;p->tss.eip = eip;p->tss.eflags = eflags;p->tss.eax = 0;p->tss.esp = esp;p->tss.cs = cs & 0xffff;p->tss.ss = ss & 0xffff;p->state = TASK_RUNNING;return last_pid;函數copy_process的返回值是last_pid,即進程1的pid(pid不為0)。在fork返回到進程0后,進程0判斷返回值非 0,因此執行代碼for(;) pause

19、();在sys_pause函數中,內核設置了進程0的狀態為 TASK_INTERRUPTIBLE,并進行進程調度。由于只有進程1處于就緒態,因此調度執行進程1的指令。由于進程1在TSS中設置了eip等寄存器的值,因此從 int 0x80 的下一條指令開始執行,且設定返回 eax 的值作為 fork 的返回值(值為 0),因此進程1執行了 init 的函數。導致反復執行,主要是利用了兩個系統調用 sys_fork 和 sys_pause 對進程狀態的設置,以及利用了進程調度機制。18. copy_process函數的參數最后五項是:long eip,long cs,long eflags,lon

20、g esp,long ss。查看棧結構確實有這五個參數,奇怪的是其他參數的壓棧代碼都能找得到,確找不到這五個參數的壓棧代碼,反匯編代碼中也查不到,請解釋原因。答:在fork()中,當執行“int $0x80”時產生一個軟中斷,該中斷使CPU硬件自動將SS、ESP、EFLAGS、CS、EIP這5個寄存器的數值按照這個順序壓入進程0的內核棧。利用硬件進行壓棧,可以確保 eip 的值指向正確的指令,以使在中斷返回后,程序能夠繼續執行。19. 為什么static inline _syscall0(type,name)中需要加上關鍵字inline?答:inline一般是用于定義內聯函數,內聯函數結合了函

21、數以及宏的優點,在定義時和函數一樣,編譯器會對其參數進行檢查;在使用時和宏類似,內聯函數的代碼會被直接嵌入在它被調用的地方,這樣省去了函數調用時的一些額外開銷,比如保存和恢復函數返回地址等,可以加快速度。20. 根據代碼詳細說明copy_process函數的所有參數是如何形成的?答:一般在應用程序中,一個函數的參數是由函數定義的,而在操作系統底層中,函數參數可以由函數定義以外的程序通過壓棧的方式“做”出來。 copy_process函數的所有參數正是通過壓棧形成的。代碼見P83頁、P85頁、P86頁。21. 根據代碼詳細分析,進程0如何根據調度第一次切換到進程1的。答:通過fork(),進程0

22、創建進程1,并將其狀態設為TASK_RUNNING,fork()函數執行完畢后返回,進入for(;) pause();在sys_pause()中,將當前進程(進程0)的狀態設置為TASK_INTERRUPTBLE,然后執行schedule(),遍歷task數組,找到唯一的一個處于TASK_RUNNING的進程(進程1),然后切換到進程1執行,即switch_to(1)。代碼見P10622. 內核的線性地址空間是如何分頁的?畫出從0x000000開始的7個頁(包括頁目錄表、頁表所在頁)的掛接關系圖,就是頁目錄表的前四個頁目錄項、第一個個頁表的前7個頁表項指向什么位置?給出代碼證據。答:先把頁目錄

23、表和4個頁表放在物理內存的起始地址,從內存起始位置開始的5頁空間內容全部清零(每頁4KB)。然后設置頁目錄表的前4項,使之分別指向4個頁表,將第4個頁表的最后一個頁表項指向尋址范圍的最后一個頁面,將第4個頁表的倒數第二個頁表項指向尋址范圍的倒數第二個頁面,從高地址向低地址方向填寫4個頁面,依次指向內存從高地址向低地址方向的各個頁面。圖見P39(注意要畫出7個頁,參考如下)代碼見P39 最下面23. 用文字和圖說明中斷描述符表是如何初始化的,可以舉例說明(比如:set_trap_gate(0,&divide_error)),并給出代碼證據。答:以set_trap_gate(0,&

24、divide_error)為例,其中,n是0,gate_addr是&idt0,也就是idt的第一項中斷描述符的地址;type是15,dpl(描述符特權級)是0;addr是中斷服務程序divide_error(void)的入口地址。見P54 圖2-9 P53 代碼24. 進程0 fork進程1之前,為什么先要調用move_to_user_mode()?用的是什么方法?解釋其中的道理。答:因為在Linux-0.11中,除進程0之外,所有進程都是由一個已有進程在用戶態下完成創建的。但是此時進程0還處于內核態,因此要調用move_to_user_mode()函數,模仿中斷返回的方式,實現進程0

25、的特權級從內核態轉化為用戶態。又因為在Linux-0.11中,轉換特權級時采用中斷和中斷返回的方式,調用系統中斷實現從3到0的特權級轉換,中斷返回時轉換為3特權級。因此,進程0從0特權級到3特權級轉換時采用的是模仿中斷返回。 設計者首先手工寫壓棧代碼模擬int(中斷)壓棧,當執行iret指令時,CPU自動將這5個寄存器的值(SS,ESP,EFLAGS,CS,EIP)按序恢復給CPU,CPU就會翻轉到3特權級去執行代碼。25. 進程0創建進程1時調用copy_process函數,在其中直接、間接調用了兩次get_free_page函數,在物理內存中獲得了兩個頁,分別用作什么?是怎么設置的?給出代

26、碼證據。答:第一次調用get_free_page函數申請的空閑頁面用于進程1 的task_struct及內核棧。首先將申請到的頁面清0,然后復制進程0的task_struct,再針對進程1作個性化設置,其中esp0 的設置,意味著設置該頁末尾為進程 1 的堆棧的起始地址。代碼見P90 及 P92。 第二次調用get_free_page函數申請的空閑頁面用于進程1的頁表。在創建進程1執行copy_process中,執行copy_mem(nr,p)時,內核為進程1拷貝了進程 0的頁表(160 項),同時修改了頁表項的屬性為只讀。代碼見P98。26. 在IA-32中,有大約20多個指令是只能在0特權

27、級下使用,其他的指令,比如cli,并沒有這個約定。奇怪的是,在Linux0.11中,在3特權級的進程代碼并不能使用cli指令,會報特權級錯誤,這是為什么?請解釋并給出代碼證據。答: cli指令用于復位IF標志位,其執行與CPL(當前特權級)和EFLAGSIOPL標志位有關。只有當CPL小于或等于IOPL時才可以執行該指令。如果在CPL大于IOPL的情況下執行,將會產生一個一般性保護異常,如下:set_trap_gate(13, &general_protection);由于在內核IOPL的初始值為0,且未經改變。進程0在 move_to_user_mode 中,繼承了內核的 eflag

28、s,如下:move_to_user_mode()"pushflnt" "iretn" 是否正確?在TSS中明確設置了eflags的iopl為0在進程0的TSS中,設置了eflags中的 IOPL 位為 0,代碼見P68,后續進程 如果沒有改動的話也是0,即IOPL=0。因此,通過設置 IOPL,可以限制3特權級的進程代碼使用 cli 指令。27. 根據代碼詳細分析操作系統是如何獲得一個空閑頁的。答:代碼見P90 get_free_page函數。過程:(1)將EAX 設置為0,EDI 設置指向mem_map 的最后一項(mem_map+PAGING_PAG

29、ES-1),std設置掃描是從高地址向低地址。從mem_map的最后一項反向掃描,找出引用次數為0(AL)的頁,如果沒有則退出;如果找到,則將找到的頁設引用數為1;(2) ECX左移12位得到頁的相對地址,加LOW_MEM得到物理地址,將此頁最后一個字節的地址賦值給EDI(LOW_MEM+4092);(3) stosl將EAX的值設置到ES:EDI所指內存,即反向清零1024*32bit,將此頁清空;(4) 將頁的地址(存放在EAX)返回。28. 用戶進程自己設計一套LDT表,并與GDT掛接,是否可行,為什么?答:不可行。GDT和LDT放在內核數據區,屬于0特權級,3特權級的用戶進程無權訪問修

30、改。此外,如果用戶進程可以自己設計LDT的話,表明用戶進程可以訪問其他進程的LDT,則會削弱進程之間的保護邊界,容易引發問題。29. 保護模式下,線性地址到物理地址的轉化過程是什么?答:保護模式下,線性地址到物理地址的轉化是借助頁目錄表及頁表完成的。其轉化過程如圖所示(見P97 圖3-9)。Linux 0.11中僅有一個頁目錄表,其地址存放在CR3寄存器中,通過線性地址中的“頁目錄項”數據及CR3寄存器就可以找到頁目錄表中對應的頁目錄項,通過該頁目錄項可以找到對應的頁表,結合線性地址中的“頁表項”數據就可以找到對應的頁表項,通過該頁表項可以找到對應的物理頁面,最后通過線性地址中的“頁內偏移”落

31、實到實際的物理地址值。30. 為什么get_free_page()將新分配的頁面清0?答:Linux在回收頁面時并沒有將頁面清0,只是將mem_map中與該頁對應的位置0。在使用get_free_page申請頁時,也是遍歷mem_map尋找對應位為0的頁,但是該頁可能存在垃圾數據,如果不清0的話,若將該頁用做頁表,則可能導致錯誤的映射,引發錯誤,所以要將新分配的頁面清0。31. 內核和普通用戶進程并不在一個線性地址空間內,為什么仍然能夠訪問普通用戶進程的頁面?答:雖然內核與普通進程并不在一個線性地址空間內,但是用戶進程的頁面最終要從物理內存上分配,而內核的分頁機制即頁目錄表、頁表等,正好管理著

32、16M物理內存,所以內核可以訪問普通用戶進程的頁面。32. 詳細分析一個進程從創建、加載程序、執行、退出的全過程。答:可以參考課本P273頁,其中的核心部分課上都進行了介紹,包括fork()、copy_process()、do_execve()及do_exit等。參考:首先,shell調用fork開始創建進程,產生int 0x80軟中斷,最終映射到sys_fork(),調用find_empty_process(),為str1申請可用的pid和task64空閑位置,接著調用copy_process()為str1申請用來承載進程task_struct和內核棧的一個頁面,shell把自己的task_

33、struct復制給str1進程,然后修改str1的task_struct的部分數據,包括時間片,TSS字段等。接著調用copy_mem()為進程分段(確定段基址和段限長等),然后調用copy_page_tables為str1進程另起一套頁目錄項和頁表項,并指向shell的頁面。還要解決文件繼承的問題,然后將str1進程TSS和LDT掛接在GDT的指定位置,完成這些后,將str1設為就緒態。接下來加載用戶程序:首先要做一些檢查工作,如可執行文件的數據長度和代碼長度等;然后調用free_page_tables解除與shell的頁面共享關系,接著根據程序的長度重新設置LDT,調整str1的task_

34、struct,最后調整EIP和ESP。用戶程序被調度執行,產生缺頁中斷,調用do_no_page為str1申請一個內存頁面,并把它登記在mem_map中,將str1程序從硬盤加載到新分配的頁面中,把它的物理地址映射到進程的線性地址空間內。執行加載到的程序,產生壓棧動作,若棧空間不夠,則產生缺頁中斷繼續申請頁面。最后,用戶進程調用exit退出,釋放程序所占頁面,解除與文件有關的內容,并調用tell_father給父進程發信號,退出后執行調度,shell進程收到用戶進程發送的信號設置為就緒態,待其執行時,釋放掉用戶進程task_struct所占用的頁面,解除與task64的關系,這時用戶進程徹底退

35、出。33. 詳細分析多個進程(無父子關系)共享一個可執行程序的完整過程。答:依次創建3個用戶進程,每個進程都有自己的task。假設進程1先執行,需要壓棧產生缺頁中斷,內核為其申請空閑物理頁面,并映射到進程1的線性地址空間。這時產生時鐘中斷,輪到進程2執行,進程2也執行同樣邏輯的程序。之后,又輪到進程3執行,也是壓棧,并設置text。可見,三個進程雖程序相同,但數據獨立,用TSS和LDT實現對進程的保護。34. 缺頁中斷是如何產生的,頁寫保護中斷是如何產生的,操作系統是如何處理的?答:缺頁中斷:每個頁目錄項和頁表項都有個標志位P,如果和一個頁面建立了映射關系,P位置1,否則置0。MMU在解析線性地址時,若發現某個表項的P位為零,說明沒有對應頁面,就會產生缺頁中斷。操作系統會調用_do_no_page為進程申請空閑頁面,將程序加載到新分配的頁面中,并建立頁目錄表-頁表-頁面

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論