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

📄 kernelmultitasker.c

📁 上一个上传的有问题,这个是好的。visopsys包括系统内核和GUI的全部SOURCE code ,还包括一些基本的docs文档。里面src子目录对应所有SOURCE code.对于想研究操作系统的朋
💻 C
📖 第 1 页 / 共 5 页
字号:
////  Visopsys//  Copyright (C) 1998-2005 J. Andrew McLaughlin// //  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.////  kernelMultitasker.c//// This file contains the C functions belonging to the kernel's // multitasker#include "kernelMultitasker.h"#include "kernelParameters.h"#include "kernelMemory.h"#include "kernelMalloc.h"#include "kernelFile.h"#include "kernelMain.h"#include "kernelPage.h"#include "kernelProcessorX86.h"#include "kernelPic.h"#include "kernelSysTimer.h"#include "kernelEnvironment.h"#include "kernelShutdown.h"#include "kernelMisc.h"#include "kernelInterrupt.h"#include "kernelNetwork.h"#include "kernelLog.h"#include "kernelError.h"#include <stdio.h>#include <string.h>#include <signal.h>#define PROC_KILLABLE(proc) ((proc != kernelProc) &&        \                             (proc != idleProc) &&          \                             (proc != kernelCurrentProcess))// next added for I/O port protection by Davide Airaghi#define SET_PORT_BIT(port,portarr)    portarr[ port / 8 ] |=  1 << (port % 8);#define UNSET_PORT_BIT(port,portarr)  portarr[ port / 8 ] &= ~(1 << (port %8));#define GET_PORT_BIT(port,portarr)    (portarr[ port / 8] >> (port % 8)) & 0x01;#define ALLOW_PORT_IO(port,portarr)  UNSET_PORT_BIT(port,portarr)#define NOT_ALLOW_PORT_IO(port,portarr)  SET_PORT_BIT(port,portarr)#define FILL_PORT_BYTES(cont,portarr,val) for (cont=0;cont<PORTS_BYTES;cont++) portarr[cont]=val;#define IOMAP_REQUESTED_SIZE(max_port)  (((max_port / 8)*8)+1)   // Global multitasker stuffstatic int multitaskingEnabled = 0;static volatile int processIdCounter = KERNELPROCID;static kernelProcess *kernelProc = NULL;static kernelProcess *idleProc = NULL;static volatile int schedulerSwitchedByCall = 0;static int fpuProcess = 0;// We allow the pointer to the current process to be exported, so that// when a process uses system calls, there is an easy way for the// process to get information about itself.kernelProcess *kernelCurrentProcess = NULL;// Process queue for CPU executionstatic kernelProcess* processQueue[MAX_PROCESSES];static volatile int numQueued = 0;// Things specific to the scheduler.  The scheduler process is just a// convenient place to keep things, we don't use all of it and it doesn't// go in the queuestatic kernelProcess *schedulerProc = NULL;static volatile int schedulerStop = 0;static void (*oldSysTimerHandler)(void) = NULL;static volatile unsigned schedulerTimeslices = 0;static volatile unsigned schedulerTime = 0;// An array of exception types.  The selectors are initialized later.struct {  int index;  kernelSelector tssSelector;  const char *a;  const char *name;  int (*handler) (void);} exceptionVector[19] = {  { EXCEPTION_DIVBYZERO, 0, "a", "divide-by-zero", NULL },  { EXCEPTION_DEBUG, 0, "a", "debug", NULL },  { EXCEPTION_NMI, 0, "a", "non-maskable interrupt (NMI)", NULL },  { EXCEPTION_BREAK, 0, "a", "breakpoint", NULL },  { EXCEPTION_OVERFLOW, 0, "a", "overflow", NULL },  { EXCEPTION_BOUNDS, 0, "a", "out-of-bounds", NULL },  { EXCEPTION_OPCODE, 0, "an", "invalid opcode", NULL },  { EXCEPTION_DEVNOTAVAIL, 0, "a", "device not available", NULL },  { EXCEPTION_DOUBLEFAULT, 0, "a", "double-fault", NULL },  { EXCEPTION_COPROCOVER, 0, "a", "co-processor segment overrun", NULL },  { EXCEPTION_INVALIDTSS, 0, "an", "invalid TSS", NULL },  { EXCEPTION_SEGNOTPRES, 0, "a", "segment not present", NULL },  { EXCEPTION_STACK, 0, "a", "stack", NULL },  { EXCEPTION_GENPROTECT, 0, "a", "general protection", NULL },  { EXCEPTION_PAGE, 0, "a", "page fault", NULL },  { EXCEPTION_RESERVED, 0, "a", "\"reserved\"", NULL },  { EXCEPTION_FLOAT, 0, "a", "floating point", NULL },  { EXCEPTION_ALIGNCHECK, 0, "an", "alignment check", NULL },  { EXCEPTION_MACHCHECK, 0, "a", "machine check", NULL }};static kernelProcess *getProcessById(int processId){  // This routine is used to find a process' pointer based on the process  // Id.  Nothing fancy -- it just searches through the list.  Maybe later  // it can be some kind of fancy sorting/searching procedure.  Returns NULL  // if the process doesn't exist    kernelProcess *theProcess = NULL;  int count;  for (count = 0; count < numQueued; count ++)    if (processQueue[count]->processId == processId)      {        theProcess = processQueue[count];        break;      }  // If we didn't find it, this will still be NULL  return (theProcess);}static kernelProcess *getProcessByName(const char *name){  // As above, but searches by name    kernelProcess *theProcess = NULL;  int count;  for (count = 0; count < numQueued; count ++)    if (!strcmp((char *) processQueue[count]->processName, name))      {        theProcess = processQueue[count];        break;      }  // If we didn't find it, this will still be NULL  return (theProcess);}static inline int requestProcess(kernelProcess **processPointer){  // This routine is used to allocate new process control memory.  It  // should be passed a reference to a pointer that will point to  // the new process, if allocated successfully.  int status = 0;  kernelProcess *newProcess = NULL;  // Make sure the pointer->pointer parameter we were passed isn't NULL  if (processPointer == NULL)    // Oops.    return (status = ERR_NULLPARAMETER);    newProcess = kernelMalloc(sizeof(kernelProcess));  if (newProcess == NULL)    return (status = ERR_MEMORY);  // Success.  Set the pointer for the calling process  *processPointer = newProcess;  return (status = 0);}// modified by Davide Airaghistatic inline int releaseProcess(kernelProcess *killProcess){  // This routine is used to free process control memory.  It  // should be passed the process Id of the process to kill.  It  // returns 0 on success, negative otherwise  int status = 0;  // destroy TSS data! Davide Airaghi  status = kernelFree((void *) killProcess->taskStateSegment);  if (status < 0)    return status;  status = kernelFree((void *) killProcess);  return (status);}static int addProcessToQueue(kernelProcess *targetProcess){  // This routine will add a process to the task queue.  It returns zero   // on success, negative otherwise  int status = 0;  int count;    if (targetProcess == NULL)    // The process does not exist, or is not accessible    return (status = ERR_NOSUCHPROCESS);  // Make sure the priority is a legal value  if ((targetProcess->priority < 0) ||       (targetProcess->priority > (PRIORITY_LEVELS - 1)))    // The process' priority is an illegal value    return (status = ERR_INVALID);  // Search the process queue to make sure it isn't already present  for (count = 0; count < numQueued; count ++)    if (processQueue[count] == targetProcess)      // Oops, it's already there      return (status = ERR_ALREADY);    // OK, now we can add the process to the queue  processQueue[numQueued++] = targetProcess;  // Done  return (status = 0);}static int removeProcessFromQueue(kernelProcess *targetProcess){  // This routine will remove a process from the task queue.  It returns zero   // on success, negative otherwise  int status = 0;  int processPosition = 0;  int count;    if (targetProcess == NULL)    // The process does not exist, or is not accessible    return (status = ERR_NOSUCHPROCESS);  // Search the queue for the matching process  for (count = 0; count < numQueued; count ++)    if (processQueue[count] == targetProcess)      {	processPosition = count;	break;      }  // Make sure we found the process  if (processQueue[processPosition] != targetProcess)    // The process is not in the task queue    return (status = ERR_NOSUCHPROCESS);  // Subtract one from the number of queued processes  numQueued -= 1;  // OK, now we can remove the process from the queue.  If there are one  // or more remaining processes in this queue, we will shorten the queue  // by moving the LAST process into the spot we're vacating  if ((numQueued > 0) && (processPosition != numQueued))    processQueue[processPosition] = processQueue[numQueued];  // Done  return (status = 0);}// modified by Davide Airaghistatic int createTaskStateSegment(kernelProcess *theProcess,				  void *processPageDir){  // This function will create a TSS (Task State Segment) for a new  // process based on the attributes of the process.  This function relies  // on the privilege, userStackSize, and superStackSize attributes having   // been previously set.  Returns 0 on success, negative on error.  int status = 0;  // next vars needed by FILL_PORT_BYTES macro & other, Davide Airaghi  int counter = 0;  int not_for_kernel = 1;  unsigned int extra_space = 0;    if (theProcess->ring0 == 1)    not_for_kernel = 0;    // Get a free descriptor for the process' TSS  status = kernelDescriptorRequest(&(theProcess->tssSelector));  if ((status < 0) || (theProcess->tssSelector == 0))    // Crap.  An error getting a free descriptor.    return (status);  // this process belongs to admin and it's NOT part of the kernel!  if (theProcess->privilege == PRIVILEGE_SUPERVISOR && not_for_kernel == 1)      extra_space = sizeof(unsigned char)*(PORTS_BYTES-1);  // Allocate data for TSS! Davide Airaghi  theProcess->TSSsize = sizeof(kernelTSS)+extra_space;    theProcess->taskStateSegment = kernelMalloc(theProcess->TSSsize);  if (theProcess->taskStateSegment == NULL) {      // Crap.  An error getting memory!      kernelDescriptorRelease(theProcess->tssSelector);      return (ERR_MEMORY);    }          // Fill in the process' Task State Segment descriptor  status = kernelDescriptorSet(     theProcess->tssSelector, // TSS selector number     /*&*/(theProcess->taskStateSegment), // Starts at... // removed '&' by Davide Airaghi, now this field is a pointer!     theProcess->TSSsize,      // Limit of a TSS segment     1,                      // Present in memory     PRIVILEGE_SUPERVISOR,   // TSSs are supervisor privilege level     0,                      // TSSs are system segs     0xB,                    // TSS, 32-bit, busy     0,                      // 0 for SMALL size granularity     0);                     // Must be 0 in TSS  if (status < 0)    {      // Crap.  An error getting a free descriptor.      kernelDescriptorRelease(theProcess->tssSelector);      return (status);    }  // Now, fill in the TSS (Task State Segment) for the new process.  Parts  // of this will be different depending on whether this is a user  // or supervisor mode process  kernelMemClear((void *) /*&*/(theProcess->taskStateSegment), theProcess->TSSsize); // removed '&'  by Davide Airaghi, now this field is a pointer!    // set IOBitmap's offset in TSS for I/O port protection, Davide Airaghi  ((kernelTSS *)(theProcess->taskStateSegment))->IOMapBase = IOBITMAP_OFFSET;  // create a pointer to IOBitmap  theProcess->IOMap = (unsigned char*)(&( ((kernelTSS *)(theProcess->taskStateSegment))->IOMap));      // ok this is the kernel process!  if (theProcess->privilege == PRIVILEGE_SUPERVISOR && not_for_kernel == 0)    {      ((kernelTSS *)(theProcess->taskStateSegment))->CS = PRIV_CODE;      ((kernelTSS *)(theProcess->taskStateSegment))->DS = PRIV_DATA;      ((kernelTSS *)(theProcess->taskStateSegment))->SS = PRIV_STACK;      // supervisor (in this case it's the kernel or a 'part' of it)       // by default can use all I/O ports he wants, Davide Airaghi      // no settings required ... we're running at ring 0!    }  else    {       // cast required! Davide Airaghi      ((kernelTSS *)(theProcess->taskStateSegment))->CS = USER_CODE;      ((kernelTSS *)(theProcess->taskStateSegment))->DS = USER_DATA;      ((kernelTSS *)(theProcess->taskStateSegment))->SS = USER_STACK;      if (theProcess->privilege != PRIVILEGE_SUPERVISOR) {        // normal user by default can't use any I/O port, Davide Airaghi        theProcess->max_io_port = 7; // 0..7 == 1 byte ;-)        theProcess->IOMap[0] = PORT_VAL_BYTE_FALSE;      }      else {        // supervisor by default can use all I/O ports he wants, Davide Airaghi        theProcess->max_io_port = IO_PORTS -1;        FILL_PORT_BYTES(counter,theProcess->IOMap,PORT_VAL_BYTE_TRUE)	    	// for debug	NOT_ALLOW_PORT_IO(1111,theProcess->IOMap);      }    }  // cast required! Davide Airaghi  ((kernelTSS *)(theProcess->taskStateSegment))->ES = ((kernelTSS *)(theProcess->taskStateSegment))->DS;  ((kernelTSS *)(theProcess->taskStateSegment))->FS = ((kernelTSS *)(theProcess->taskStateSegment))->DS;  ((kernelTSS *)(theProcess->taskStateSegment))->GS = ((kernelTSS *)(theProcess->taskStateSegment))->DS;  // cast required! Davide Airaghi   ((kernelTSS *)(theProcess->taskStateSegment))->ESP =    ((unsigned) theProcess->userStack +     (theProcess->userStackSize - sizeof(int)));  if (/*theProcess->privilege == PRIVILEGE_USER &&*/ not_for_kernel == 1) // mod by Davide Airaghi    {       // cast required! Davide Airaghi      ((kernelTSS *)(theProcess->taskStateSegment))->SS0 = PRIV_STACK;      ((kernelTSS *)(theProcess->taskStateSegment))->ESP0 = ((unsigned) theProcess->superStack + 					   (theProcess->superStackSize -					    sizeof(int)));    }   // cast required! Davide Airaghi  ((kernelTSS *)(theProcess->taskStateSegment))->EFLAGS = 0x00000202; // Interrupts enabled && IOPL = 0, 						    // ring <= 0 can use I/O ports                                        //0x00003202; to have IOPL == 3  ((kernelTSS *)(theProcess->taskStateSegment))->CR3 = ((unsigned) processPageDir);  // All remaining values will be NULL from initialization.  Note that this   // includes the EIP.  // Return success

⌨️ 快捷键说明

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