欧美在线专区-欧美在线伊人-欧美在线一区二区三区欧美-欧美在线一区二区三区-pornodoxxx中国妞-pornodoldoo欧美另类

position>home>Softball

基于X86平臺(tái)的簡(jiǎn)單多任務(wù)內(nèi)核的分析與實(shí)現(xiàn)

[導(dǎo)讀]摘要:描述了一個(gè)簡(jiǎn)單多任務(wù)內(nèi)核的基于簡(jiǎn)單設(shè)計(jì)和實(shí)現(xiàn)方法。分析了該簡(jiǎn)單內(nèi)核的多任基本結(jié)構(gòu)和加載運(yùn)行的基本原理,然后描述了其被加載進(jìn)機(jī)器RAM中以及兩個(gè)任務(wù)進(jìn)行切換的分析運(yùn)行方法。

引言

基于X86平臺(tái)的簡(jiǎn)單多任務(wù)內(nèi)核的分析與實(shí)現(xiàn)

當(dāng)提到多任務(wù)時(shí),實(shí)現(xiàn)人們便會(huì)聯(lián)想到MacOS、基于簡(jiǎn)單Linux、多任Windows等操作系統(tǒng)。分析通常情況下,實(shí)現(xiàn)若在操作系統(tǒng)下運(yùn)行多任務(wù),基于簡(jiǎn)單是多任由操作系統(tǒng)負(fù)責(zé)管理和調(diào)度各個(gè)任務(wù)的。本文通過(guò)分析一個(gè)簡(jiǎn)單的分析多任務(wù)內(nèi)核,能夠便于更容易地理解操作系統(tǒng)的實(shí)現(xiàn)任務(wù)管理機(jī)制,以及可以理解計(jì)算機(jī)系統(tǒng)是基于簡(jiǎn)單如何啟動(dòng)的。

1多任務(wù)程序的多任結(jié)構(gòu)

本文實(shí)現(xiàn)的簡(jiǎn)單多任務(wù)內(nèi)核,主要由兩個(gè)文件構(gòu)成:一個(gè)是分析使用as86語(yǔ)言編制的引導(dǎo)啟動(dòng)程序,主要用于在計(jì)算機(jī)系統(tǒng)加電時(shí),將內(nèi)核代碼從啟動(dòng)盤加載到內(nèi)存中;另一個(gè)便是使用GNUas匯編語(yǔ)言編寫的內(nèi)核程序,其中實(shí)現(xiàn)兩個(gè)運(yùn)行在特權(quán)級(jí)2上的任務(wù)可在時(shí)鐘中斷控制下相互切換運(yùn)行,并可通過(guò)系統(tǒng)調(diào)用在屏幕上實(shí)現(xiàn)字符顯示。

2多任務(wù)內(nèi)核工作的啟動(dòng)程序原理

計(jì)算機(jī)系統(tǒng)加電啟動(dòng)后,會(huì)把啟動(dòng)程序從啟動(dòng)盤的第一個(gè)扇區(qū)加載到物理內(nèi)存0x7c00位置開(kāi)始處,之后把執(zhí)行權(quán)交給0x7c00初開(kāi)始運(yùn)行啟動(dòng)程序。

啟動(dòng)程序的主要功能是將軟盤或者鏡像文件中的內(nèi)核程序加載到內(nèi)存的某個(gè)指定位置,實(shí)現(xiàn)這個(gè)目的的方法是利用ROSBIOS中斷int0x13,把軟盤或者鏡像中的內(nèi)核代碼讀入到內(nèi)存,然后再把這段內(nèi)核代碼移動(dòng)到內(nèi)存0開(kāi)始處。最后設(shè)置控制寄存器CR0中的開(kāi)啟保護(hù)運(yùn)行模式標(biāo)志,并跳轉(zhuǎn)到內(nèi)存0處開(kāi)始執(zhí)行內(nèi)核代碼。啟動(dòng)程序在內(nèi)存中移動(dòng)內(nèi)核代碼的示意圖如圖1所示。

圖1啟動(dòng)程序在內(nèi)存中移動(dòng)內(nèi)核代碼的示意圖

