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

📄 kernelmultitasker.c

📁 上一个上传的有问题,这个是好的。visopsys包括系统内核和GUI的全部SOURCE code ,还包括一些基本的docs文档。里面src子目录对应所有SOURCE code.对于想研究操作系统的朋
💻 C
📖 第 1 页 / 共 5 页
字号:
  return (status = 0);}// modified by Davide Airaghistatic 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;  int require_ring0 = 0;   // by DAvide Airaghi   if (privilege & PRIVILEGE_KERNEL || priority == KERNEL_PRIORITY) {    require_ring0 = 1;    privilege = privilege & ~PRIVILEGE_KERNEL;    // normal user can't be at ring0!!!!    if (privilege != PRIVILEGE_SUPERVISOR)	require_ring0 = 0;   }  // for debug  // kernelError(kernel_error,"%s: ring0? %d\n",name,require_ring0);  // 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));  // set the "ring0" field by Davide Airaghi  if (require_ring0)    newProcess->ring0 = 1;  else    newProcess->ring0 = 0;      // 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 =	kernelPageGetPhysical(newProcess->parentProcessId, execImage->code);      // Make the process own its code/data memory.  Don't remap it yet      // because we want to map it at the requested virtual address.      status = kernelMemoryChangeOwner(newProcess->parentProcessId,				newProcess->processId, 0, execImage->code,				NULL);      if (status < 0)	{	  // Couldn't make the process own its memory	  releaseProcess(newProcess);	  return (status);	}      // Remap the code/data to the requested virtual address.      status = kernelPageMap(newProcess->processId, physicalCodeData,			     execImage->virtualAddress, execImage->imageSize);      if (status < 0)	{	  // Couldn't map the process memory	  releaseProcess(newProcess);	  return (status);	}      // Code should be read-only      status =	kernelPageSetAttrs(newProcess->processId, 0, PAGEFLAG_WRITABLE,			   execImage->virtualAddress, execImage->codeSize);      if (status < 0)	{	  releaseProcess(newProcess);	  return (status);	}    }  else    {      // This process will share a page directory with its parent      processPageDir = kernelPageShareDirectory(newProcess->parentProcessId, 						newProcess->processId);      if (processPageDir == NULL)	{	  // Not able to setup a page directory	  releaseProcess(newProcess);	  return (status = ERR_NOVIRTUAL);	}    }  // Give the process a stack  stackMemoryAddr =    kernelMemoryGet((DEFAULT_STACK_SIZE + DEFAULT_SUPER_STACK_SIZE),		    "process stack");  if (stackMemoryAddr == NULL)    {      // We couldn't make a stack for the new process.  Maybe the system      // doesn't have anough available memory?      releaseProcess(newProcess);      return (status = ERR_MEMORY);    }  if (!require_ring0) // (newProcess->privilege == PRIVILEGE_USER)    {      newProcess->userStackSize = DEFAULT_STACK_SIZE;      newProcess->superStackSize = DEFAULT_SUPER_STACK_SIZE;    }  else    newProcess->userStackSize =      (DEFAULT_STACK_SIZE + DEFAULT_SUPER_STACK_SIZE);  // Copy 'argc' and 'argv' arguments to the new process' stack while we  // still own the stack memory.  // Set pointers to the appropriate stack locations for the arguments  args = (stackMemoryAddr + newProcess->userStackSize - (2 * sizeof(int)));  // Calculate the amount of memory we need to allocate for argument data.  // Leave space for pointers to the strings, since the (int argc,  // char *argv[]) scheme means just 2 values on the stack: an integer  // an a pointer to an array of char* pointers...  argSpaceSize = ((execImage->argc + 1) * sizeof(char *));  for (count = 0; count < execImage->argc; count ++)    argSpaceSize += (strlen(execImage->argv[count]) + 1);  // Get memory for the argument data  argSpace = kernelMemoryGet(argSpaceSize, "process arguments");  if (argSpace == NULL)    {      kernelMemoryRelease(stackMemoryAddr);      releaseProcess(newProcess);      return (status = ERR_MEMORY);    }        // Change ownership to the new process, and share it back with this process.  if (kernelMemoryChangeOwner(newProcess->parentProcessId,			      newProcess->processId, 1, argSpace,			      (void **) &newArgAddress) < 0)    {      kernelMemoryRelease(stackMemoryAddr);      kernelMemoryRelease(argSpace);      releaseProcess(newProcess);      return (status = ERR_MEMORY);    }  if (kernelMemoryShare(newProcess->processId, newProcess->parentProcessId,			newArgAddress, (void **) &argSpace) < 0)    {      kernelMemoryRelease(stackMemoryAddr);      releaseProcess(newProcess);      return (status = ERR_MEMORY);    }  args[0] = execImage->argc;  args[1] = (int) newArgAddress;	  argv = (char **) argSpace;  argSpace += ((execImage->argc + 1) * sizeof(char *));  newArgAddress += ((execImage->argc + 1) * sizeof(char *));  // Copy the args into argv  for (count = 0; count < execImage->argc; count ++)    {      strcpy((argSpace + length), execImage->argv[count]);      argv[count] = (newArgAddress + length);      length += (strlen(execImage->argv[count]) + 1);    }  // argv[argc] is supposed to be a NULL pointer, according to  // some standard or other  argv[args[0]] = NULL;  // Unmap the argument space from this process  kernelPageUnmap(newProcess->parentProcessId, argSpace, argSpaceSize);  // Make the process own its stack memory  status = kernelMemoryChangeOwner(newProcess->parentProcessId, 				   newProcess->processId, 1, // remap				   stackMemoryAddr, 				   (void **) &(newProcess->userStack));  if (status < 0)    {      // Couldn't make the process own its memory      kernelMemoryRelease(stackMemoryAddr);      releaseProcess(newProcess);      return (status);    }  // Get the new virtual address of supervisor stack  if (!require_ring0) // (newProcess->privilege == PRIVILEGE_USER)    newProcess->superStack = (newProcess->userStack + DEFAULT_STACK_SIZE);  // Create the TSS (Task State Segment) for this process.    status = createTaskStateSegment(newProcess, processPageDir);      if (status < 0)    {      // Not able to create the TSS      releaseProcess(newProcess);      return (status);    }  // Adjust the stack pointer to account for the arguments that we copied to  // the process' stack  // cast required! Davide Airaghi  ((kernelTSS *)(newProcess->taskStateSegment))->ESP -= sizeof(int);  // Set the EIP to the entry point  // cast required! Davide Airaghi  ((kernelTSS *)(newProcess->taskStateSegment))->EIP = (unsigned) execImage->entryPoint;  // Finally, add the process to the process queue  status = addProcessToQueue(newProcess);  if (status < 0)    {      // Not able to queue the process.      releaseProcess(newProcess);      return (status);    }  // Return the processId on success.  return (status = newProcess->processId);}static int deleteProcess(kernelProcess *killProcess){  // Does all the work of actually destroyng a process when there's really  // no more use for it.  This occurs after all descendent threads have  // terminated, for example.  int status = 0;  // Processes cannot delete themselves  if (killProcess == kernelCurrentProcess)    {      kernelError(kernel_error, "Process %d cannot delete itself",		  killProcess->processId);      return (status = ERR_INVALID);    }  // Remove the process from the multitasker's process queue.  status = removeProcessFromQueue(killProcess);  if (status < 0)    {      // Not able to remove the process      kernelError(kernel_error, "Can't dequeue process");      return (status);    }  // We need to deallocate the TSS descriptor allocated to the process, if  // it has one  if (killProcess->tssSelector)    {      status = kernelDescriptorRelease(killProcess->tssSelector);      // If this was unsuccessful, we don't want to continue and "lose"       // the descriptor      if (status < 0)	{	  kernelError(kernel_error, "Can't release TSS");	  return (status);	}    }  // Try to close all network connections owned by this process  status = kernelNetworkCloseAll(killProcess->processId);  if (status < 0)    kernelError(kernel_warn, "Can't release network connections");  // If the process has a signal stream, destroy it  if (killProcess->signalStream.buffer)    kernelStreamDestroy((stream *) &(killProcess->signalStream));  // Deallocate all memory owned by this process  status = kernelMemoryReleaseAllByProcId(killProcess->processId);  // Likewise, if this deallocation was unsuccessful, we don't want to  // deallocate the process structure.  If we did, the memory would become  // "lost".  if (status < 0)    {      kernelError(kernel_error, "Can't release process memory");      return (status);    }  // Delete the page table we created for this process  status = kernelPageDeleteDirectory(killProcess->processId);  // If this deletion was unsuccessful, we don't want to deallocate the   // process structure.  If we did, the page directory would become "lost".  if (status < 0)    {      kernelError(kernel_error, "Can't release page directory");      return (status);    }  // Finally, release the process structure  status = releaseProcess(killProcess);  if (status < 0)    {      kernelError(kernel_error, "Can't release process structure");      return (status);    }  return (status = 0);}static void idleThread(void){  // This is the idle task.  It runs in this loop whenever no other   // processes need the CPU.  However, the only thing it does inside  // that loop -- as you can probably see -- is run in a loop.  This should

⌨️ 快捷键说明

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