Operating systems

Introduction

Prashanth L.A.

2023-08-01

Lecture 1 starts here

Von Neumann model of computing

What does an OS do?

OS as a resource manager

OS concepts

Virtualization

A couple of questions

On virtualizing CPU

First program

#include <stdio.h>
#include <stdlib.h>
#include "common.h"

int main(int argc, char *argv[])
{
    if (argc != 2) {
    fprintf(stderr, "usage: cpu <string>\n");
    exit(1);
    }
    char *str = argv[1];

    while (1) {
    printf("%s\n", str);
    Spin(1);
    }
    return 0;
}

What happens when we run this program

prompt> gcc -o cpu cpu.c -Wall
prompt> ./cpu "A"
A
A
A
ˆC
prompt>

Another run of the same program

prompt> ./cpu A & ; ./cpu B & ; ./cpu C & ; ./cpu D &
[1] 7353
[2] 7354
[3] 7355
[4] 7356
A
B
D
C
A
B
D
C
A
C
B
D
...

Some thoughts on virtualizing CPU

Question: If two programs run want to run at the same time, which should run?

On virtualizing memory

A simple model for memory

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include "common.h"

int main(int argc, char *argv[]) {
    if (argc != 2) { 
    fprintf(stderr, "usage: mem <value>\n"); 
    exit(1); 
    } 
    int *p; 
    p = malloc(sizeof(int));
    assert(p != NULL);
    printf("(%d) addr pointed to by p: %p\n", (int) getpid(), p);
    *p = atoi(argv[1]); // assign value to addr stored in p
    while (1) {
    Spin(1);
    *p = *p + 1;
    printf("(%d) value of p: %d\n", getpid(), *p);
    }
    return 0;
}

What happens when we run this program

prompt> ./mem
(2134) memory address of p: 00200000
(2134) p: 1
(2134) p: 2
(2134) p: 3
(2134) p: 4
(2134) p: 5
ˆC

How about running it again and again

prompt> ./mem &; ./mem &
[1] 24113
[2] 24114
(24113) memory address of p: 00200000
(24114) memory address of p: 00200000
(24113) p: 1
(24114) p: 1
(24114) p: 2
(24113) p: 2
(24113) p: 3
(24114) p: 3
...

Both programs allocated the same address, and each program updates this location

Some thoughts on virtualizing memory

Physical memory is a shared resource, managed by the OS

Lecture 2 starts here

Concurrency

The problem of concurrent access

Third program (Concurrency)

#include <stdio.h>
#include <stdlib.h>
#include "common.h"
#include "common_threads.h"

volatile int counter = 0; 
int loops;

void *worker(void *arg) {
    int i;
    for (i = 0; i < loops; i++) {
    counter++;
    }
    return NULL;
}

Third program (contd)

int main(int argc, char *argv[]) {
    if (argc != 2) { 
    fprintf(stderr, "usage: threads <loops>\n"); 
    exit(1); 
    } 
    loops = atoi(argv[1]);
    pthread_t p1, p2;
    printf("Initial value : %d\n", counter);
    Pthread_create(&p1, NULL, worker, NULL); 
    Pthread_create(&p2, NULL, worker, NULL);
    Pthread_join(p1, NULL);
    Pthread_join(p2, NULL);
    printf("Final value   : %d\n", counter);
    return 0;
}

Understanding the concurrency problem

Running this program

prompt> gcc -o thread thread.c -Wall -pthread 
prompt> ./thread 1000
Initial value : 0
Final value : 2000

Another run

prompt> ./thread 100000
Initial value : 0
Final value   : 143012 // huh??
prompt> ./thread 100000
Initial value : 0
Final value   : 137298 // what the??

Why is the output not as expected?

Concurrency problem

These three instructions do not execute atomically

Persistence

How to persist?

Why not create a private, virtualized disk for each application?

Lecture 3 starts here

Fourth program that does some I/O

#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>

int main(int argc, char *argv[]) {
    int fd = open("/tmp/file", O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
    assert(fd >= 0);
    char buffer[20];
    sprintf(buffer, "hello world\n");
    int rc = write(fd, buffer, strlen(buffer));
    assert(rc == (strlen(buffer)));
    fsync(fd);
    close(fd);
    return 0;
}

Persistence

Questions to an OS designer

Design goals