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

📄 kernelmultitasker.c

📁 上一个上传的有问题,这个是好的。visopsys包括系统内核和GUI的全部SOURCE code ,还包括一些基本的docs文档。里面src子目录对应所有SOURCE code.对于想研究操作系统的朋
💻 C
📖 第 1 页 / 共 5 页
字号:
  // The scheduler needs to make a task (but not a fully-fledged  // process) for itself.  All other task switches will follow  // as nested tasks from the scheduler.    int status = 0;  int interrupts = 0;  processImage schedImage = {    scheduler, scheduler,    NULL, 0xFFFFFFFF,    NULL, 0xFFFFFFFF,    0xFFFFFFFF,    "", 0, { NULL }  };    status = createNewProcess("scheduler process", kernelProc->priority,			    kernelProc->privilege, &schedImage, 0);  if (status < 0)    return (status);  schedulerProc = getProcessById(status);  removeProcessFromQueue(schedulerProc);  // Set the instruction pointer to the scheduler task  schedulerProc->taskStateSegment.EIP = (unsigned) scheduler;  // Interrupts should always be disabled for this task, and we manually set  // the NT (nested task) flag as well, since Virtual PC doesn't do it when  // we switch the first time.  schedulerProc->taskStateSegment.EFLAGS = 0x00004002;  // Get a page directory  schedulerProc->taskStateSegment.CR3 =    (unsigned) kernelPageGetDirectory(KERNELPROCID);  // Not busy  markTaskBusy(schedulerProc->tssSelector, 0);  // The scheduler task should now be set up to run.  We should set   // up the kernel task to resume operation    // Before we load the kernel's selector into the task reg, mark it as  // not busy, since one cannot load the task register, with a busy TSS  // selector...  markTaskBusy(kernelProc->tssSelector, 0);  // Make the kernel's Task State Segment be the current one.  In  // reality, it IS still the currently running code  kernelProcessorLoadTaskReg(kernelProc->tssSelector);  // Reset the schedulerTime and schedulerTimeslices  schedulerTime = 0;  schedulerTimeslices = 0;    // Make sure the scheduler is set to "run"  schedulerStop = 0;  // Set the "switched by call" flag  schedulerSwitchedByCall = 0;  // Make note that the multitasker has been enabled.  We do it a little  // early so we can finish some of our tasks of creating threads without  // complaints  multitaskingEnabled = 1;  // Yield control to the scheduler  kernelMultitaskerYield();  // Disable interrupts, so we can insure that we don't immediately get  // a timer interrupt.  kernelProcessorSuspendInts(interrupts);  // Hook the system timer interrupt.  oldSysTimerHandler = kernelInterruptGetHandler(INTERRUPT_NUM_SYSTIMER);  if (oldSysTimerHandler == NULL)    return (status = ERR_NOTINITIALIZED);  // Install a task gate for the interrupt, which will  // be the scheduler's timer interrupt.  After this point, our  // new scheduler task will run with every clock tick  status = kernelDescriptorSetIDTTaskGate((0x20 + INTERRUPT_NUM_SYSTIMER), 	 				  schedulerProc->tssSelector);  if (status < 0)    {      kernelProcessorRestoreInts(interrupts);      return (status);    }  // Reenable interrupts after we get control back from the scheduler  kernelProcessorRestoreInts(interrupts);  // Return success  return (status = 0);}static int createKernelProcess(void){  // This function will create the kernel process at initialization time.  // Returns 0 on success, negative otherwise.  int status = 0;  int kernelProcId = 0;  processImage kernImage = {    (void *) KERNEL_VIRTUAL_ADDRESS,    kernelMain,     NULL, 0xFFFFFFFF,    NULL, 0xFFFFFFFF,    0xFFFFFFFF,    "", 0, { NULL }  };  // The kernel process is its own parent, of course, and it is owned   // by "admin".  We create no page table, and there are no arguments.  kernelProcId =     createNewProcess("kernel process", 1, PRIVILEGE_SUPERVISOR, &kernImage, 0);  if (kernelProcId < 0)    // Damn.  Not able to create the kernel process    return (kernelProcId);  // Get the pointer to the kernel's process  kernelProc = getProcessById(kernelProcId);  // Make sure it's not NULL  if (kernelProc == NULL)    // Can't access the kernel process    return (status = ERR_NOSUCHPROCESS);  // Interrupts are initially disabled for the kernel  kernelProc->taskStateSegment.EFLAGS = 0x00000002;  // Set the current process to initially be the kernel process  kernelCurrentProcess = kernelProc;  // Deallocate the stack that was allocated, since the kernel already  // has one.  kernelMemoryRelease(kernelProc->userStack);  // Create the kernel process' environment  status = kernelEnvironmentCreate(KERNELPROCID, (variableList *)				   &(kernelProc->environment), NULL);  if (status < 0)    // Couldn't create an environment structure for this process    return (status);  // Make the kernel's text streams be the console streams  kernelProc->textInputStream = kernelTextGetConsoleInput();  kernelProc->textInputStream->ownerPid = KERNELPROCID;  kernelProc->textOutputStream = kernelTextGetConsoleOutput();  // Make the kernel process runnable  kernelProc->state = proc_ready;  // Return success  return (status = 0);}static void incrementDescendents(kernelProcess *theProcess){  // This will walk up a chain of dependent child threads, incrementing  // the descendent count of each parent    kernelProcess *parentProcess = NULL;  if (theProcess->processId == KERNELPROCID)    // The kernel is its own parent    return;  parentProcess = getProcessById(theProcess->parentProcessId);  if (parentProcess == NULL)    // No worries.  Probably not a problem    return;  parentProcess->descendentThreads++;  // Do a recursion to walk up the chain  incrementDescendents(parentProcess);  // Done  return;}static void decrementDescendents(kernelProcess *theProcess){  // This will walk up a chain of dependent child threads, decrementing  // the descendent count of each parent    kernelProcess *parentProcess = NULL;  if (theProcess->processId == KERNELPROCID)    // The kernel is its own parent    return;  parentProcess = getProcessById(theProcess->parentProcessId);  if (parentProcess == NULL)    // No worries.  Probably not a problem    return;  parentProcess->descendentThreads--;  // Do a recursion to walk up the chain  decrementDescendents(parentProcess);  // Done  return;}static void kernelProcess2Process(kernelProcess *kernProcess,				  process *userProcess){  // Given a kernel-space process structure, create the corresponding  // user-space version.    strncpy(userProcess->processName, (char *) kernProcess->processName,	  MAX_PROCNAME_LENGTH);  userProcess->userId = kernProcess->userId;  userProcess->processId = kernProcess->processId;  userProcess->type = kernProcess->type;  userProcess->priority = kernProcess->priority;  userProcess->privilege = kernProcess->privilege;  userProcess->parentProcessId = kernProcess->parentProcessId;  userProcess->descendentThreads = kernProcess->descendentThreads;  userProcess->cpuPercent = kernProcess->cpuPercent;  userProcess->state = kernProcess->state;}//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////  Below here, the functions are exported for external use////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////int kernelMultitaskerInitialize(void){  // This function intializes the kernel's multitasker.  int status = 0;  int count;    // Make sure multitasking is NOT enabled already  if (multitaskingEnabled)    return (status = ERR_ALREADY);  // Now we must initialize the process queue  for (count = 0; count < MAX_PROCESSES; count ++)    processQueue[count] = NULL;  numQueued = 0;   // We need to create the kernel's own process.    status = createKernelProcess();  // Make sure it was successful  if (status < 0)    return (status);  // Now start the scheduler  status = schedulerInitialize();  if (status < 0)    // The scheduler couldn't start    return (status);  // Create an "idle" thread to consume all unused cycles  status = spawnIdleThread();  // Make sure it was successful  if (status < 0)    return (status);  // Start the exception handler thread.  status = exceptionThreadInitialize();  // Make sure it was successful  if (status < 0)    return (status);  // Log a boot message  kernelLog("Multitasking started");  // Return success  return (status = 0);}int kernelMultitaskerShutdown(int nice){  // This function will shut down the multitasker and halt the scheduler,   // returning exclusive control to the kernel process.  If the nice  // argument is non-zero, this function will do a nice orderly shutdown,  // killing all the running processes gracefully.  If it is zero, the  // resources allocated to the processes will never be freed, and the  // multitasker will just stop.  Returns 0 on success, negative otherwise.   int status = 0;  // Make sure multitasking has been enabled  if (!multitaskingEnabled)    // We can't yield if we're not multitasking yet    return (status = ERR_NOTINITIALIZED);  // If we are doing a "nice" shutdown, we will kill all the running  // processes (except the kernel and scheduler) gracefully.  if (nice)    kernelMultitaskerKillAll();  // Set the schedulerStop flag to stop the scheduler  schedulerStop = 1;  // Yield control back to the scheduler, so that it can stop  kernelMultitaskerYield();  // Make note that the multitasker has been disabled  multitaskingEnabled = 0;  // Deallocate the stack used by the scheduler  kernelMemoryReleaseSystem(schedulerProc->userStack);  // Print a message  kernelLog("Multitasking stopped");    return (status = 0);}void kernelExceptionHandler(void){  // This code sleeps until woken up by an exception.  Before multitasking  // starts it is referenced by an interrupt gate.  Afterward, it has its  // TSS referenced by a task gate descriptor in the IDT.  char tmpMsg[256];  void *stackMemory = NULL;  int count;  extern kernelSymbol *kernelSymbols;  extern int kernelNumberSymbols;  while(1)    {      // We got an exception.      deadProcess = kernelCurrentProcess;      deadProcess->state = proc_stopped;      kernelCurrentProcess = exceptionProc;      // Don't get into a loop.      if (exceptionProc->state != proc_sleeping)	kernelPanic("Double-fault while processing exception");      exceptionProc->state = proc_running;      // If the fault occurred while we were processing an interrupt,      // we should tell the PIC that the interrupt service routine is      // finished.  It's not really fair to kill a process because an      // interrupt handler is screwy, but that's what we have to do for      // the time being.      if (kernelProcessingInterrupt)	kernelPicEndOfInterrupt(0xFF);      if (!multitaskingEnabled || (deadProcess == kernelProc))	strcpy(tmpMsg, "The kernel has experienced a fatal exception");      // Get the dead process      else if (deadProcess == NULL)	// We have to make an error here.  We can't return to the program	// that caused the exception, and we can't tell the multitasker	// to kill it.  We'd better make a kernel panic.	kernelPanic("Exception handler unable to determine current process");      else	sprintf(tmpMsg, "Process \"%s\" caused a fatal exception",		deadProcess->processName);      if (multitaskingEnabled)	{	  if (deadProcess->taskStateSegment.EIP >= KERNEL_VIRTUAL_ADDRESS)	    {	      char *symbolName = NULL;	      if (kernelSymbols)		{		  // Find roughly the kernel function where the exception		  // happened		  for (count = 0; count < kernelNumberSymbols; count ++)		    {		      if ((deadProcess->taskStateSegment.EIP >=			   kernelSymbols[count].address) &&			  (deadProcess->taskStateSegment.EIP <			   kernelSymbols[count + 1].address))			{			  symbolName = kernelSymbols[count].symbol;			  break;			}		    }		}	      if (symbolName)		sprintf(tmpMsg, "%s in function %s", tmpMsg, symbolName);	      else		sprintf(tmpMsg, "%s at kernel address %08x", tmpMsg,			deadProcess->taskStateSegment.EIP);	    }	  else	    sprintf(tmpMsg, "%s at application address %08x", tmpMsg,		    deadProcess->taskStateSegment.EIP);	}      if (kernelProcessingInterrupt)	sprintf(tmpMsg, "%s while processing interrupt %d", tmpMsg,		kernelPicGetActive());      if (!multitaskingEnabled || (deadProcess == kernelProc))

⌨️ 快捷键说明

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