將內(nèi)核代碼移動(dòng)到物理內(nèi)存0開(kāi)始處的主要原因是這是GDT表時(shí)可以簡(jiǎn)單一點(diǎn)。但是,不能讓啟動(dòng)程序把內(nèi)核代碼從軟盤或映像文件中直接加載到內(nèi)存0處,因?yàn)榧虞d操作需要ROMBIOS提供中斷過(guò)程,而BIOS使用的中斷向量表正處于內(nèi)存0開(kāi)始處。若直接把內(nèi)核代碼加載到內(nèi)存0處,那么,BIOS中斷過(guò)程將不能正常運(yùn)行。

3內(nèi)核程序

3.1初始化任務(wù)

內(nèi)核程序運(yùn)行在32位保護(hù)模式下,初始化階段主要包括重新設(shè)置GDT表,設(shè)置系統(tǒng)定時(shí)器芯片,重新設(shè)置IDT表并且設(shè)置時(shí)鐘和系統(tǒng)調(diào)用中斷門。內(nèi)核示例中所有代碼和數(shù)據(jù)段都對(duì)應(yīng)到物理內(nèi)存同一個(gè)區(qū)域上,即從物理內(nèi)存0開(kāi)始的區(qū)域。在虛擬地址空間中內(nèi)核程序的內(nèi)核代碼和任務(wù)代碼分配圖如圖2所示。

3.2啟動(dòng)第一個(gè)任務(wù)

特權(quán)級(jí)0的代碼不能直接把控制權(quán)轉(zhuǎn)移到特權(quán)級(jí)2的代碼中執(zhí)行,但可以使用中斷返回操作來(lái)實(shí)現(xiàn),因此當(dāng)初始化GDT、IDT和定時(shí)芯片結(jié)束后,就利用中斷返回指令I(lǐng)RET來(lái)啟動(dòng)第一個(gè)任務(wù)。

具體的實(shí)現(xiàn)方法是在初始堆棧init_stack中人工設(shè)置一個(gè)返回環(huán)境,即把任務(wù)0的TSS段選擇符加載到任務(wù)寄存器TR中,LDT段選擇符加載到LDTR中以后,把任務(wù)0的用戶棧指針和代碼指針以及標(biāo)志寄存器值壓入棧中,然后執(zhí)行中斷返回指令I(lǐng)RET。該指令會(huì)彈出堆棧上的堆棧指針作為任務(wù)0用戶棧指針,恢復(fù)假設(shè)的任務(wù)0的標(biāo)志寄存器內(nèi)容,并且彈出棧中代碼指針?lè)湃隒S:EIP寄存器中,從而開(kāi)始執(zhí)行任務(wù)0的代碼,以完成從特權(quán)級(jí)0到特權(quán)級(jí)3代碼的控制轉(zhuǎn)移。

3.3兩個(gè)任務(wù)的切換

內(nèi)核程序?qū)⒍〞r(shí)器芯片的通道0設(shè)置成每經(jīng)過(guò)10ms就向中斷控制芯片發(fā)送一個(gè)時(shí)鐘中斷請(qǐng)求信號(hào),這樣,每個(gè)10ms將會(huì)切換運(yùn)行的任務(wù)。PC的ROMBIOS開(kāi)機(jī)時(shí)已經(jīng)在定時(shí)器芯片中把時(shí)鐘中斷請(qǐng)求信號(hào)設(shè)置成中斷向量8,因此需要在中斷8的處理過(guò)程中執(zhí)行任務(wù)切換操作。

每個(gè)任務(wù)在執(zhí)行時(shí),會(huì)首先把一個(gè)字符的ASCII碼放入寄存器AL中,然后調(diào)用系統(tǒng)中斷int0x80,而該系統(tǒng)調(diào)用處理過(guò)程會(huì)調(diào)用一個(gè)簡(jiǎn)單的字符寫屏子程序。在顯示過(guò)一個(gè)字符后,任務(wù)代碼會(huì)使用循環(huán)語(yǔ)句延遲一段時(shí)間,然后又跳轉(zhuǎn)到任務(wù)代碼開(kāi)始處繼續(xù)循環(huán)執(zhí)行,直到運(yùn)行了10ms而發(fā)生了定時(shí)中斷,從而代碼會(huì)切換到另一個(gè)任務(wù)去運(yùn)行。

