Lecture date: January 23, 2012
Scribes: Kevin Du and Andrew Law
send(fact_name, (m) {"!", 5}); a = get_response(fact_name); if(a.response_code == OK) print(a.val) else return ERROR;Server Code:
for(;;){ receive(fact_name, request); if(request.opcall == "!"){ n=request.val; //compute n! response = (m) {OK, n!} } else response = (m) {NG, "0"}; send(fact_name, reponse); }Pros and cons:
Create a virtual machine to run your untrusted code:
Write an x86 emulator
int emul(int start_ip) { int ip; char ins = mem[ip++]; // handwaving code switch(decode(ins)) case POP: } r=emul(fact's code address) switch(r) { case STACK_OVERFLOW: case TOO_MANY_INSNS: case OK: get return value of fact; }Pros and cons:
What we need:
halt, inb, outb
).This is only possible with architecture that supports this (i.e. a virtualizable processor).
normal computation
a=b*b-c*c;
system call
write(1,"hello, world\n", 13); //no inb, outb here
This is implemented via a system crash by convention.
The INT
instruction is an example of a system call that would accomplish this.
x86
1 byte (if this is 128, it's a system call).
example:
%eax system call # %ebx arg1 %ecx arg2 %edx arg3 %esi arg4 %edi arg5 %ebp arg6
This runs in the virtual machine:
ssize_t write(int fd, char const * buf, size_t bufsize) { ... asm("int 128"); ... }
INT 128
This causes a hardware trap and pushes the following onto the real machine's stack:
RETI is the instruction for return from interrupt.
Virtualization is faster than the client and server approach.
OS organization:
The kernel keeps track of the ALU, registers, RAM and I/O registers.
Beyond this, there can be multiple layers of abstraction.
On a single-core machine, at most 1 process can run at a time.
Registers don't always have to be saved as in this case:
n=getpid();
halt
.exit(23)
can be called. 23
, is an 8 bit code and the kernel stores the exit status in the PID table.To Create:
p=fork();This clones the current process with the following exceptions:
- the parent's p = the child's PID
- the child's p = 0.
- the child's p = -1 if there is an error.
pid_t waitpid(pid_t p, int * status, int options) { int i; q=waitpid(p,&i,0); }p is the PID and &i is the exit status returned.