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

📄 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 "kernelMemoryManager.h"#include "kernelMalloc.h"#include "kernelFile.h"#include "kernelMain.h"#include "kernelPageManager.h"#include "kernelProcessorX86.h"#include "kernelPic.h"#include "kernelSysTimer.h"#include "kernelEnvironment.h"#include "kernelShutdown.h"#include "kernelMiscFunctions.h"#include "kernelInterrupt.h"#include "kernelLog.h"#include "kernelError.h"#include <stdio.h>#include <string.h>#include <signal.h>// Global multitasker stuffstatic int multitaskingEnabled = 0;static volatile int processIdCounter = KERNELPROCID;static kernelProcess *kernelProc = NULL;static kernelProcess *idleProc = NULL;static kernelProcess *exceptionProc = NULL;static kernelProcess *deadProcess;static volatile int schedulerSwitchedByCall = 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;#define PROC_KILLABLE(proc) ((proc != kernelProc) &&        \                             (proc != exceptionProc) &&     \                             (proc != idleProc) &&          \                             (proc != kernelCurrentProcess))  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);}static 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;  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);}static 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;  // 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);    // Fill in the process' Task State Segment descriptor  status = kernelDescriptorSet(     theProcess->tssSelector, // TSS selector number     &(theProcess->taskStateSegment), // Starts at...     sizeof(kernelTSS),      // 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), sizeof(kernelTSS));  if (theProcess->privilege == PRIVILEGE_SUPERVISOR)    {      theProcess->taskStateSegment.CS = PRIV_CODE;      theProcess->taskStateSegment.DS = PRIV_DATA;      theProcess->taskStateSegment.SS = PRIV_STACK;    }  else    {      theProcess->taskStateSegment.CS = USER_CODE;      theProcess->taskStateSegment.DS = USER_DATA;      theProcess->taskStateSegment.SS = USER_STACK;    }  theProcess->taskStateSegment.ES = theProcess->taskStateSegment.DS;  theProcess->taskStateSegment.FS = theProcess->taskStateSegment.DS;  theProcess->taskStateSegment.GS = theProcess->taskStateSegment.DS;  theProcess->taskStateSegment.ESP =    ((unsigned) theProcess->userStack +     (theProcess->userStackSize - sizeof(int)));  if (theProcess->privilege == PRIVILEGE_USER)    {      theProcess->taskStateSegment.SS0 = PRIV_STACK;      theProcess->taskStateSegment.ESP0 = ((unsigned) theProcess->superStack + 					   (theProcess->superStackSize -					    sizeof(int)));    }  theProcess->taskStateSegment.EFLAGS = 0x00000202; // Interrupts enabled  theProcess->taskStateSegment.CR3 = ((unsigned) processPageDir);  // All remaining values will be NULL from initialization.  Note that this   // includes the EIP.  // Return success  return (status = 0);}static int createNewProcess(const char *name, int priority, int privilege,			    processImage *execImage, int newPageDir){  // This function is used to create a new process in the process  // queue.  It makes a "defaults" kind of process -- it sets up all of  // the process' attributes with default values.  If the calling process  // wants something different, it should reset those attributes afterward.  // If successful, it returns the processId of the new process.  Otherwise,   // it returns negative.  int status = 0;  kernelProcess *newProcess = NULL;  void *stackMemoryAddr = NULL;  void *processPageDir = NULL;  void *physicalCodeData = NULL;  int *args = NULL;  char **argv = NULL;  int argSpaceSize = 0;  char *argSpace = NULL;  char *newArgAddress = NULL;  int length = 0;  int count;  // Don't bother checking the parameters, as the external functions   // should have done this already.  // We need to see if we can get some fresh process control memory  status = requestProcess(&newProcess);  if (status < 0)    return (status);  if (newProcess == NULL)    return (status = ERR_NOFREE);  // Ok, we got a new, fresh process.  We need to start filling in some  // of the process' data (after initializing it, of course)  kernelMemClear((void *) newProcess, sizeof(kernelProcess));  // Fill in the process' Id number  newProcess->processId = processIdCounter++;  // By default, the type is process  newProcess->type = proc_normal;  // Now, if the process Id is KERNELPROCID, then we are creating the  // kernel process, and it will be its own parent.  Otherwise, get the  // current process and make IT be the parent of this new process  if (newProcess->processId == KERNELPROCID)    {      newProcess->parentProcessId = newProcess->processId;      newProcess->userId = 1;   // root      // Give it "/" as current working directory      strncpy((char *) newProcess->currentDirectory, "/", 2);    }  else    {      // Make sure the current process isn't NULL      if (kernelCurrentProcess == NULL)	{	  releaseProcess(newProcess);	  return (status = ERR_NOSUCHPROCESS);	}      // Fill in the process' parent Id number      newProcess->parentProcessId = kernelCurrentProcess->processId;      // Fill in the process' user Id number      newProcess->userId = kernelCurrentProcess->userId;      // Fill in the current working directory      strncpy((char *) newProcess->currentDirectory, 	      (char *) kernelCurrentProcess->currentDirectory,	      MAX_PATH_LENGTH);      newProcess->currentDirectory[MAX_PATH_LENGTH - 1] = '\0';    }  // Fill in the process name  strncpy((char *) newProcess->processName, name, MAX_PROCNAME_LENGTH);  newProcess->processName[MAX_PROCNAME_LENGTH - 1] = '\0';  // Fill in the process' priority level  newProcess->priority = priority;  // Fill in the process' privilege level  newProcess->privilege = privilege;  // The amount of time since started (now)  newProcess->startTime = kernelSysTimerRead();  // The thread's initial state will be "stopped"  newProcess->state = proc_stopped;  // Do we need to create a new page directory and a set of page tables for   // this process?  if (newPageDir)    {      // We need to make a new page directory, etc.      processPageDir = kernelPageNewDirectory(newProcess->processId,					      newProcess->privilege);      if (processPageDir == NULL)	{	  // Not able to setup a page directory	  releaseProcess(newProcess);	  return (status = ERR_NOVIRTUAL);	}      // Get the physical address of the code/data      physicalCodeData =

⌨️ 快捷键说明

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