⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 Simple Operating Systems (简称SOS)是一个可以运行在X86平台上(包括QEMU
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Copyright (C) 2004  The SOS Team   This program is free software; you can redistribute it and/or   modify it under the terms of the GNU General Public License   as published by the Free Software Foundation; either version 2   of the License, or (at your option) any later version.      This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.      You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,   USA. */#include <sos/errno.h>/* Include definitions of the multiboot standard */#include <bootstrap/multiboot.h>#include <hwcore/idt.h>#include <hwcore/gdt.h>#include <hwcore/irq.h>#include <hwcore/exception.h>#include <hwcore/i8254.h>#include <sos/list.h>#include <sos/physmem.h>#include <hwcore/paging.h>#include <hwcore/mm_context.h>#include <hwcore/swintr.h>#include <sos/kmem_vmm.h>#include <sos/kmalloc.h>#include <sos/time.h>#include <sos/thread.h>#include <sos/process.h>#include <sos/umem_vmm.h>#include <sos/klibc.h>#include <sos/assert.h>#include <drivers/x86_videomem.h>#include <drivers/bochs.h>#include <sos/calcload.h>#include <sos/umem_vmm.h>#include <sos/binfmt_elf32.h>#include <drivers/zero.h>#include <sos/fs.h>#include <drivers/fs_virtfs.h>/* Helper function to display each bits of a 32bits integer on the   screen as dark or light carrets */void display_bits(unsigned char row, unsigned char col,		  unsigned char attribute,		  sos_ui32_t integer){  int i;  /* Scan each bit of the integer, MSb first */  for (i = 31 ; i >= 0 ; i--)    {      /* Test if bit i of 'integer' is set */      int bit_i = (integer & (1 << i));      /* Ascii 219 => dark carret, Ascii 177 => light carret */      unsigned char ascii_code = bit_i?219:177;      sos_x86_videomem_putchar(row, col++,			       attribute,			       ascii_code);    }}/* Clock IRQ handler */static void clk_it(int intid){  static sos_ui32_t clock_count = 0;  display_bits(0, 48,	       SOS_X86_VIDEO_FG_LTGREEN | SOS_X86_VIDEO_BG_BLUE,	       clock_count);  clock_count++;  /* Execute the expired timeout actions (if any) */  sos_time_do_tick();  /* Update scheduler statistics and status */  sos_sched_do_timer_tick();}/* ====================================================================== * Page fault exception handling *//* Page fault exception handler with demand paging for the kernel */static void pgflt_ex(int intid, struct sos_cpu_state *ctxt){  static sos_ui32_t demand_paging_count = 0;  struct sos_thread * cur_thr = sos_thread_get_current();  sos_vaddr_t faulting_vaddr  = sos_cpu_context_get_EX_faulting_vaddr(ctxt);  sos_paddr_t ppage_paddr;  if (sos_cpu_context_is_in_user_mode(ctxt)      || (cur_thr->fixup_uaccess.return_vaddr))    {      __label__ unforce_address_space;      sos_bool_t need_to_setup_mmu;      sos_ui32_t errcode = sos_cpu_context_get_EX_info(ctxt);      /* Make sure to always stay in the interrupted thread's MMU	 configuration */      need_to_setup_mmu = (cur_thr->squatted_mm_context			   != sos_process_get_mm_context(cur_thr->process));      if (need_to_setup_mmu)	sos_thread_prepare_user_space_access(NULL, 0);      if (SOS_OK ==	  sos_umem_vmm_try_resolve_page_fault(faulting_vaddr,					      errcode & (1 << 1),					      TRUE))	goto unforce_address_space;      /* If the page fault occured in kernel mode, return to kernel to	 the fixup address */      if (! sos_cpu_context_is_in_user_mode(ctxt))	{	  cur_thr->fixup_uaccess.faulted_uaddr = faulting_vaddr;	  sos_cpu_context_set_EX_return_address(ctxt,						cur_thr->fixup_uaccess.return_vaddr);	  goto unforce_address_space;	}      if (need_to_setup_mmu)	sos_thread_end_user_space_access();      sos_bochs_printf("Unresolved USER page Fault at instruction 0x%x on access to address 0x%x (info=%x)!\n",		       sos_cpu_context_get_PC(ctxt),		       (unsigned)faulting_vaddr,		       (unsigned)sos_cpu_context_get_EX_info(ctxt));      sos_bochs_printf("Terminating User thread\n");      sos_thread_exit();    unforce_address_space:      if (need_to_setup_mmu)	sos_thread_end_user_space_access();      return;    }  /* Check if address is covered by any VMM range */  if (! sos_kmem_vmm_is_valid_vaddr(faulting_vaddr))    {      /* No: The page fault is out of any kernel virtual region. For	 the moment, we don't handle this. */      sos_display_fatal_error("Unresolved page Fault at instruction 0x%x on access to address 0x%x (info=%x)!",			      sos_cpu_context_get_PC(ctxt),			      (unsigned)faulting_vaddr,			      (unsigned)sos_cpu_context_get_EX_info(ctxt));      SOS_ASSERT_FATAL(! "Got page fault (note: demand paging is disabled)");    }  /*   * Demand paging in kernel space   */   /* Update the number of demand paging requests handled */  demand_paging_count ++;  display_bits(0, 0,	       SOS_X86_VIDEO_FG_LTRED | SOS_X86_VIDEO_BG_BLUE,	       demand_paging_count);  /* Allocate a new page for the virtual address */  ppage_paddr = sos_physmem_ref_physpage_new(FALSE);  if (! ppage_paddr)    SOS_ASSERT_FATAL(! "TODO: implement swap. (Out of mem in demand paging because no swap for kernel yet !)");  SOS_ASSERT_FATAL(SOS_OK == sos_paging_map(ppage_paddr,					    SOS_PAGE_ALIGN_INF(faulting_vaddr),					    FALSE,					    SOS_VM_MAP_PROT_READ					    | SOS_VM_MAP_PROT_WRITE					    | SOS_VM_MAP_ATOMIC));  sos_physmem_unref_physpage(ppage_paddr);  /* Ok, we can now return to interrupted context */}/* ====================================================================== * An operating system MUST always have a ready thread ! Otherwise: * what would the CPU have to execute ?! */static void idle_thread(){  sos_ui32_t idle_twiddle = 0;  while (1)    {      /* Remove this instruction if you get an "Invalid opcode" CPU	 exception (old 80386 CPU) */      asm("hlt\n");      idle_twiddle ++;      display_bits(0, 0, SOS_X86_VIDEO_FG_GREEN | SOS_X86_VIDEO_BG_BLUE,		   idle_twiddle);            /* Lend the CPU to some other thread */      sos_thread_yield();    }}/* ====================================================================== * Kernel thread showing some CPU usage statistics on the console every 1s */static void stat_thread(){  while (1)    {      sos_ui32_t flags;      sos_ui32_t load1, load5, load15;      char str1[11], str5[11], str15[11];      struct sos_time t;      t.sec = 1;      t.nanosec = 0;      sos_thread_sleep(& t);      sos_disable_IRQs(flags);      /* The IDLE task is EXcluded in the following computation */      sos_load_get_sload(&load1, &load5, &load15);      sos_load_to_string(str1, load1);      sos_load_to_string(str5, load5);      sos_load_to_string(str15, load15);      sos_x86_videomem_printf(16, 34,			      SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,			      "Kernel (- Idle): %s %s %s    ",			      str1, str5, str15);      sos_load_get_uload(&load1, &load5, &load15);      sos_load_to_string(str1, load1);      sos_load_to_string(str5, load5);      sos_load_to_string(str15, load15);      sos_x86_videomem_printf(17, 34,			      SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,			      "User: %s %s %s        ",			      str1, str5, str15);      sos_load_get_uratio(&load1, &load5, &load15);      sos_load_to_string(str1, load1);      sos_load_to_string(str5, load5);      sos_load_to_string(str15, load15);      sos_x86_videomem_printf(18, 34,			      SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,			      "User CPU %%: %s %s %s        ",			      str1, str5, str15);      /* The IDLE task is INcluded in the following computation */      sos_load_get_sratio(&load1, &load5, &load15);      sos_load_to_string(str1, load1);      sos_load_to_string(str5, load5);      sos_load_to_string(str15, load15);      sos_x86_videomem_printf(19, 34,			      SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,			      "Kernel CPU %% (+ Idle): %s %s %s    ",			      str1, str5, str15);      sos_restore_IRQs(flags);    }}/* ====================================================================== * Start the "init" (userland) process */static sos_ret_tstart_init(struct sos_fs_manager_instance * rootfs){  sos_ret_t retval;  struct sos_umem_vmm_as *as_init;  struct sos_process *proc_init;  struct sos_thread *new_thr;  sos_uaddr_t ustack, start_uaddr;  struct sos_fs_opened_file * init_root, * init_cwd, * unused_of;  /* Create the new process */  proc_init = sos_process_create("init", FALSE);  if (! proc_init)    return -SOS_ENOMEM;  as_init = sos_process_get_address_space(proc_init);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -