What API does the OS provide to the user programs?
- API = Application Programming Interface = functions available to write user programs
- API provided by OS is a set of “system calls”,
– A system call is a function call into OS code that runs at a higher privilege level of the CPU.
– Sensitive operations (e.g., access to hardware) are allowed only at a higher privilege level
– Some “blocking” system calls cause the process to be blocked and de scheduled (e.g., read from disk)
– A system call is a function call into OS code that runs at a higher privilege level of the CPU.
– Sensitive operations (e.g., access to hardware) are allowed only at a higher privilege level
– Some “blocking” system calls cause the process to be blocked and de scheduled (e.g., read from disk)
So, should we rewrite programs for each OS?
- POSIX API: a standard set of system calls that an OS must implement
– Programs written to the POSIX API can run on any POSIX compliant OS
– Most modern OSes are POSIX compliant
– Ensures program portability
- Program language libraries hide the details of invoking system calls
– The printf function in the C library calls the writing system call to write to the screen
– User programs usually do not need to worry about invoking system calls
– Programs written to the POSIX API can run on any POSIX compliant OS
– Most modern OSes are POSIX compliant
– Ensures program portability
– The printf function in the C library calls the writing system call to write to the screen
– User programs usually do not need to worry about invoking system calls
Process related system calls (in Unix)
- fork() creates a new child process
– All processes are created by forking from a parent
– The init process is the ancestor of all processes
- exec() makes a process execute a given executable
- exit() terminates a process
- wait() causes a parent to block until the child terminates
- Many variants exist of the above system calls with different arguments
– All processes are created by forking from a parent
– The init process is the ancestor of all processes
What happens during a fork?
- A new process is created by making a copy of parent’s memory image
- The new process is added to the OS process list and scheduled
- Parent and child start the execution just after the fork (with different return values)
- Parent and child execute and modify the memory data independently
#include #include #include int main(int argc,char *argv[]){
printf("helloworld(pid:%d)\n",(int)getpid());
int rc=fork();
if(rc<0 br="" failed="" fork="" fprintf="" n="" stderr=""> exit(1);}else
if(rc==0) { 0> int rc=fork(); if(rc<0 br="" failed="" fork="" fprintf="" n="" stderr=""> exit(1);}else
if(rc==0) { 0> if(rc==0) { printf("hello, I am child (pid:%d)\n",(int)getpid()); }else{ printf("hello,I am parent of %d (pid:%d)\n",rc,(int)getpid());} return 0; }
if(rc==0) { 0>
Waiting for children to die…
- Process termination scenarios
– By calling exit() (exit is called automatically when end of main is reached)
– OS terminates a misbehaving process
- Terminated process exists as a zombie
- When a parent calls wait(), zombie child is cleaned up or “reaped”
- wait() blocks in parent until child terminates (non-blocking ways to invoke wait exist)
- What if parent terminates before child? init process adopts orphans and reaps them
– By calling exit() (exit is called automatically when end of main is reached)
– OS terminates a misbehaving process