目前,該內(nèi)核示例已經(jīng)在Bochs模擬軟件中運(yùn)行測(cè)試過(guò),測(cè)試結(jié)果如圖3所示。

4結(jié)語(yǔ)

本文分析了一個(gè)基于X86平臺(tái)的簡(jiǎn)單多任務(wù)內(nèi)核的基本結(jié)構(gòu)和加載運(yùn)行原理,描述了其被加載進(jìn)機(jī)器RAM中的基本思路,同時(shí)給出了兩個(gè)任務(wù)進(jìn)行切換的運(yùn)行方法。其主要目的是理解操作系統(tǒng)的啟動(dòng)加載過(guò)程。

附 :本文的啟動(dòng)代碼及內(nèi)核代碼如下:

#############################################

# 名稱 :引導(dǎo)程序 boot.s #

# 說(shuō)明 :把鏡像文件中的 head 內(nèi)核代碼加載到內(nèi)存某個(gè)

指定位置。 #

# #

#############################################

BOOTSEG=0x07c0

SYSSEG=0x1000

SYSLEN=17

entry start

start :

jmpi go,#BOOTSEG

go :

mov ax,cs

mov ds,ax

mov es,ax

mov ss,ax

mov sp,#0x400

mov ax,#0x0600

mov cx,#0x0000

mov dx,#0xFFFF

int 0x10

mov cx,#10

mov dx,#0x0000

mov bx,#0x000c

mov bp,#msg

mov ax,#0x1301

int 0x10

load_system :

mov dx,#0x0000

mov cx,#0x0002

mov ax,#SYSSEG

mov es,ax

xor bx,bx

mov ax,#0x200+SYSLEN

int 0x13

jnc ok_load

mov dx,#0x0000

mov ax,#0x0000

int 0x13

jmp load_system

ok_load :

cli

mov ax,#SYSSEG

mov ds,ax

xor ax,ax

mov es,ax

mov cx,#0x1000

sub si,si

sub di,di

rep

movw

mov ax,cs

mov ds,ax

lidt idt_48

lgdt gdt_48

mov ax,#0x0001

lmsw ax

jmpi 0,8

msg :

.ascii "Loading..."

.byte 13,10

gdt :

.word 0,0,0,0

.word 0x07FF

.word 0x0000

.word 0x9A00

.word 0x00C0

.word 0x07FF

.word 0x0000

.word 0x9200

.word 0x00C0

idt_48 :

.word 0

.word 0,0

gdt_48 :

.word 0x7FF

.word 0x7c00+gdt,0

.org 510

.word 0xAA55

#############################################

# 名稱 :內(nèi)核程序 head.s

# 說(shuō)明 :包含 32 位保護(hù)模式初始化設(shè)置代碼,時(shí)鐘中斷代碼,系統(tǒng)調(diào)用中斷代碼和兩個(gè)任務(wù)的代碼。在初始化完成之后程序移動(dòng)到任務(wù) 0 開(kāi)始執(zhí)行,并在時(shí)鐘中斷控制下進(jìn)行任務(wù) 0 和 1 之間的切換操作。

#############################################

LATCH = 11930 # 定時(shí)器初始計(jì)數(shù)值,即每隔 10ms 發(fā)送一次中斷請(qǐng)求。

SCRN_SEL = 0x18 # 屏幕顯示內(nèi)存段選擇符

TSS0_SEL = 0x20 # 任務(wù) 0 的 TSS 段選擇符

LDT0_SEL = 0x28 # 任務(wù) 0 的 LDT 段選擇符

TSS1_SEL = 0x30 # 任務(wù) 1 的 TSS 段選擇符

LDT1_SEL = 0x38 # 任務(wù) 1 的 LDT 段選擇符

.globl startup_32

.text

startup_32 :

# 首先加載數(shù)據(jù)段寄存器 DS、堆棧段寄存器 SS 和堆棧

指針 ESP。所有段的線性基地址都是 0.

movl $0x10,%eax # 0x10 是 GDT 中數(shù)據(jù)段選擇符。

