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

📄 kernelpage.c

📁 上一个上传的有问题,这个是好的。visopsys包括系统内核和GUI的全部SOURCE code ,还包括一些基本的docs文档。里面src子目录对应所有SOURCE code.对于想研究操作系统的朋
💻 C
📖 第 1 页 / 共 4 页
字号:
  // Grab the value from the page table  *entry = (void *) (table->virtual->page[pageNumber] & 0xFFFFF000);  return (status = 0);}static inline int getNumPages(unsigned size){  // Turn a size into a number of pages  return ((size / MEMORY_PAGE_SIZE) + ((size % MEMORY_PAGE_SIZE) != 0));}static int areFreePagesAt(kernelPageDirectory *directory, int pages,			  void *virtualAddress,int kernel) // lst param by Davide Airaghi{  // This function will return 1 if the requested number of pages are unused  // at the requested address in the supplied page directory.  int numberFree = 0;  kernelPageTable *table = NULL;  int tableNumber = 0;  int maxTableNumber = 0;  int pageNumber = 0;  if (directory == kernelPageDir)    maxTableNumber = PAGE_TABLES_PER_DIR;  else    maxTableNumber = (getTableNumber(KERNEL_VIRTUAL_ADDRESS) - 1);  tableNumber = getTableNumber(virtualAddress);  pageNumber = getPageNumber(virtualAddress);  // Loop through the supplied page directory.  for ( ; tableNumber < maxTableNumber; tableNumber++)    {      // Get a pointer to this page table.      table = findPageTable(directory, tableNumber);      if (table == NULL)	{	  // Create the page table	  table = createPageTable(directory, tableNumber,kernel);	  if (table == NULL)	    return (0);	}            // Loop through the pages in this page table.  If we find a used      // page before 'numberFree' equals 'pages', return 0      for ( ; pageNumber < PAGE_PAGES_PER_TABLE; pageNumber++)	{	  if (table->virtual->page[pageNumber] != NULL)	    return (0);	  numberFree++;	  if (numberFree >= pages)	    return (1);	}      // If we fall through, we're moving on to the next page table.      pageNumber = 0;    }  // If we fall through, we're out of range  return (0);}static int map(kernelPageDirectory *directory, void *physicalAddress, 	       void **virtualAddress, unsigned size, int flags, int kernel) // last by Davide Airaghi{  // This function is used by the rest of the kernel to map physical memory  // pages in the address space of a process.  This will map the physical  // memory to the first range of the process' unused pages that is large  // enough to handle the request.  By default, it will make all pages that  // it maps writable.  int status = 0;  kernelPageTable *pageTable = NULL;  void *currentVirtualAddress = NULL;  void *currentPhysicalAddress = NULL;  int tableNumber = 0;  unsigned pageNumber = 0;  unsigned numPages = 0;    // Make sure that our arguments are reasonable.  The wrapper functions  // that are used to call us from external locations do not check them.  if (size == 0)    return (status = ERR_INVALID);  // Make sure the pointer to virtualAddress is not NULL  if (virtualAddress == NULL)    return (status = ERR_NULLPARAMETER);  if ((unsigned) physicalAddress % MEMORY_PAGE_SIZE)    return (status = ERR_ALIGN);  // Determine how many pages we need to map  numPages = getNumPages(size);  if (flags == PAGE_MAP_ANY)    {      // Are there enough free pages in this page directory (plus 1 for      // the next page table)?  If not, add more page tables until we have      // enough.      while (((numPages + 1) >= countFreePages(directory)) ||	     (findFreePages(directory, numPages, virtualAddress) < 0))	{	  if (createPageTable(directory,			      findFreeTableNumber(directory),kernel) == NULL) //modified by Davide Airaghi	    return (status = ERR_NOFREE);	}    }  else if (flags == PAGE_MAP_EXACT)    {      if ((unsigned) *virtualAddress % MEMORY_PAGE_SIZE)	return (status = ERR_ALIGN);      if (!areFreePagesAt(directory, numPages, *virtualAddress,kernel)) // last by Davide Airaghi	return (status = ERR_NOFREE);      // Make sure there's enough for the next page table      if ((numPages + 1) >= countFreePages(directory))	{	  if (createPageTable(directory,			      findFreeTableNumber(directory),kernel) == NULL) // modified by Davide Airaghi	    return (status = ERR_NOFREE);	  if (!areFreePagesAt(directory, numPages, *virtualAddress,kernel)) // modified by Davide Airaghi	    return (status = ERR_NOFREE);	}    }  else    return (status = ERR_INVALID);      currentPhysicalAddress = physicalAddress;  currentVirtualAddress = *virtualAddress;  // Change the entries in the page table  while (numPages > 0)    {      pageNumber = getPageNumber(currentVirtualAddress);      if ((pageTable == NULL) || (pageNumber == 0))	{	  // Get the address of the page table.  Figure out the page table	  // number based on the virtual address we're currently working with,	  // and get the page table.	  tableNumber = getTableNumber(currentVirtualAddress);	  pageTable = findPageTable(directory, tableNumber);	  if (pageTable == NULL)	    // We're hosed.  This table should already exist.	    return (status = ERR_NOSUCHENTRY);	}      // Put the real address into the page table entry.  Set the      // writable bit and the page present bit.      pageTable->virtual->page[pageNumber] =	(unsigned) currentPhysicalAddress;      pageTable->virtual->page[pageNumber] |=	(PAGEFLAG_WRITABLE | PAGEFLAG_PRESENT);      if (directory == kernelPageDir)	// Set the 'global' bit, so that if this is a Pentium Pro or better	// processor, the page table won't be invalidated during a context	// switch	pageTable->virtual->page[pageNumber] |= PAGEFLAG_GLOBAL;      // Set the 'user' bit, if this page is not privileged      if (directory->privilege != PRIVILEGE_SUPERVISOR || (kernel == 0)) // last cond by DAvide Airaghi	pageTable->virtual->page[pageNumber] |= PAGEFLAG_USER;      // Decrease the count of free pages      pageTable->freePages--;      // Increment the working memory addresses      currentVirtualAddress += MEMORY_PAGE_SIZE;      currentPhysicalAddress += MEMORY_PAGE_SIZE;      // Decrement the number of pages left to map      numPages--;      // Loop again    }  // Return success  return (status = 0);}static int unmap(kernelPageDirectory *directory, void *virtualAddress,		 unsigned size){  // This function is used by the rest of the kernel to unmap virtual memory  // pages from the address space of a process.    int status = 0;  kernelPageTable *pageTable = NULL;  unsigned tableNumber = 0;  unsigned pageNumber = 0;  unsigned numPages = 0;  // Make sure that our arguments are reasonable.  The wrapper functions  // that are used to call us from external locations do not check them.  if (size == 0)    return (status = ERR_INVALID);  if (((unsigned) virtualAddress % MEMORY_PAGE_SIZE) != 0)    return (status = ERR_ALIGN);  // Determine how many pages we need to unmap  numPages = getNumPages(size);  // Change the entries in the page table  while (numPages > 0)    {      pageNumber = getPageNumber(virtualAddress);      if ((pageTable == NULL) || (pageNumber == 0))	{	  // Get the address of the page table.  Figure out the page table	  // number based on the virtual address we're currently working with,	  // and get the page table.	  tableNumber = getTableNumber(virtualAddress);	  pageTable = findPageTable(directory, tableNumber);	  if (pageTable == NULL)	    // We're hosed.  This table should already exist.	    return (status = ERR_NOSUCHENTRY);	}      // Clear out the physical address from the page table entry      pageTable->virtual->page[pageNumber] = NULL;      // Clear the TLB entry for this page      kernelProcessorClearAddressCache(virtualAddress);      // Increase the count of free pages      pageTable->freePages++;      // Is the table now unused?      if (pageTable->freePages == PAGE_PAGES_PER_TABLE)	// Try to deallocate it	deletePageTable(directory, pageTable);      // Increment the working memory addresses      virtualAddress += MEMORY_PAGE_SIZE;      // Decrement the number of pages left to map      numPages--;      // Loop again    }  // Return success  return (status = 0);}static kernelPageDirectory *createPageDirectory(int processId, int privilege, int kernel) // last by Davide Airaghi{  // This function creates an empty page directory by allocating physical  // memory for it, and on success, returns a pointer to a   // kernelPageDirectory holding information about the directory.  Returns  // NULL on error.  int status = 0;  kernelPageDirectory *directory = NULL;  kernelPageDirPhysicalMem *physicalAddr = NULL;  kernelPageDirVirtualMem *virtualAddr = NULL;  // Get some physical memory for the page directory  physicalAddr = (kernelPageDirPhysicalMem *)     kernelMemoryGetPhysical(sizeof(kernelPageDirPhysicalMem), MEMORY_PAGE_SIZE,			    "page directory");  if (physicalAddr == NULL)    return (directory = NULL);  // Map it into the kernel's virtual address space.  status = map(kernelPageDir, (void *) physicalAddr, (void **) &virtualAddr,	       sizeof(kernelPageDirPhysicalMem), PAGE_MAP_ANY, kernel); // last by Davide Airaghi  if (status < 0)    return (directory = NULL);  // Clear this memory block, since kernelMemoryGetPhysical can't do it for us  kernelMemClear((void *) virtualAddr, sizeof(kernelPageDirPhysicalMem));  // Put it in the next available kernelPageDirectory slot, and increase  // the count of kernelPageDirectories  directory = pageDirList[numberPageDirectories++];  kernelMemClear((void *) directory, sizeof(kernelPageDirectory));  // Fill in this page directory  directory->processId = processId;  directory->numberShares = 0;  directory->parent = 0;  // next by Davide Airaghi  directory->kernel = kernel;  directory->privilege = privilege;  directory->physical = physicalAddr;  directory->virtual = virtualAddr;  // Return the directory  return (directory);}static kernelPageDirectory *findPageDirectory(int processId){  // This function just finds the page directory structure that belongs  // to the requested process.  Returns NULL on failure.  kernelPageDirectory *dir = NULL;  int count;  if (processId == KERNELPROCID)    return (dir = kernelPageDir);  for (count = 0; count < numberPageDirectories; count ++)    if (pageDirList[count]->processId == processId)      {	// If this page directory is 'shared' from another page directory,	// then we need to recurse to find the parent (since this one will,	// essentially, be 'empty')		if (pageDirList[count]->parent)	  dir = findPageDirectory(pageDirList[count]->parent);	else	  dir = pageDirList[count];	break;      }  return (dir);}static int deletePageDirectory(kernelPageDirectory *directory){  // This function is for the maintenance of our dynamic list of  // page directory pointers.  It will remove the supplied page  // directory from the list and deallocate the memory that was  // reserved for the directory.  Returns 0 on success, negative  // otherwise.  int status = 0;  kernelPageDirectory *parent = NULL;  int listPosition = 0;  // Make sure this page directory isn't currently shared.  If it is,   // we can't delete it.  if (directory->numberShares)    return (status = ERR_BUSY);  // Figure out whether this page directory is 'sharing' from another  // page directory.  If so, we don't need to do much other than remove  // it from the list, and decrement the refcount in the parent  if (directory->parent)    {      // Find the parent page directory      parent = findPageDirectory(directory->parent);      if (parent == NULL)	return (status = ERR_NOSUCHENTRY);      parent->numberShares--;    }  else    {      // It's a 'real' page table.  Deallocate the dynamic memory that      // this directory is occupying      kernelMemoryReleasePhysical((void *) directory->physical);      // Unmap the directory from kernel memory      status = unmap(kernelPageDir, (void *) directory->virtual,		     sizeof(kernelPageDirVirtualMem));      if (status < 0)	return (status);    }  // Now we need to remove it from the list.  First find its position  // in the list.  for (listPosition = 0; listPosition < numberPageDirectories; )    if (pageDirList[listPosition] == directory)      break;    else      listPosition++;  if ((listPosition == numberPageDirectories) ||       (pageDirList[listPosition] != directory))    return (status = ERR_NOSUCHENTRY);  // This list is the same as several other lists in the kernel.  We remove  // this pointer from the list by swapping its pointer in the list with  // that of the last item in the list and decrementing the count  // (UNLESS: this is the last one, or the only one).  // Decrement the count of page directories BEFORE the following operation  numberPageDirectories--;  if ((numberPageDirectories > 0) && (listPosition < numberPageDirectories))    {      // Swap this item with the last item      pageDirList[listPosition] = pageDirList[numberPageDirectories];      pageDirList[numberPageDirectories] = directory;    }  // Return success  return (status = 0);}static int firstPageDirectory(void){  // This will create the first page directory, specifically for the  // kernel.  This presents some special problems, since we don't want  // to map it into the current, temporary page directory set up by  // the loader.  We have to do this one manually.  Returns a pointer  // to the directory on success, NULL on failure.

⌨️ 快捷键说明

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