private: int spaceID; static BitMap* userMap, pidMap;
addrspace.cc :
#define Max_UserProcess 256
BitMap* AddrSpace::userMap = new BitMap(NumPhysPages); BitMap* AddrSpace::pidMap = new BitMap(Max_UserProcess);
intAddrSpace::getSpaceId(){ return spaceID; }
AddrSpace::AddrSpace(OpenFile *executable) { spaceID = pidMap->Find()+100; // find a pid for the process // ........... }
AddrSpace::~AddrSpace() { pidMap->Clear(spaceID-100); // remember to remove it for (int i = 0; i < numPages; i++) { userMap->Clear(pageTable[i].physicalPage); } delete [] pageTable; }
To test whether the space id works, print the pid in StartProcess :
The main process with PID = 100, executes exit.noff and halt.noff, then exits with code 0; while the exit.noff gets it PID = 101, exits with code 1, and the halt.noff with PID = 102 halts.
So there is a little problem: the father process won’t wait until its child process exits. That’s what Join does.
Join()
This is similar to pthread_join(tid) in Linux, waiting for a process then it continues.
Here is how it works:
The child process is in a waiting queue.
Join() sleeps the current process.
Get a process from waiting queue, give it CPU.
After it ends, Finish it, then wake up father process.
--------[SC_Exec] PID: 100 filename: ../test/exit.noff-------- Initializing code segment, at 0x580, size 256 --------[SC_Yield] PID: 100-------- --------[SC_Exit] PID: 101 exit_code: 1-------- --------[SC_Exit] PID: 100 exit_code: 0-------- No threads ready or runnable, and no pending interrupts. Assuming the program completed. Machine halting!
First, exec, then yield, then the child exits. At last it exits.
File Operation
Create()
Obviously, create need to read a filename, then create an empty file:
elseif (type == SC_Create) { int address = machine->ReadRegister(4); char filename[128]; for(int i = 0; i < 128; i++) { machine->ReadMem(address+i, 1, (int *)&filename[i]); if (filename[i] == '\0') break; } printf("--------[SC_Create] PID: %d, filename: %s--------\n", (currentThread->space)->getSpaceId(), filename); int fileDescriptor = OpenForWrite(filename); if (fileDescriptor == -1) printf("create file %s failed!\n", filename); else printf("create file %s succeed!, the file id is %d\n", filename, fileDescriptor); Close(fileDescriptor); //machine->WriteRegister(2,fileDescriptor); advancePC(); }
Open()
It opens a file, then returns the file id(write to register 2 for future use):
elseif (type == SC_Open) { int address = machine->ReadRegister(4); char filename[128]; for (int i = 0; i < 128; i++) { machine->ReadMem(address+i, 1, (int *)&filename[i]); if (filename[i] == '\0') break; } printf("--------[SC_Open] PID: %d, filename: %s--------\n", (currentThread->space)->getSpaceId(), filename); int fileDescriptor = OpenForWrite(filename); if (fileDescriptor == -1) printf("open file %s failed!\n", filename); else printf("open file %s succeed!, the file id is %d\n", filename, fileDescriptor); machine->WriteRegister(2, fileDescriptor); advancePC(); }
Write()
/* Write "size" bytes from "buffer" to the open file. */ voidWrite(char *buffer, intsize, OpenFileId id);
3 arguments, obviously.
elseif (type == SC_Write) { int address = machine->ReadRegister(4); int bufsize = machine->ReadRegister(5); int fileID = machine->ReadRegister(6); printf("--------[SC_Write] PID: %d, fileid: %d, buffer address: %d with size=%d--------\n", (currentThread->space)->getSpaceId(), fileID, address, bufsize); OpenFile* openfile = new OpenFile(fileID); ASSERT(openfile != NULL);
charbuffer[128]; for (int i = 0; i < bufsize; i++) { machine->ReadMem(address+i, 1, (int *)&buffer[i]); } buffer[bufsize] = '\0'; printf("the buffer is %s\n", buffer);
int WritePosition; if (fileID == 1) WritePosition = 0; else WritePosition = openfile->Length(); int writtenBytes = openfile->WriteAt(buffer, bufsize, WritePosition); if ((writtenBytes) == 0) printf("Writing file failed!\n"); else printf("\"%s\" has been written in file %d successfully!\n", buffer, fileID); advancePC(); }
Read()
/* Read "size" bytes from the open file into "buffer". * Return the number of bytes actually read -- if the open file isn't long enough, or if it is an I/O device, and there aren't enough characters to read, return whatever is available (for I/O devices, you should always wait until you can return at least one character). */ intRead(char *buffer, intsize, OpenFileId id);
Similar to write() :
elseif (type == SC_Read) { int address = machine->ReadRegister(4); int bufsize = machine->ReadRegister(5); int fileID = machine->ReadRegister(6); printf("--------[SC_Read] PID: %d, fileid: %d, buffer address: %d with size=%d--------\n", (currentThread->space)->getSpaceId(), fileID, address, bufsize); OpenFile* openfile = new OpenFile(fileID); ASSERT(openfile != NULL); charbuffer[128]; int readnum = openfile->Read(buffer, bufsize);
for (int i = 0; i < bufsize; i++) { if (!machine->WriteMem(address, 1, buffer[i])) printf("There is something wrong.\n"); } buffer[bufsize] = '\0'; printf("Read successfully! The content is \"%s\" , length = %d\n", buffer, bufsize); machine->WriteRegister(2, readnum); advancePC(); }
Close()
/* Close the file, we're done reading and writing to it. */ voidClose(OpenFileId id);
--------[SC_Create] PID: 100, filename: Test-------- create file Test succeed!, the file id is 3 --------[SC_Open] PID: 100, filename: Test-------- open file Test succeed!, the file id is 3 --------[SC_Write] PID: 100, fileid: 3, buffer address: 360 with size=15-------- the buffer is something to te "something to te" has been written in file 3 successfully! --------[SC_Read] PID: 100, fileid: 3, buffer address: 1320 with size=10-------- Read successfully! The content is "something " , length = 10 --------[SC_Close] PID: 100, fileid: 3-------- Close file[3] successfully! --------[SC_Exit] PID: 100 exit_code: 0-------- No threads ready or runnable, and no pending interrupts. Assuming the program completed. Machine halting!