新聞中心
近年來,隨著信息技術(shù)的不斷發(fā)展,操作系統(tǒng)作為計(jì)算機(jī)科學(xué)的一個(gè)重要分支之一,一直是人們研究的熱點(diǎn)之一。而在操作系統(tǒng)的內(nèi)存管理中,為實(shí)現(xiàn)多任務(wù)的切換,通常需要用到段描述符表(Global Descriptor Table,簡稱GDT)。在Linux系統(tǒng)中,GDT被廣泛應(yīng)用于多任務(wù)切換中。

本文將詳細(xì)介紹Linux系統(tǒng)下GDT實(shí)現(xiàn)的任務(wù)切換原理,包括GDT的定義及其與多任務(wù)切換的關(guān)系、GDT的寄存器存儲(chǔ)方式等方面。希望對(duì)Linux系統(tǒng)多任務(wù)切換的研究及開發(fā)起到指導(dǎo)和借鑒的作用。
一、GDT概述
GDT是管理段地址空間的數(shù)據(jù)結(jié)構(gòu),包含多個(gè)段描述符。段描述符是用來描述一個(gè)內(nèi)存段的一個(gè)數(shù)據(jù)結(jié)構(gòu),它包含了該段的基址、限長、訪問權(quán)限等信息。在不同的代碼段中,GDT的內(nèi)容是不同的,因?yàn)槊總€(gè)段描述符只能描述同一種類型的段,如代碼段或數(shù)據(jù)段等。在實(shí)現(xiàn)多任務(wù)的切換中,GDT被廣泛應(yīng)用。
二、GDT的定義
在Linux系統(tǒng)中,GDT被定義在kernel/head.S文件中。定義的方式如下:
.align 4
gdt_descr: //GDT的描述符結(jié)構(gòu)
.word gdt_end – gdt – 1 /* GDT的大小 */
.long gdt /* GDT的地址 */
gdt:
.quad 0x0 //0號(hào)描述符
.quad 0x00cf9a000000ffff //1號(hào)描述符(32位代碼段)
.quad 0x00cf92023000ffff //2號(hào)描述符(32位數(shù)據(jù)段)
.align 16
gdt_end:
其中,GDT的描述符結(jié)構(gòu)包含GDT的大小和GDT的地址。GDT表的每一項(xiàng)稱為段描述符,每個(gè)段描述符都有一個(gè)編號(hào),0~8191(共8192個(gè)段描述符)。每個(gè)段描述符都至少包等含兩個(gè)字段:段基址和段限長,用于限制用戶代碼和數(shù)據(jù)訪問的范圍。其中,段基地址是該段的起始地址,段限長則指定了該段的大?。▎挝粸樽止?jié))。在這些字段之外,段描述符中還包含著其他的一些元數(shù)據(jù)信息,如:段屬性、段訪問權(quán)限等。每個(gè)描述符的大小為8字節(jié)。
三、任務(wù)切換
在實(shí)現(xiàn)多任務(wù)的切換中,GDT起著至關(guān)重要的作用。當(dāng)CPU切換到另一個(gè)任務(wù)時(shí),需要先加載新任務(wù)的GDT表,然后執(zhí)行IRET指令。IRET指令會(huì)將當(dāng)前CPU的狀態(tài)還原,包括程序計(jì)數(shù)器、棧指針、FPU、MMX等寄存器。CPU將進(jìn)入到新的GDT表,新的程序計(jì)數(shù)器將根據(jù)新的GDT表開始執(zhí)行代碼。
在Linux系統(tǒng)中,任務(wù)切換是由time.c文件中的do_timer函數(shù)實(shí)現(xiàn)的。在此函數(shù)中,通過查找任務(wù)列表中更優(yōu)先的未完成任務(wù),并將其插入到運(yùn)行隊(duì)列的隊(duì)尾。然后,將當(dāng)前任務(wù)從處理機(jī)中移除,并將其保存到任務(wù)狀態(tài)段中。
四、GDT與進(jìn)程管理
在Linux系統(tǒng)中,進(jìn)程管理是操作系統(tǒng)的核心功能之一。在進(jìn)程管理中,進(jìn)程是操作系統(tǒng)中最小的調(diào)度單位,也是操作系統(tǒng)的任務(wù)切換最小單位。在Linux系統(tǒng)中,每個(gè)進(jìn)程都有一個(gè)獨(dú)立的地址空間,包括代碼段、數(shù)據(jù)段和堆棧段等。在多進(jìn)程管理中,不同進(jìn)程的地址空間被分隔開來,通過機(jī)制實(shí)現(xiàn)地址空間的隔離,從而提高操作系統(tǒng)的安全性和穩(wěn)定性。
需要說明的是,在Linux系統(tǒng)中,進(jìn)程的所有信息都保存在任務(wù)狀態(tài)段中,并且由操作系統(tǒng)維護(hù)。當(dāng)一個(gè)進(jìn)程被調(diào)度執(zhí)行時(shí),操作系統(tǒng)會(huì)將進(jìn)程的信息復(fù)制到處理機(jī)的寄存器中,以便處理器在執(zhí)行進(jìn)程時(shí)能夠訪問進(jìn)程的相關(guān)信息。
GDT是Linux系統(tǒng)中實(shí)現(xiàn)多任務(wù)切換的關(guān)鍵之一。通過對(duì)GDT的詳細(xì)介紹,我們可以更好地理解Linux系統(tǒng)中的任務(wù)切換原理。對(duì)于早期的操作系統(tǒng)設(shè)計(jì)者而言,多任務(wù)切換的實(shí)現(xiàn)利器是好的,而目前我們使用的Linux操作系統(tǒng)也極大地受益于GDT的應(yīng)用。
成都網(wǎng)站建設(shè)公司-創(chuàng)新互聯(lián),建站經(jīng)驗(yàn)豐富以策略為先導(dǎo)10多年以來專注數(shù)字化網(wǎng)站建設(shè),提供企業(yè)網(wǎng)站建設(shè),高端網(wǎng)站設(shè)計(jì),響應(yīng)式網(wǎng)站制作,設(shè)計(jì)師量身打造品牌風(fēng)格,熱線:028-86922220Linux系統(tǒng)開機(jī)時(shí)啟動(dòng)內(nèi)核步驟是什么?
開機(jī)–加電自檢–讀取CMOS設(shè)置–從硬盤引導(dǎo)記錄查找系統(tǒng)所在位置–讀取GRUB配置文件(/boot/grub/grub.conf),加載內(nèi)核,驅(qū)動(dòng)硬件–開啟init進(jìn)程,讀取相應(yīng)旦卜肆配置文件(/etc/inittab),打開默認(rèn)運(yùn)行級(jí)別模轎,加載相應(yīng)服務(wù),開機(jī)啟動(dòng)弊薯項(xiàng)–完成啟動(dòng)過程
實(shí)模式,并開始執(zhí)行位于地址0xFFFF0處
的代碼,也就是ROM-BIOS起始位置的代碼。BIOS先進(jìn)行一系列的系統(tǒng)自檢,然后初始化位
于地址0的中斷向量表。最后BIOS將啟動(dòng)盤的鋒扒之一個(gè)扇區(qū)裝入到0x7C00,并開始執(zhí)行此處
的代碼。這就是對(duì)內(nèi)核初始化過程的一個(gè)最簡單的描述。
最初,linux核心的最開始部分是用8086匯編語言編寫的。當(dāng)開始運(yùn)行時(shí),核心將自
己裝入到絕對(duì)地址0x90000,再將其后的2k字節(jié)裝入到地址0x90200處,最后將核心的其余
部分裝入到0x10000。
當(dāng)系統(tǒng)裝入時(shí),會(huì)顯示Loading…信息。裝入完成后,控制轉(zhuǎn)向另一個(gè)實(shí)模式下的匯
編語言代碼boot/Setup.S。Setup部分首先設(shè)置一些系統(tǒng)的硬件設(shè)備,然后將核心從
0x10000處移至0x1000處。這時(shí)系統(tǒng)轉(zhuǎn)入保護(hù)模式,開始執(zhí)行位于0x1000處的代碼。
接下來是內(nèi)核的解壓縮銀銷昌。0x1000處的代碼來自于文件Boot/head.S,它用來初始化寄
存器和調(diào)用decompress_kernel( )程序。decompress_kernel( )程序由Boot/inflate.c,
Boot/unzip.c和Boot../misc.c組成。解壓縮后的數(shù)據(jù)被裝入到了0x100000處,這也是
linux不能在內(nèi)存小于2M的環(huán)境下運(yùn)行的主要原因。
解壓后的代碼在0x處開始執(zhí)行,緊接著所有的32位的設(shè)斗逗置都將完成: IDT、
GDT和LDT將被裝入,處理器初始化完畢,設(shè)置好內(nèi)存頁面,最終調(diào)用start_kernel過程。
這大概是整個(gè)內(nèi)核中最為復(fù)雜的部分。
linux kernel 最早的C代碼從匯編標(biāo)記startup_32開始執(zhí)行
startup_32:
start_kernel
lock_kernel
trap_init
init_IRQ
sched_init
softirq_init
time_init
console_init
#ifdef CONFIG_MODULES
init_modules
#endif
kmem_cache_init
sti
calibrate_delay
mem_init
kmem_cache_sizes_init
pgtable_cache_init
fork_init
proc_caches_init
vfs_caches_init
buffer_init
page_cache_init
signals_init
#ifdef CONFIG_PROC_FS
proc_root_init
#endif
#if defined(CONFIG_SYSVIPC)
ipc_init
#endif
check_bugs
p_init
rest_init
kernel_thread
unlock_kernel
cpu_idle
?startup_32
?start_kernel
?lock_kernel
?trap_init
?init_IRQ
?sched_init
?softirq_init
?time_init
?console_init
?init_modules
?kmem_cache_init
?sti
?calibrate_delay
?mem_init
?kmem_cache_sizes_init
?pgtable_cache_init
?fork_init
?proc_caches_init
?vfs_caches_init
?buffer_init
?page_cache_init
?signals_init
?proc_root_init
?ipc_init
?check_bugs
?p_init
?rest_init
?kernel_thread
?unlock_kernel
?cpu_idle
start_kernel( )程序用于初始化系統(tǒng)內(nèi)核的各個(gè)部分,包括:
*設(shè)置內(nèi)存邊界,調(diào)用paging_init( )初始化內(nèi)存頁面。
*初始化陷阱,中斷通道和調(diào)度。
*對(duì)命令行進(jìn)行語法分析。
*初始化設(shè)備驅(qū)動(dòng)程序和磁盤緩沖區(qū)。
*校對(duì)延遲循環(huán)。
最后的function’rest_init’ 作了以下工作:
?開辟內(nèi)核線程’init’
?調(diào)用unlock_kernel
?建立內(nèi)核運(yùn)行的cpu_idle環(huán), 如果沒有調(diào)度,就一直死循環(huán)
實(shí)際上start_kernel永遠(yuǎn)不能終止.它會(huì)無窮地循環(huán)執(zhí)行cpu_idle.
最后,系統(tǒng)核心轉(zhuǎn)向move_to_user_mode( ),以便創(chuàng)建初始化進(jìn)程(init)。此后,進(jìn)程0開始進(jìn)入無限循環(huán)。
初始化進(jìn)程開始執(zhí)行/etc/init、/bin/init 或/in /init中的一個(gè)之后,系統(tǒng)內(nèi)核就不再對(duì)程序進(jìn)行直接控制了。之后系統(tǒng)內(nèi)核的作用主要是給進(jìn)程提供系統(tǒng)調(diào)用,以及提供異步中斷事件的處理。多任務(wù)機(jī)制已經(jīng)建立起來,并開始處理多個(gè)用戶的登錄和fork( )創(chuàng)建的進(jìn)程。
init是之一個(gè)進(jìn)程,或者說內(nèi)核線程
init
lock_kernel
do_basic_setup
mtrr_init
sysctl_init
pci_init
sock_init
start_context_thread
do_init_calls
(*call())-> kswapd_init
prepare_namespace
free_initmem
unlock_kernel
execve
啟動(dòng)步驟
系統(tǒng)引導(dǎo):
涉及的文件
./arch/$ARCH/boot/bootsect.s
./arch/$ARCH/boot/setup.s
bootsect.S
這個(gè)程序是linux kernel的之一個(gè)程序,包括了linux自己的bootstrap程序,
但是在說明這個(gè)程序前,必須先說明一般IBM PC開機(jī)時(shí)的動(dòng)作(此處的開機(jī)是指
“打開PC的電源”):
一般PC在電源一開時(shí),是由內(nèi)存中地址FFFF:0000開始執(zhí)行(這個(gè)地址一定
在ROM BIOS中,ROM BIOS一般是在FEOOOh到FFFFFh中),而此處的內(nèi)容則是一個(gè)
jump指令,jump到另一個(gè)位於ROM BIOS中的位置,開始執(zhí)行一系列的動(dòng)作,包
括了檢查RAM,keyboard,顯示器,軟硬磁盤等等,這些動(dòng)作是由系統(tǒng)測(cè)試代碼
(system test code)來執(zhí)行的,隨著制作BIOS廠商的不同而會(huì)有些許差異,但都
是大同小異,讀者可自行觀察自家機(jī)器開機(jī)時(shí),螢?zāi)簧纤@示的檢查訊息。
緊接著系統(tǒng)測(cè)試碼之后,控制權(quán)會(huì)轉(zhuǎn)移給ROM中的啟動(dòng)程序
(ROM bootstrap routine),這個(gè)程序會(huì)將磁盤上的第零軌第零扇區(qū)讀入
內(nèi)存中(這就是一般所謂的boot sector,如果你曾接觸過電腦病
毒,就大概聽過它的大名),至於被讀到內(nèi)存的哪里呢? –絕對(duì)
位置07C0:0000(即07C00h處),這是IBM系列PC的特性。而位在linux開機(jī)
磁盤的boot sector上的正是linux的bootsect程序,也就是說,bootsect是
之一個(gè)被讀入內(nèi)存中并執(zhí)行的程序?,F(xiàn)在,我們可以開始來
看看到底bootsect做了什么。
之一步
首先,bootsect將它”自己”從被ROM BIOS載入的絕對(duì)地址0x7C00處搬到
0x90000處,然后利用一個(gè)jmpi(jump indirectly)的指令,跳到新位置的
jmpi的下一行去執(zhí)行,
第二步
接著,將其他segment registers包括DS,ES,SS都指向0x9000這個(gè)位置,
與CS看齊。另外將SP及DX指向一任意位移地址( offset ),這個(gè)地址等一下
會(huì)用來存放磁盤參數(shù)表(disk para- meter table )
第三步
接著利用BIOS中斷服務(wù)int 13h的第0號(hào)功能,重置磁盤控制器,使得剛才
的設(shè)定發(fā)揮功能。
第四步
完成重置磁盤控制器之后,bootsect就從磁盤上讀入緊鄰著bootsect的setup
程序,也就是setup.S,此讀入動(dòng)作是利用BIOS中斷服務(wù)int 13h的第2號(hào)功能。
setup的image將會(huì)讀入至程序所指定的內(nèi)存絕對(duì)地址0x90200處,也就是在內(nèi)存
中緊鄰著bootsect 所在的位置。待setup的image讀入內(nèi)存后,利用BIOS中斷服
務(wù)int 13h的第8號(hào)功能讀取目前磁盤的參數(shù)。
第五步
再來,就要讀入真正linux的kernel了,也就是你可以在linux的根目錄下看
到的”vmlinuz” 。在讀入前,將會(huì)先呼叫BIOS中斷服務(wù)int 10h 的第3號(hào)功能,
讀取游標(biāo)位置,之后再呼叫BIOS 中斷服務(wù)int 10h的第13h號(hào)功能,在螢?zāi)簧陷?/p>
出字串”Loading”,這個(gè)字串在boot linux時(shí)都會(huì)首先被看到,相信大家應(yīng)該覺
得很眼熟吧。
第六步
接下來做的事是檢查root device,之后就仿照一開始的方法,利用indirect
jump 跳至剛剛已讀入的setup部份
第七步
setup.S完成在實(shí)模式下版本檢查,并將硬盤,鼠標(biāo),內(nèi)存參數(shù)寫入到 INITSEG
中,并負(fù)責(zé)進(jìn)入保護(hù)模式。
第八步
關(guān)于linux gdt 任務(wù)切換的介紹到此就結(jié)束了,不知道你從中找到你需要的信息了嗎 ?如果你還想了解更多這方面的信息,記得收藏關(guān)注本站。
創(chuàng)新互聯(lián)【028-86922220】值得信賴的成都網(wǎng)站建設(shè)公司。多年持續(xù)為眾多企業(yè)提供成都網(wǎng)站建設(shè),成都品牌建站設(shè)計(jì),成都高端網(wǎng)站制作開發(fā),SEO優(yōu)化排名推廣服務(wù),全網(wǎng)營銷讓企業(yè)網(wǎng)站產(chǎn)生價(jià)值。
本文名稱:Linux下GDT實(shí)現(xiàn)的任務(wù)切換(linuxgdt任務(wù)切換)
轉(zhuǎn)載注明:http://fisionsoft.com.cn/article/cdipsio.html


咨詢
建站咨詢