mov %ax,%ds

lss init_stack,%esp # 把 init_stack 地址處的內(nèi)容既

init_stack 有效地址給 esp,同時(shí)把 0x10 給 ss 段寄存器

# 在新的位置重新設(shè)置 IDT 和 GDT 表。

call setup_idt # 設(shè)置 IDT,先把 256 個(gè)中斷門都填

默認(rèn)處理過(guò)程的描述符

call setup_gdt

movl $0x10,%eax # 在改變了 GDT 之后 重新加載

所有段寄存器 .

mov %ax,%ds

mov %ax,%es

mov %ax,%fs

mov %ax,%gs

lss init_stack,%esp

# 設(shè)置 8253 定時(shí)芯片。把計(jì)數(shù)器通道 0 設(shè)置成每個(gè) 10ms

向中斷控制器發(fā)送一個(gè)中斷請(qǐng)求信號(hào)。

movb $0x36,%al # 控制字:設(shè)置通道0工作在方式3、

計(jì)數(shù)處置采用二進(jìn)制

movl $0x43,%edx #8253 芯片控制字寄存器寫端口

outb %al,%dx

movl $LATCH,%eax # 初始計(jì)數(shù)值設(shè)置為 LATCH

(1193180/100),即頻率 100HZ

movl $0x40,%edx # 通道 0 的端口

outb %al,%dx # 分兩次把初始計(jì)數(shù)值寫入通道 0

movb %ah,%al

outb %al,%dx

# 在 IDT 表第 8 和第 128(

0x80)項(xiàng)處分別設(shè)置定時(shí)中斷

門描述符和系統(tǒng)調(diào)用陷阱門描述符

movl $0x00080000,%eax # 中斷處 理 屬內(nèi)核,即

EAX 高字節(jié)是內(nèi)核代碼段選擇符 0x0008.

movw $timer_interrupt,%ax # 設(shè)置定時(shí)中斷門描述

符。取定時(shí)中斷處理程序地址。

movw $0x8E00,%dx # 中斷門類型是 14(屏蔽中斷),

特權(quán)級(jí) 0 或硬件使用。

movl $0x08,%ecx # 開(kāi)機(jī)時(shí) BIOS 設(shè)置的時(shí)鐘中斷

向量號(hào) 8. 這里直接使用它。

lea idt(,%ecx,8),%esi # 把 IDT 描 述 符 0x08 地

址放入 ESI 中,然后設(shè)置該描述符

movl %eax,(%esi)

movl %edx,4(%esi)

movw $system_interrupt,%ax # 設(shè)置系統(tǒng)調(diào)用陷阱

門描述符。取系統(tǒng)調(diào)用處理程序地址。

movw $0xef00,%dx # 陷阱門類型是 15,特權(quán)級(jí) 3

的程序可執(zhí)行。

movl $0x80,%ecx # 系統(tǒng)調(diào)用向量號(hào)是 0x80.

lea idt(,%ecx,8),%esi # 把 IDT 描 述 符 項(xiàng) 0x80

地址放入 ESI 中,然后設(shè)置該描述符.

movl %eax,(%esi)

movl %edx,4(%esi)

# 現(xiàn)在,為移動(dòng)到任務(wù) 0 中執(zhí)行來(lái)操作堆棧內(nèi)容,在堆

棧中人工建立中斷返回時(shí)的場(chǎng)景

pushfl

andl $0xffffbfff,(%esp)

popfl

movl $TSS0_SEL,%eax # 把任務(wù) 0 的 TSS 段選擇

符加載到任務(wù)寄存器 TR

ltr %ax

movl $LDT0_SEL,%eax # 把任務(wù) 0 的 LDT 段選擇

符加載到局部描述符表寄存器 LDTR

lldt %ax

movl $0,current

sti

pushl $0x17 # 任務(wù) 0 當(dāng)前局部空間數(shù)據(jù)段選擇符入棧

pushl $init_stack # 堆棧指針入棧

pushfl # 標(biāo)志寄存器值入棧

pushl $0x0f # 任務(wù) 0 局部空間代碼段選擇符入棧

pushl $task0 # 把代碼指針入棧

