當前位置:首頁 > 物聯(lián)網(wǎng) > 《物聯(lián)網(wǎng)技術(shù)》雜志
[導讀]摘要:描述了一個簡單多任務內(nèi)核的設計和實現(xiàn)方法。分析了該簡單內(nèi)核的基本結(jié)構(gòu)和加載運行的基本原理,然后描述了其被加載進機器RAM中以及兩個任務進行切換的運行方法。

引言

當提到多任務時,人們便會聯(lián)想到MacOS、Linux、Windows等操作系統(tǒng)。通常情況下,若在操作系統(tǒng)下運行多任務,是由操作系統(tǒng)負責管理和調(diào)度各個任務的。本文通過分析一個簡單的多任務內(nèi)核,能夠便于更容易地理解操作系統(tǒng)的任務管理機制,以及可以理解計算機系統(tǒng)是如何啟動的。

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

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

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

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

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

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

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

3內(nèi)核程序

3.1初始化任務

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

3.2啟動第一個任務

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

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

3.3兩個任務的切換

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

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

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

4結(jié)語

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

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

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

# 名稱 :引導程序 boot.s #

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

指定位置。 #

# #

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

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

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

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

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

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

TSS0_SEL = 0x20 # 任務 0 的 TSS 段選擇符

LDT0_SEL = 0x28 # 任務 0 的 LDT 段選擇符

TSS1_SEL = 0x30 # 任務 1 的 TSS 段選擇符

LDT1_SEL = 0x38 # 任務 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,同時把 0x10 給 ss 段寄存器

# 在新的位置重新設置 IDT 和 GDT 表。

call setup_idt # 設置 IDT,先把 256 個中斷門都填

默認處理過程的描述符

call setup_gdt

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

所有段寄存器 .

mov %ax,%ds

mov %ax,%es

mov %ax,%fs

mov %ax,%gs

lss init_stack,%esp

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

向中斷控制器發(fā)送一個中斷請求信號。

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

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

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

outb %al,%dx

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

(1193180/100),即頻率 100HZ

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

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

movb %ah,%al

outb %al,%dx

# 在 IDT 表第 8 和第 128(

0x80)項處分別設置定時中斷

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

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

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

movw $timer_interrupt,%ax # 設置定時中斷門描述

符。取定時中斷處理程序地址。

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

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

movl $0x08,%ecx # 開機時 BIOS 設置的時鐘中斷

向量號 8. 這里直接使用它。

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

址放入 ESI 中,然后設置該描述符

movl %eax,(%esi)

movl %edx,4(%esi)

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

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

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

的程序可執(zhí)行。

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

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

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

movl %eax,(%esi)

movl %edx,4(%esi)

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

棧中人工建立中斷返回時的場景

pushfl

andl $0xffffbfff,(%esp)

popfl

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

符加載到任務寄存器 TR

ltr %ax

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

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

lldt %ax

movl $0,current

sti

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

pushl $init_stack # 堆棧指針入棧

pushfl # 標志寄存器值入棧

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

pushl $task0 # 把代碼指針入棧

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

務 0 中執(zhí)行.

# 一下是設置 GDT 和 IDT 中描述符項的子程序

setup_gdt :

lgdt lgdt_opcode

ret

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

認值,均使用默認的中斷處理過程 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 個中斷處理程序 :默認中斷、定時中斷和系統(tǒng)

調(diào)用中斷

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

中斷,會在屏幕上顯示一個字符“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

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

.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

/*************************************************/

current :

.long 0

src_loc :

.long 0

.align 2

lidt_opcode :

.word 256*8-1

.long idt

lgdt_opcode :

.word (end_gdt-gdt)-1

.long gdt

.align 2

idt :

.fill 256,8,0

gdt :

.quad 0x0000000000000000 #GDT 表, 第

一個描述符不用

.quad 0x00c09a00000007ff # 第二個是內(nèi)核代碼段描

述符,其選擇符是 0x08.

.quad 0x00c09200000007ff # 第三個是內(nèi)核數(shù)據(jù)段描

