Operating Systems 2019F Lecture 3
Video
Video from the lecture given on Sept. 11, 2019 is now available.
Topics
- supervisor and user mode
- system calls
- process abstraction
Notes
Lecture 3 --------- To understand system calls, we have to be able to differentiate between function calls and system calls. Function call * saver current instruction pointer to stack * jump to a memory location (load into current instruction register) Function call return * pop instruction pointer from stack * jump to value (load it into current instruction register) CPUs have registers * mostly used for manipulating data * but some store special values (some) Special registers * the instruction pointer, which contains the address of the currently executing instruction key operating system code *cannot* be seen by regular programs - they can't even get a pointer to that code this key part of the operating system is called the "kernel" My apologies for the lack of sound! the kernel has control over all hardware, all resources - processes have to ask the kernel for access to resources And a process can't ask using a function call, because it can't jump to the code in the kernel So we have to execute a special instruction that causes the kernel to be invoked - without this, the process code is completely isolated - can't access files, network, keyboard, etc Those special instructions cause the CPU to do some interesting things, which we will talk about later Key system calls ---------------- The big ones are the ones for files * open * close * read * write ...and a few others From your program's perspective, the world is the process: that's your "cpu", that's your memory for storing all code and data system calls are special instructions * note you can't make system calls with pure C, has to use assembly at some point System calls for creating a process: * fork (clone) But all fork does is duplicate the current process System call for loading a program binary: * execve Execve replaces the code in the process with the code from the specified file (throwing out all the old code and data, and only loading the data passed as command-line arguments and environment variables).
Code
fork-demo.c
#include <unistd.h>
#include <stdio.h>
int main(int argc, char *argv) {
pid_t pid;
pid = fork();
if (pid == 0) {
printf("First branch, pid = %d\n", (int) pid);
} else {
printf("Second branch, pid = %d\n", (int) pid);
}
printf("%d: After the check\n", getpid());
return 0;
}
execve-demo.c
#include <unistd.h>
#include <stdio.h>
int main(int argc, char *argv[], char *envp[]) {
execve("/bin/ls", argv, envp);
printf("All done!\n");
return 0;
}
fork-execve-demo.c
#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>
int main(int argc, char *argv[], char *envp[]) {
pid_t pid;
pid = fork();
if (pid == 0) {
printf("Child, pid = %d, doing execve\n", getpid());
execve("/bin/ls", argv, envp);
} else {
printf("Parent, pid = %d, will wait for child.\n",
getpid());
/* wait(NULL); */
sleep(600);
printf("%d: Child %d finished!\n",
getpid(), (int) pid);
}
printf("Both parent and child could have run this "
"but it was run by %d\n", getpid());
return 0;
}