iret # 執(zhí)行中斷返回指令,從而切換到特權(quán)級(jí) 3 的任

務(wù) 0 中執(zhí)行.

# 一下是設(shè)置 GDT 和 IDT 中描述符項(xiàng)的子程序

setup_gdt :

lgdt lgdt_opcode

ret

# 設(shè)置 IDT 表中所有 256 個(gè)中斷們描述符都為統(tǒng)一個(gè)默

認(rèn)值,均使用默認(rèn)的中斷處理過(guò)程 ignore_int。

setup_idt :

lea ignore_int,%edx

movl $0x0008000,%eax

movw %dx,%ax

movw $0x8E00,%dx

lea idt,%edi

mov $256,%ecx

rp_idt :

movl %eax,(%edi)

movl %edx,4(%edi)

addl $8,%edi

dec %ecx

jne rp_idt

lidt lidt_opcode

ret

# 顯示字符子程序

write_char :

push %gs

pushl %ebx

mov $SCRN_SEL,%ebx

mov %bx,%gs

mov src_loc,%bx

shl $1,%ebx

mov %ax,%gs :

(%ebx)

shr $1,%ebx

incl %ebx

cmpl $2000,%ebx

jb 1f

movl $0,%ebx

1 :

movl %ebx,src_loc

popl %ebx

pop %gs

ret

# 以下是 3 個(gè)中斷處理程序 :默認(rèn)中斷、定時(shí)中斷和系統(tǒng)

調(diào)用中斷

#ignore_int 是默認(rèn)的中斷處理程序,若系統(tǒng)產(chǎn)生了其他

中斷,會(huì)在屏幕上顯示一個(gè)字符“C”

.align 2

ignore_int :

push %ds

pushl %eax

movl $0x10,

%eax

mov %ax,

%ds

mov $0x0c98,

%ax /* print 'C' */

call write_char

popl %eax

pop %ds

iret

# 這是定時(shí)中斷處理程序,主要執(zhí)行任務(wù)切換操作 .

.align 2

timer_interrupt :

push %ds

pushl %eax

movl $0x10,

%eax

mov %ax,

%ds

movb $0x20,

%al

outb %al,

$0x20

movl $1,%eax

cmpl %eax,current

je 1f

movl %eax,current

ljmp $TSS1_SEL,$0

jmp 2f

1 :

movl $0,current

ljmp $TSS0_SEL,$0

2 :

popl %eax

pop %ds

iret

# 系統(tǒng)調(diào)用中斷 int 0x80 處理程序 . 顯示字符功能

.align 2

system_interrupt :

push %ds

pushl %edx

pushl %ecx

pushl %ebx

pushl %eax

movl $0x10,

%edx

mov %dx,

%ds

call write_char

popl %eax

popl %ebx

popl %ecx

popl %edx

pop %ds

iret

/

Popular articles

主站蜘蛛池模板: 国产一级毛片大陆| 日本一本高清| 99久久精品免费观看国产| 日本波多野结衣电影| 久久免费视频网站| 天堂8在线天堂资源bt| 天天干夜夜操| а√在线地址最新版| 4480yy私人影院论| 亚洲不卡| 菠萝蜜视频在线观看入口| 日本一道本| 狂野欧美激情性xxxx| 玖玖色资源站| 色噜噜在线观看| 182tv精品视频在线播放| 又硬又粗又长又爽免费看| 欧美一级黄色片视频| 久久精品一区二区三区不卡| 国产男女无遮挡猛进猛出| 一本久久a久久精品vr综合| 妖精的尾巴ova| 爱情岛亚洲论坛在线观看| 高清仑乱| 美女张开腿让男人桶爽动漫视频| 亚洲香蕉电影| 美女黄色录像| 波多野结衣33分钟办公室jian情| 全肉高h动漫在线看| 久久一日本道色综合久久m| 日本视频免费高清一本18| 久久依人| 高清免费毛片| 国产欧美日韩中文久久| 两个人看的www视频日本| 欧美日韩视频| 99精品欧美| 日韩aaa电影| 男人的j插入女人的p| 午夜三级三级三点在线| 水蜜桃视频在线免费观看|