述符,其選擇符是 0x10.

.quad 0x00c0920b80000002 # 第 4 個是顯示內(nèi)存段

描述符,其選擇符是 0x18.

.word 0x68,tss0,0xe900,0x0 # 第 5 個是 TSS0 段

的描述符,其選擇符是 0x20.

.word 0x40,ldt0,0xe200,0x0 # 第 6 個 是 LDT0

段的描述符,其選擇符是 0x28

.word 0x68,tss1,0xe900,0x0 # 第 7 個是 TSS1 段

的描述符,其選擇符是 0x30

.word 0x40,ldt1,0xe200,0x0 # 第 8 個是 LDT1 段

的描述符,其選擇符是 0x38

end_gdt :

.fill 128,4,0 # 初始內(nèi)核堆棧空間

init_stack :

# 剛進入保護

模式時用于加載 SS :ESP 堆棧指針值

.long init_stack

.word 0x10

# 下面是任務 0 的 LDT 表段中的局部段描述符

.align 2

ldt0 :

.quad 0x0000000000000000

.quad 0x00c0fa00000003ff # 第 2 個是局部代碼段

描述符,對應選擇符是 0x0f.

.quad 0x00c0f200000003ff # 第 3 個是局部數(shù)度段

描述符,

對應選擇符是 0x17.

# 下面是任務 0 的 TSS 段的內(nèi)容

tss0 :

.long 0

.long krn_stk0,0x10 /*esp0,ss0*/

.long 0,0,0,0,0

/*esp1,ss1,esp2,ss2,

cr3*/

.long 0,0,0,0,0

/ *e i p,e f l a g s,e a x,

ecx,edx*/

.long 0,0,0,0,0

/*ebx,esp,ebp,esi,

edi*/

.long 0,0,0,0,0,0

/*es,cs,ss,ds,fs,

gs*/

.long LDT0_SEL,0x8000000

/ * l d t,t r a c e

bitmap*/

.fill 128,4,0

# 這是任務 0 的內(nèi)核棧

空間

krn_stk0 :

# 下面是任務 1 的 LDT 表段內(nèi)容和 TSS 段內(nèi)容

.align 2

ldt1 :

.quad 0x0000000000000000# 第 1 個 描 述

符,不用

.quad 0x00c0fa00000003ff # 選擇符是 0x0f,基地

址 = 0x00000

.quad 0x00c0f200000003ff # 選擇符是 0x17,基地

值 = 0x00000

tss1 :

.long 0

.long krn_stk1,0x10

.long 0,0,0,0,0

.long task1,0x200

.long 0,0,0,0

.long usr_stk1,0,0,0

.long 0x17,0x0f,0x17,0x17,0x17,0x17

.long LDT1_SEL,0x8000000

.fill 128,4,0

# 這是任務 1 的內(nèi)核棧

空間,其用戶棧直接使用初始??臻g

krn_stk1 :

# 下面是任務 0 和任務 1 的程序,它們分別循環(huán)顯示字

符“A”和“B”

task0 :

movw $0x0c61,

%ax

# 把需要顯示

的字符 A 放入 AL 寄存器中

int $0x80

movl $0xfff,%ecx # 執(zhí)行循環(huán),起延時作用

1 :

loop 1b

jmp task0

task1 :

movw $0x0d62,

%ax

int $0x80

movl $0xfff,%ecx

1 :

loop 1b

jmp task1

.fill 128,4,0

# 這是任務 1 的用戶棧

空間

usr_stk1 :

.long 0

20211117_6193e118b949a__基于X86平臺的簡單多任務內(nèi)核的分析與實現(xiàn)

本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫毥谦F公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術(shù)解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關(guān)鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務中斷的風險,如企業(yè)系統(tǒng)復雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機 衛(wèi)星通信

要點: 有效應對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅持高質(zhì)量發(fā)展策略,塑強核心競爭優(yōu)勢...

關(guān)鍵字: 通信 BSP 電信運營商 數(shù)字經(jīng)濟

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術(shù)學會聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(shù)(集團)股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