Пример #1
0
  /**
   * Transfer data from the specified array to this process's virtual memory. This method handles
   * address translation details. This method must <i>not</i> destroy the current process if an
   * error occurs, but instead should return the number of bytes successfully copied (or zero if no
   * data could be copied).
   *
   * @param vaddr the first byte of virtual memory to write.
   * @param data the array containing the data to transfer.
   * @param offset the first byte to transfer from the array.
   * @param length the number of bytes to transfer from the array to virtual memory.
   * @return the number of bytes successfully transferred.
   */
  public int writeVirtualMemory(int vaddr, byte[] data, int offset, int length) {
    Lib.assertTrue(offset >= 0 && length >= 0 && offset + length <= data.length);

    byte[] memory = Machine.processor().getMemory();

    int transferred = 0;
    while (length > 0 && offset < data.length) {
      int addrOffset = vaddr % 1024;
      int virtualPage = vaddr / 1024;

      if (virtualPage >= pageTable.length || virtualPage < 0) {
        break;
      }

      TranslationEntry pte = pageTable[virtualPage];
      if (!pte.valid || pte.readOnly) {
        break;
      }
      pte.used = true;
      pte.dirty = true;

      int physPage = pte.ppn;
      int physAddr = physPage * 1024 + addrOffset;

      int transferLength = Math.min(data.length - offset, Math.min(length, 1024 - addrOffset));
      System.arraycopy(data, offset, memory, physAddr, transferLength);
      vaddr += transferLength;
      offset += transferLength;
      length -= transferLength;
      transferred += transferLength;
    }

    return transferred;
  }
Пример #2
0
  /**
   * Read a null-terminated string from this process's virtual memory. Read at most <tt>maxLength +
   * 1</tt> bytes from the specified address, search for the null terminator, and convert it to a
   * <tt>java.lang.String</tt>, without including the null terminator. If no null terminator is
   * found, returns <tt>null</tt>.
   *
   * @param vaddr the starting virtual address of the null-terminated string.
   * @param maxLength the maximum number of characters in the string, not including the null
   *     terminator.
   * @return the string read, or <tt>null</tt> if no null terminator was found.
   */
  public String readVirtualMemoryString(int vaddr, int maxLength) {
    Lib.assertTrue(maxLength >= 0);

    byte[] bytes = new byte[maxLength + 1];

    int bytesRead = readVirtualMemory(vaddr, bytes);

    for (int length = 0; length < bytesRead; length++) {
      if (bytes[length] == 0) return new String(bytes, 0, length);
    }

    return null;
  }
Пример #3
0
  /**
   * Load the executable with the specified name into this process, and prepare to pass it the
   * specified arguments. Opens the executable, reads its header information, and copies sections
   * and arguments into this process's virtual memory.
   *
   * @param name the name of the file containing the executable.
   * @param args the arguments to pass to the executable.
   * @return <tt>true</tt> if the executable was successfully loaded.
   */
  private boolean load(String name, String[] args) {
    Lib.debug(dbgProcess, "UserProcess.load(\"" + name + "\")");

    OpenFile executable = ThreadedKernel.fileSystem.open(name, false);
    if (executable == null) {
      Lib.debug(dbgProcess, "\topen failed");
      return false;
    }

    try {
      coff = new Coff(executable);
    } catch (EOFException e) {
      executable.close();
      Lib.debug(dbgProcess, "\tcoff load failed");
      return false;
    }

    // make sure the sections are contiguous and start at page 0
    numPages = 0;
    for (int s = 0; s < coff.getNumSections(); s++) {
      CoffSection section = coff.getSection(s);
      if (section.getFirstVPN() != numPages) {
        coff.close();
        Lib.debug(dbgProcess, "\tfragmented executable");
        return false;
      }
      numPages += section.getLength();
    }

    // make sure the argv array will fit in one page
    byte[][] argv = new byte[args.length][];
    int argsSize = 0;
    for (int i = 0; i < args.length; i++) {
      argv[i] = args[i].getBytes();
      // 4 bytes for argv[] pointer; then string plus one for null byte
      argsSize += 4 + argv[i].length + 1;
    }
    if (argsSize > pageSize) {
      coff.close();
      Lib.debug(dbgProcess, "\targuments too long");
      return false;
    }

    // program counter initially points at the program entry point
    initialPC = coff.getEntryPoint();

    // next comes the stack; stack pointer initially points to top of it
    numPages += stackPages;
    initialSP = numPages * pageSize;

    // and finally reserve 1 page for arguments
    numPages++;

    if (!loadSections()) return false;

    // store arguments in last page
    int entryOffset = (numPages - 1) * pageSize;
    int stringOffset = entryOffset + args.length * 4;

    this.argc = args.length;
    this.argv = entryOffset;

    for (int i = 0; i < argv.length; i++) {
      byte[] stringOffsetBytes = Lib.bytesFromInt(stringOffset);
      Lib.assertTrue(writeVirtualMemory(entryOffset, stringOffsetBytes) == 4);
      entryOffset += 4;
      Lib.assertTrue(writeVirtualMemory(stringOffset, argv[i]) == argv[i].length);
      stringOffset += argv[i].length;
      Lib.assertTrue(writeVirtualMemory(stringOffset, new byte[] {0}) == 1);
      stringOffset += 1;
    }

    return true;
  }