*/
if (scanCode & KB_KEY_RELEASE) { release = true;
scanCode &= ~(KB_KEY_RELEASE); }
if (scanCode >= SCAN_TABLE_SIZE) {
Print(\, scanCode); goto done; }
/* Process the key */
shift = ((s_shiftState & SHIFT_MASK) != 0);
keycode = shift ? s_scanTableWithShift[scanCode] : s_scanTableNoShift[scanCode]; /* Update shift, control and alt state */ switch (keycode) { case KEY_LSHIFT: flag = LEFT_SHIFT; break;
case KEY_RSHIFT: flag = RIGHT_SHIFT; break; case KEY_LCTRL: flag = LEFT_CTRL; break; case KEY_RCTRL: flag = RIGHT_CTRL; break; case KEY_LALT: flag = LEFT_ALT; break; case KEY_RALT: flag = RIGHT_ALT; break; default:
goto noflagchange; }
if (release)
s_shiftState &= ~(flag); else
s_shiftState |= flag; /*
* Shift, control and alt keys don't have to be * queued, flags will be set! */ goto done;
noflagchange:
/* Format the new keycode */ if (shift)
keycode |= KEY_SHIFT_FLAG; if ((s_shiftState & CTRL_MASK) != 0) keycode |= KEY_CTRL_FLAG; if ((s_shiftState & ALT_MASK) != 0) keycode |= KEY_ALT_FLAG; if (release)
keycode |= KEY_RELEASE_FLAG;
/* Put the keycode in the buffer */ Enqueue_Keycode(keycode); /* Wake up event consumers */ Wake_Up(&s_waitQueue); /*
* Pick a new thread upon return from interrupt * (hopefully the one waiting for the keyboard event) */
g_needReschedule = true;
} done:
End_IRQ(state); }
(二) project1的设计
1.设计原理
在函数Parse_ELF_Executable()中添加代码,分析ELF格式的可执行文件(包括分析得出ELF文件头、程序头,获取可执行文件长度,代码段、数据段等信息),并填充Exe_Format数据中的值域。熟悉ELF文件格式,了解GeekOS系统如何将ELF格式的可执行程序装入到内存,建立内核进程并运行的实现技术。
2.运行原理
(1) 从用户程序的入口_Entry进入,而不是Main进入(Main函数实际是开发这定义的
程序主函数的名称)。
(2) 在GeekOS启动后,从PFAT文件系统讲执行文件装入内存,建立进程并运行得到
相应的输出。
(3) 用户可以看到函数调用Spawn_Init_Process,该函数的功能是调用
Start_Kernel_Thread(),它以Spawner函数为进程体建立一个核心级进程,并使之准备就绪。
(4) 函数Spawner主要功能从PFAT文件系统读入一个用户执行程序,为之建立相应的
进程影像。然后调用Spawn Program函数建立相应进程。
3.项目设计要求
1、修改/geekos/elf.c文件:在函数Parse_ELF_Executable( )中添加代码,分析ELF格式的可执行文件(包括分析得出ELF文件头、程序头,获取可执行文件长度,代码段、数据段等信息),并填充Exe_Format数据结构中的域值。
2、在Linux环境下编译系统得到GeekOS镜像文件。 3、编写一个相应的bochs配置文件。
4、在bochs中运行GeekOS系统显示结果。
在此项目中,GeekOS需要从磁盘加载一个可执行文件到内存中,并且在内核线程中执行此程序。我们需要做的就是完成/geekos/elf.c中Parse_ELF_Executable函数,把EXE文件的内容填充到指定的Exe_format格式的区域。
/geekos/elf.c中Parse_ELF_Executable函数的定义如下:
int Parse_ELF_Executable(char *exeFileData, ulong_t exeFileLength, struct Exe_Format *exeFormat)
exeFileData为ELF(Executable and Linking Format)格式的可执行文件的内容,exeFileLength为文件的长度,函数就是需要把exeFileData中的数据填充到exeFormat中。
4.运行结果
(项目1)
5.核心代码
static int Spawn_Program(char *exeFileData, struct Exe_Format *exeFormat) {
struct Segment_Descriptor* desc;
unsigned long virtSize;
unsigned short codeSelector, dataSelector; int i;
ulong_t maxva = 0;
/* Find maximum virtual address */
for (i = 0; i < exeFormat->numSegments; ++i) {
struct Exe_Segment *segment = &exeFormat->segmentList[i]; ulong_t topva = segment->startAddress + segment->sizeInMemory; if (topva > maxva) maxva = topva; }
/* setup some memory space for the program */
virtSize = Round_Up_To_Page(maxva) + 4096; /* leave some slack for stack */ virtSpace = Malloc(virtSize);
memset((char *) virtSpace, '\\0', virtSize); /* Load segment data into memory */
for (i = 0; i < exeFormat->numSegments; ++i) {
struct Exe_Segment *segment = &exeFormat->segmentList[i]; memcpy(virtSpace + segment->startAddress,
exeFileData + segment->offsetInFile, segment->lengthInFile);
}
/* allocate and init descriptors and selectors for code and data */ // Kernel code segment.
desc = Allocate_Segment_Descriptor(); Init_Code_Segment_Descriptor(
desc,
(unsigned long)virtSpace, // base address (virtSize/PAGE_SIZE)+10, 0 );
// num pages
// privilege level (0 == kernel)
codeSelector = Selector( 0, true, Get_Descriptor_Index( desc ) ); // Kernel data segment.
desc = Allocate_Segment_Descriptor(); Init_Data_Segment_Descriptor(
desc,
(unsigned long)virtSpace, // base address (virtSize/PAGE_SIZE)+10, 0 );
// num pages
// privilege level (0 == kernel)
dataSelector = Selector( 0, true, Get_Descriptor_Index( desc ) ); Install_Interrupt_Handler( 0x90, &Printrap_Handler ); if (lprogdebug) {
Print(\); Print(\ = %x\\n\, (unsigned int) virtSpace); Print(\ = %x\\n\, (unsigned int) virtSize); Print(\, codeSelector); Print(\, dataSelector); Print(\); }
Trampoline(codeSelector, dataSelector, exeFormat->entryAddr); return 0; }
/* Spawner is a a thread that accomodates the program to be loaded & executed * it is started from main.c */
void Spawner( unsigned long arg ) {
const char *program = \; char *exeFileData = 0; ulong_t exeFileLength; struct Exe_Format exeFormat; /*
* Load the executable file data, parse ELF headers, * and load code and data segments into user memory. */
if (lprogdebug) {
Print(\, program); }
if (Read_Fully(program, (void**) &exeFileData, &exeFileLength) != 0) {
Print(\, program); goto fail; }
if (lprogdebug) {
Print(\); }
if (Parse_ELF_Executable(exeFileData, exeFileLength, &exeFormat) != 0) {
Print(\); goto fail; }
if (lprogdebug) {
Print(\);
百度搜索“77cn”或“免费范文网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,免费范文网,提供经典小说教育文库geekos计算机系统软件实验报告(2)在线全文阅读。
相关推荐: