Operating Systems 2019F Lecture 3: Difference between revisions

From Soma-notes
No edit summary
 
Line 78: Line 78:


==Code==
==Code==
===fork-demo.c===
<source lang="c" line>
#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;
}
</source>
===execve-demo.c===
<source lang="c" line>
#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;
}
</source>
===fork-execve-demo.c===
<source lang="c" line>
#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;
}
</source>

Latest revision as of 02:06, 12 September 2019

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;
}