操作系统源码及GeekOS学习
操作系统是非常神奇的!
在学习的过程中,通过Source Insight查看了关于OS的一些知识,还有关于GeekOS的知识,老师在市面上关于操作系统知识与理论相结合的一些课程中做了对比后,最终选定《操作系统概念》和《操作系统及实验实习指导》(老师个人编辑)后进行教学。而个人在学习过程中,也发现了一些玄奥。
关于软件及相关文件的压缩包在个人的下载中,以下附上部分学习的知识,仅供有兴趣的大佬批阅。
1.请说明GeekOS内核文件KERNEL_OBJS包括哪两类源程序?
两类源程序:
.c和.asm
2.Common目录下的文件用于什么场合?
内核程序,用户程序
3.内核基地址、内核入口点函数分别是什么?
0x10000;Main函数
4、编译Geekos需要哪些工具软件?
gcc、ld、ar、ranlib、nm、objcopy、nasm、builtFat、perl、pad、zerofile、numsecs、
5、GeekOS中fd.img文件的组成,fd.img 由哪几个文件组成,在Makefile 文件中通过哪些语句体现出现的?
fd.img由fd_boot.bin、setup.bin和kernel.bin组成;
通过以下体现:
6、浏览 fd_boot.asm文件,了解GeekOS的启动过程BeginText ->after_move ->load_setup ->load_kernel。从下列代码可知,引导扇区的大小及最后两个字节的内容分分别是什么?
Pad_From_Symbol BIOS_SIGNATURE_OFFSET, BeginText
Signature dw 0xAA55
引导扇区大小为512Byte;最后两个字节的内容为AA55
7、浏览 lowlevel.asm文件,此文件向外输出了哪些符号,输入了哪些符号?
输出了gs、fs、es、ds、ebp、edi、esi、edx、ecx、ebx、eax;输入了eax、ebx、ecx、edx、esi、edi、ebp、ds、es、fs、gs
8、GeekOS的启动过程
机器加电后,BIOS会自动检测启动设备, 我们把Bochs被配置为从软盘启动,所以BIOS把引导程序(位于软盘的引导扇区)复制到从内存地址0x7c00开始的一块内存区,之后跳转到这个地址开始执行引导程序。
将自己复制到内存的0x90000处,将setup.bin复制到0x90200处,将kernel.bin复制到0x10000处。然后跳转到setup执行。
Setup程序完成装载临时GDT(Global Descriptor Table,内存管理)、IDT(Interrup D T)描述符,打开A20地址线,初始化中断控制器,完成由实模式转换到保护模式,最后跳转到内核main.c中的Main函数(kenerl),这是内核入口点。
初始化内核,开始执行内核级线程或用户线线程。
9、Begin_Int_Atomic();和End_Int_Atomic();两个函数功能及其实现。
分别是开中断与关中断
10、GeekOS中进程管理的代码位于Kthread.h、Kthread.c文件中。请说明在Kthread.h中定义了哪些队列类型、结构体、函数、全局变量、常量?
队列类型:Thread_Queue和All_Thread_List。
结构体:Kernel_Thread
函数:Start_Kernel_Thread;Start_User_Thread;Make_Runnable;Make_Runnable_Atomic;Get_Current;Get_Next_Runnable;Schedule;Wait;Wake_Up;Exit;Dump_All_Thread_List;Init_Thread;
全局变量:int g_needReschedule;volatile int g_preemptionDisabled;
struct Kernel_Thread* g_currentThread;SF_SchedulePolicy g_SchedPolicy;
常量:
#define MIN_DESTRUCTOR_ITERATIONS 4
#define MAX_QUEUE_LEVEL 4;
#define PRIORITY_IDLE 0;
#define PRIORITY_USER_BAKGROUND 1;
#define PRIORITY_USER 2;
#define PRIORITY_LOW 3;
#define PRIORITY_NORMAL 5;
#define PRIORITY_HIGH 10;
#define MAX_TLOCAL_KEYS 128;
#define GEEKOS_KTHREAD_H;
11、 Kthread.h中如下函数
Remove_Thread(struct Thread_Queue *queue, struct Kernel_Thread *kthread) {
Remove_From_Thread_Queue(queue, kthread);
}
问题:
(1)函数Remove_Thread的功能是什么?
使队列的一个结点出队
(2)函数Remove_From_Thread_Queue通过什么方式定义的?
宏定义
12 、 GeekOS 中进程优先级有几类?
五类
#define PRIORITY_IDLE 0
#define PRIORITY_USER 1
#define PRIORITY_LOW 2
#define PRIORITY_NORMAL 5
#define PRIORITY_HIGH 10
13、阅读函数Init_Scheduler代码请回答如下问题:
(1)创建一个内核进程分配了多少内存空间?
KERN_THREAD_OBJ分配了1MB,KERN_STACK分配了1MB+4KB
总共是2M+4K
(2)GeekOS最先创建的三个进程分别是什么?
Init_Scheduler;Start_Kernel_Thread;Start_User_Thread;
(3)此函数调用了哪些函数?
Init_Thread(mainThread, (void *) KERN_STACK, PRIORITY_NORMAL, true);
Add_To_Back_Of_All_Thread_List(&s_allThreadList, mainThread);
Start_Kernel_Thread(Idle, 0, PRIORITY_IDLE, true);
Start_Kernel_Thread(Reaper, 0, PRIORITY_NORMAL, true);
mainThread,Idle,Reaper三个进程
(4)新创建的进程mainThread放进了哪些队列中?
Add_To_Back_Of_All_Thread_List(&s_allThreadList, mainThread);放进了s_allThreadList队列中
14、阅读函数Init_Thread代码请回答如下问题:
(1)函数参数detached的含义?
detached为真时,表示此进程是独立创建的,否则此进程是当前运行的进程请求创建的子进程
(2)进程ID号如何生成的?
static int nextFreePid = 1;
kthread->pid = nextFreePid++;
15、阅读函数Start_Kernel_Thread代码请回答如下问题:
(1)此函数调用了哪些函数?
Create_Thread(priority, detached);
Setup_Kernel_Thread(kthread, startFunc, arg);
Make_Runnable_Atomic(kthread);
(2)此函数的参数Thread_Start_Func表示要创建进程的函数名,请说明对这类进程函数的函数参数的类型、个数有什么要求?
注:请参考Init_Scheduler中对Start_Kernel_Thread的调用。
Start_Kernel_Thread(Idle, 0, PRIORITY_IDLE, true);
Start_Kernel_Thread(Reaper, 0, PRIORITY_NORMAL, true);
struct Kernel_Thread* Start_Kernel_Thread(
Thread_Start_Func startFunc,
ulong_t arg,
int priority,
bool detached
)
16、阅读函数Create_Thread代码请回答如下问题:
(1)此函数调用了哪些函数?
Alloc_Page();
Free_Page(kthread);
Init_Thread(kthread, stackPage, priority, detached);
(2)如果分配内存不成功,此函数返回值是什么?
return 0
17、阅读函数Make_Runnable_Atomic代码请回答如下问题:
(1)此函数调用了哪些函数?
Disable_Interrupts();
Make_Runnable(kthread);
Enable_Interrupts();
(3)此函数功能?
关中断,把进程添加到就绪队列中,开中断
18、Idle进程的作用是什么?请阅读它的源代码,说明它的执行过程是什么?
作用:保证就绪队列中不空。
执行过程:Idle始终放在就绪队列队尾,当系统中没有可运行的进程时,就运行Idle,一旦就绪队列中有其他进程,Idle就重新进入就绪队列,系统重新执行调度。
19、 阅读函数Yield代码请回答如下问题:
(1)此函数调用了哪些函数?
Disable_Interrupts();
Make_Runnable(g_currentThread);
Schedule();
Enable_Interrupts();
(2)Disable_Interrupts表示关中断,那么与它对应的开中断用什么表示的?
用Enable_Interrupts()表示。
20、阅读函数Schedule代码请回答如下问题:
(1)此函数调用了哪些函数?
struct Kernel_Thread* runnable;
KASSERT(!Interrupts_Enabled());
KASSERT(!g_preemptionDisabled);
runnable = Get_Next_Runnable();
Switch_To_Thread(runnable);
(2)Switch_To_Thread的作用、此函数定义在哪个文件中?
作用:完成硬件上下文切换
定义在C:\Program Files\Source Insight 4.0\pSchedule\src\geekos
21、添加一个系统调用,如Get_ppp,实现获取当前进程优先级。
Src\user\Shell.c中:
else if (strcmp(command, “ppp”) == 0) {
Print("%d\n", Get_ppp());
continue;
}
Include\libs\process.h中:
int Get_ppp(void);
src\libc\ process.c中:
DEF_SYSCALL(Get_ppp,SYS_GETppp,int,(void),SYSCALL_REGS_0)
include\Geekos\Syscall.h中:
enum {
SYS_NULL, /* Null (no-op) system call /
SYS_EXIT, / Exit system call /
SYS_PRINTSTRING, / Print string system call /
SYS_GETKEY, / Get key system call /
SYS_SETATTR, / Set screen attribute system call /
SYS_GETCURSOR, / Get current cursor position /
SYS_PUTCURSOR, / Put current cursor position /
SYS_SPAWN, / Spawn process system call /
SYS_WAIT, / Wait for child process to exit system call /
SYS_GETPID, / Get pid (process id) system call /
SYS_KILL, / Kill a process /
SYS_PS, / Get the current process table /
SYS_SIGNAL, / Register a signal handler for a signal /
SYS_REGDELIVER, / Register user-space handler routines /
SYS_RETURNSIG, / Called when signal handler is done executing /
SYS_WAITNOPID, / Like Wait, but doesn’t require a PID. /
SYS_SETSCHEDULINGPOLICY, / Set scheduler policy system call /
SYS_GETTIMEOFDAY, / Get time of day system call /
SYS_CREATESEMAPHORE, / Create semaphore system call /
SYS_P, / P (acquire semaphore) system call /
SYS_V, / V (release semaphore) system call /
SYS_DESTROYSEMAPHORE, / Destroy semaphore system call /
SYS_GETppp, / Get ppp (process priority) system call / };
src\Geekos\ Syscall.c中:
static int Sys_Getppp(struct Interrupt_State state)
{
return g_currentThread->priority;
}
const Syscall g_syscallTable[] = {
Sys_Null,
Sys_Exit,
Sys_PrintString,
Sys_GetKey,
Sys_SetAttr,
Sys_GetCursor,
Sys_PutCursor,
Sys_Spawn,
Sys_Wait,
Sys_GetPID,
Sys_Kill,
Sys_PS,
Sys_Signal,
Sys_RegDeliver,
Sys_ReturnSignal,
Sys_WaitNoPID,
/* Scheduling and semaphore system calls. */
Sys_SetSchedulingPolicy,
Sys_GetTimeOfDay,
Sys_CreateSemaphore,
Sys_P,
Sys_V,
Sys_DestroySemaphore,
Sys_Getppp,
};
22、编写一个hello.c应用程序放到src/user,调用上一步骤编写的系统调用命令Get_Priority.
需要在build/makefile中# User program source files. USER_C_SRCS 处 添加此hello.c。
src/user/hello.c中:
#include <conio.h>
#include <process.h>
#include <string.h>
int main( int argc , char ** argv )
{
Print (“Hello world!\n “) ;
Print(”%d\n”, Get_ppp());
return 0;
}
//User program source files.
USER_C_SRCS :=
workload.c
semtest1.c semtest2.c p1.c p2.c p3.c
schedtest.c sched1.c sched2.c sched3.c
ping.c pong.c long.c
sigtest.c
shell.c b.c c.c hello.c
23、增加shell 命令为ppp, 使它能够获取当前进程优先级 。
Src\user\Shell.c中:
else if (strcmp(command, “ppp”) == 0) {
Print("%d\n", Get_ppp());
continue;
}
24要求:添加先来先服务(FCFS)调度算法,并能通过workload程序测试此算法。
测试格式举例如: $ workload.exe fcfs
提示:
(1)修改typedef enum {PSA,RR} SF_SchedulePolicy;使之增加枚举值FCFS。
(位于kthread.h中)
(2)修改workload.c使之通过调用Set_Scheduling_Policy能够识别并执行FCFS调度算法。
(位于src\user中)
(3)修改Sys_SetSchedulingPolicy使之能够识别并调用FCFS调度算法。
(位于syscall.c中)
(4)修改Chang_Scheduling_Policy使能够改变当前所使用的调度算法。
(位于kthread.c中)
(5)修改Get_Next_Runnable 使之根据不同的调度算法策略设置系统的调度算法。
(位于kthread.c中)