51
1 CENG334 Introduction to Operating Systems Erol Sahin Dept of Computer Eng. Middle East Technical University Ankara, TURKEY URL: http://kovan.ceng.metu.edu.tr/~erol/Courses/CENG334 Processes Topics Processes Context switching Some of the following slides are adapted from Matt Welsh, Harvard Univ.

CENG334 Introduction to Operating Systems

  • Upload
    sitara

  • View
    31

  • Download
    0

Embed Size (px)

DESCRIPTION

Erol Sahin Dept of Computer Eng. Middle East Technical University Ankara, TURKEY. URL: http://kovan.ceng.metu.edu.tr/~erol/Courses/CENG334. Processes Topics Processes Context switching. CENG334 Introduction to Operating Systems. - PowerPoint PPT Presentation

Citation preview

Page 1: CENG334 Introduction to Operating Systems

1

CENG334Introduction to Operating Systems

Erol Sahin

Dept of Computer Eng.Middle East Technical University

Ankara, TURKEY

URL: http://kovan.ceng.metu.edu.tr/~erol/Courses/CENG334

Processes Topics•Processes•Context switching

Some of the following slides are adapted from Matt Welsh, Harvard Univ.

Page 2: CENG334 Introduction to Operating Systems

2

Process ManagementThis lecture begins a series of topics on

Processes Threads Synchronization

Probably the most important part of the class! Definitely will be questions on this on the midterm and final

Today: Processes and process management What are the units of execution inside of an OS? How are they implemented inside of the OS? What are the possible execution states of a process? How does the OS switch between processes?

Page 3: CENG334 Introduction to Operating Systems

3

What is a process? A process is the OS's abstraction for execution

A process represents a single running application on the system

Process has three main components:

1) Address space The memory that the process can access Consists of various pieces: the program code, static variables, heap, stack, etc.

2) Processor state The CPU registers associated with the running process Includes general purpose registers, program counter, stack pointer, etc.

3) OS resources Various OS state associated with the process Examples: open files, network sockets, etc.

Page 4: CENG334 Introduction to Operating Systems

4

Process Address Space

The range of virtual memory addresses that the process can access Includes the code of the running program The data of the running program (static variables and heap) An execution stack

Local variables and saved registers for each procedure call

Stack

Heap

Initialized vars(data

segment)Code(text segment)

Address space

0x00000000

0xFFFFFFFF

Stack pointer

Program counter

Uninitialized vars

(BSS segment)

(Reserved for OS)

Page 5: CENG334 Introduction to Operating Systems

5

Process Address Space

Stack

Heap

Initialized vars(data

segment)Code(text segment)

Address space

0x00000000

0xFFFFFFFF

Stack pointer

Program counter

Uninitialized vars

(BSS segment)

(Reserved for OS)

Note!!! This is the process's own view of the address space ---physical memory may not be laid out this way at all.

In fact, on systems that support multiple running processes, it's pretty muchguaranteed to look different.

The virtual memory system provides this illusion to each process.

Page 6: CENG334 Introduction to Operating Systems

6

Execution State of a Process Each process has an execution state

Indicates what the process is currently doing

Running: Process is currently using the CPU

Ready: Currently waiting to be assigned to a CPU That is, the process could be running, but another process is using the CPU

Waiting (or sleeping): Process is waiting for an event Such as completion of an I/O, a timer to go off, etc. Why is this different than “ready” ?

As the process executes, it moves between these states What state is the process in most of the time?

Page 7: CENG334 Introduction to Operating Systems

7

Process State Transitions

What causes schedule and unschedule transitions?

New

Terminated

Ready

Running

Waiting

create

kill or exit I/O, page fault,

etc.

I/O done

scheduleunschedule

Page 8: CENG334 Introduction to Operating Systems

8

Process Control Block OS maintains a Process Control Block (PCB) for each process

The PCB is a big data structure with many fields: Process ID User ID Execution state

ready, running, or waiting Saved CPU state

CPU registers saved the last time the process was suspended. OS resources

Open files, network sockets, etc. Memory management info Scheduling priority

Give some processes higher priority than others Accounting information

Total CPU time, memory usage, etc.

Page 9: CENG334 Introduction to Operating Systems

9

struct task_struct {volatile long state;unsigned long flags;int sigpending;mm_segment_t addr_limit;struct exec_domain *exec_domain;volatile long need_resched;unsigned long ptrace;int lock_depth;unsigned int cpu;int prio, static_prio;struct list_head run_list;prio_array_t *array;unsigned long sleep_avg;unsigned long last_run;unsigned long policy;unsigned long cpus_allowed;unsigned int time_slice, first_time_slice;atomic_t usage;struct list_head tasks;struct list_head ptrace_children;struct list_head ptrace_list;struct mm_struct *mm, *active_mm;struct linux_binfmt *binfmt;int exit_code, exit_signal;int pdeath_signal; unsigned long personality;int did_exec:1;unsigned task_dumpable:1;pid_t pid;pid_t pgrp;pid_t tty_old_pgrp;pid_t session;pid_t tgid;int leader;struct task_struct *real_parent; struct task_struct *parent;struct list_head children;struct list_head sibling;struct task_struct *group_leader;struct pid_link pids[PIDTYPE_MAX];wait_queue_head_t wait_chldexit;struct completion *vfork_done;int *set_child_tid;int *clear_child_tid;unsigned long rt_priority;

s

Linux PCB Structure (task_struct)unsigned long it_real_value, it_prof_value, it_virt_value;unsigned long it_real_incr, it_prof_incr, it_virt_incr;struct timer_list real_timer;struct tms times;struct tms group_times;unsigned long start_time;long per_cpu_utime[NR_CPUS], per_cpu_stime[NR_CPUS];unsigned long min_flt, maj_flt, nswap, cmin_flt, cmaj_flt, cnswap;int swappable:1;uid_t uid,euid,suid,fsuid;gid_t gid,egid,sgid,fsgid;int ngroups;gid_tgroups[NGROUPS];kernel_cap_t cap_effective, cap_inheritable, cap_permitted;int keep_capabilities:1;struct user_struct *user;struct rlimit rlim[RLIM_NLIMITS];unsigned short used_math;char comm[16];int link_count, total_link_count;struct tty_struct *tty; unsigned int locks; struct sem_undo *semundo;struct sem_queue *semsleeping;struct thread_struct thread;struct fs_struct *fs;struct files_struct *files;struct namespace *namespace;struct signal_struct *signal;struct sighand_struct *sighand;sigset_t blocked, real_blocked;struct sigpending pending;unsigned long sas_ss_sp;size_t sas_ss_size;int (*notifier)(void *priv);void *notifier_data;sigset_t *notifier_mask;void *tux_info;void (*tux_exit)(void); u32 parent_exec_id; u32 self_exec_id;spinlock_t alloc_lock; spinlock_t switch_lock;void *journal_info;unsigned long ptrace_message;siginfo_t *last_siginfo; };

Execution state

Memory mgmt info

Process ID

Priority

User ID

Accounting info

CPU state

Open files

Page 10: CENG334 Introduction to Operating Systems

10

Context Switching The act of swapping a process state on or off the CPU is a context switch

PC

Registers

PC

Registers

PID 1342State: Running

PC

Registers

PID 4277State: Ready

PC

Registers

PID 8109State: Ready

Save current CPU state

Currently running process

Page 11: CENG334 Introduction to Operating Systems

11

Context Switching The act of swapping a process state on or off the CPU is a context switch

PC

Registers

PC

Registers

PID 1342State: Ready

PC

Registers

PID 4277State: Ready

PC

Registers

PID 8109State: Ready

Suspend process

Page 12: CENG334 Introduction to Operating Systems

12

Context Switching The act of swapping a process state on or off the CPU is a context switch

PC

Registers

PC

Registers

PID 1342State: Ready

PC

Registers

PID 4277State: Running

PC

Registers

PID 8109State: Ready

Restore CPU state of new processPick next process

PC

Registers

Page 13: CENG334 Introduction to Operating Systems

13

Context Switch Overhead Context switches are not cheap

Generally have a lot of CPU state to save and restore Also must update various flags in the PCB Picking the next process to run – scheduling – is also expensive

Context switch overhead in Linux 2.4.21 About 5.4 usec on a 2.4 GHz Pentium 4 This is equivalent to about 13,200 CPU cycles!

Not quite that many instructions since CPI > 1

Page 14: CENG334 Introduction to Operating Systems

14

Context Switching in Linux

Process A

time

Process A is happily running along...

Page 15: CENG334 Introduction to Operating Systems

15

Context Switching in Linux

Process A

time

Timer interrupt handler

1) Timer interrupt fires

2) PC saved on stackUserKernel

Page 16: CENG334 Introduction to Operating Systems

16

Context Switching in Linux

Process A

Timer interrupt handler

time

1) Timer interrupt fires

2) PC saved on stack

Scheduler

4) Call schedule() routine

3) Rest of CPU statesaved in PCB

UserKernel

Page 17: CENG334 Introduction to Operating Systems

17

Context Switching in Linux

Process A

Timer interrupt handler

time

1) Timer interrupt fires

2) PC saved on stack

Scheduler5) Decide next process to run

4) Call schedule() routine

3) Rest of CPU statesaved in PCB

Timer interrupthandler

6) Resume Process B(suspended withintimer interrupt handler!)

UserKernel

Process B

7) Return from interrupthandler – process CPUstate restored

Page 18: CENG334 Introduction to Operating Systems

18

State Queues The OS maintains a set of state queues for each process state

Separate queues for ready and waiting states Generally separate queues for each kind of waiting process

e.g., One queue for processes waiting for disk I/O Another queue for processes waiting for network I/O, etc.

PC

Registers

PID 4277State: Ready

PC

Registers

PID 4110State: Waiting

PC

Registers

PID 4002State: Waiting

PC

Registers

PID 4923State: Waiting

PC

Registers

PID 4391State: Ready

Ready queue

Disk I/O queue

Page 19: CENG334 Introduction to Operating Systems

19

State Queue Transitions PCBs move between these queues as their state changes

When scheduling a process, pop the head off of the ready queue When I/O has completed, move PCB from waiting queue to ready queue

PC

Registers

PID 4277State: Ready

PC

Registers

PID 4110State: Waiting

PC

Registers

PID 4002State: Waiting

PC

Registers

PID 4391State: Ready

PC

Registers

PID 4923State: Waiting

Ready queue

Disk I/O queue

PC

Registers

PID 4923State: Ready

Disk I/O completes

Page 20: CENG334 Introduction to Operating Systems

20

Process Creation One process can create, or fork, another process

The original process is the parent The new process is the child

What creates the first process in the system, and when?

Parent process defines resources and access rights of children Just like real life ... e.g., child process inherits parent's user ID

% pstree -p

init(1)-+-apmd(687) |-atd(847) |-crond(793) |-rxvt(2700)---bash(2702)---ooffice(2853) `-rxvt(2752)---bash(2754)

Page 21: CENG334 Introduction to Operating Systems

21

PC

Registers

PID 4110State: Ready

UNIX fork mechanism In UNIX, use the fork() system call to create a new process

This creates an exact duplicate of the parent process!! Creates and initializes a new PCB Creates a new address space Copies entire contents of parent's address space into the child Initializes CPU and OS resources to a copy of the parent's Places new PCB on ready queue

PC

Registers

PID 4109State: Running

PC

Registers

PID 4277State: Ready

PC

Registers

PID 4391State: Ready

Ready queue

Process calls fork()

PC

Registers

PID 4110State: ReadyCopy state

PC

Registers

PID 4110State: Ready

Add to end ofready queue

Page 22: CENG334 Introduction to Operating Systems

22

UNIX fork mechanism New child process starts running where fork() system call returns!

And has an exact copy of the parent's variables.

int main(int argc, char **argv) {int i;for (i = 0; i < 10; i++) { printf(“Process %d: value is %d\n”, getpid(), i); if (i == 5) { printf(“Process %d: About to do a fork...\n”, getpid()); int child_pid = fork(); }}

}

Page 23: CENG334 Introduction to Operating Systems

23

Output of sample program Process 4530: value is 0 Process 4530: value is 1 Process 4530: value is 2 Process 4530: value is 3 Process 4530: value is 4 Process 4530: value is 5 Process 4530: About to do a fork... Process 4531: value is 6 Process 4530: value is 6 Process 4530: value is 7 Process 4531: value is 7 Process 4530: value is 8 Process 4531: value is 8 Process 4530: value is 9 Process 4531: value is 9

Page 24: CENG334 Introduction to Operating Systems

24

Why have fork() at all? Why make a copy of the parent process?

Don't you usually want to start a new program instead?

Where might “cloning” the parent be useful?

Page 25: CENG334 Introduction to Operating Systems

25

Why have fork() at all? Why make a copy of the parent process?

Don't you usually want to start a new program instead?

Where might “cloning” the parent be useful? Web server – make a copy for each incoming connection Parallel processing – set up initial state, fork off multiple copies to do work

UNIX philosophy: System calls should be minimal. Don't overload system calls with extra functionality if it is not always needed. Better to provide a flexible set of simple primitives and let programmers

combine them in useful ways.

Page 26: CENG334 Introduction to Operating Systems

26

UNIX fork mechanism So, how do you tell the parent from the child?

Return value of fork() is zero in the child, or child's PID in the parent.

int main(int argc, char **argv) {int child_pid = fork();

if (child_pid == 0) { /* Running in the child process */

printf(“I am the child process with pid %d\n”, getpid()); /* ... Do stuff for child ... */} else {

/* Running in the parent process */ printf(“My child process is %d\n”, child_pid); /* ... Do stuff for parent ... */}

}

Page 27: CENG334 Introduction to Operating Systems

27

Waiting for children Child process runs “in parallel” with the parent

Use the wait() system call to cause parent to wait for it.

int main(int argc, char **argv) {int i, rv;for (i = 0; i < 10; i++) { printf(“Process %d: value is %d\n”, getpid(), i); if (i == 5) { printf(“Process %d: About to do a fork...\n”, getpid()); int child_pid = fork(); if (child_pid) wait(&rv); /* Only the parent waits here */ }}exit(1); /* Return the exit value to the parent process */

}

Page 28: CENG334 Introduction to Operating Systems

28

Output of program with wait() Process 11476: value is 0 Process 11476: value is 1 Process 11476: value is 2 Process 11476: value is 3 Process 11476: value is 4 Process 11476: value is 5 Process 11476: About to do a fork... Process 11477: value is 6 Process 11477: value is 7 Process 11477: value is 8 Process 11477: value is 9 Process 11476: value is 6 Process 11476: value is 7 Process 11476: value is 8 Process 11476: value is 9

Parent waits here...

Page 29: CENG334 Introduction to Operating Systems

29

Memory concerns So fork makes a copy of a process. What about memory usage?

Stack

Heap

Initialized vars(data

segment)Code(text segment)

Uninitialized vars

(BSS segment)

(Reserved for OS)

Parent

Stack

Heap

Initialized vars(data

segment)Code(text segment)

Uninitialized vars

(BSS segment)

(Reserved for OS)

Child #1Stack

Heap

Initialized vars(data

segment)Code(text segment)

Uninitialized vars

(BSS segment)

(Reserved for OS)

Child #2

Stack

Heap

Initialized vars(data

segment)Code(text segment)

Uninitialized vars

(BSS segment)

(Reserved for OS)

Child #3Stack

Heap

Initialized vars(data

segment)Code(text segment)

Uninitialized vars

(BSS segment)

(Reserved for OS)

Child #4Stack

Heap

Initialized vars(data

segment)Code(text segment)

Uninitialized vars

(BSS segment)

(Reserved for OS)

Child #5

Stack

Heap

Initialized vars(data

segment)Code(text segment)

Uninitialized vars

(BSS segment)

(Reserved for OS)

Child #6

Stack

Heap

Initialized vars(data

segment)Code(text segment)

Uninitialized vars

(BSS segment)

(Reserved for OS)

Child #7

Stack

Heap

Initialized vars(data

segment)Code(text segment)

Uninitialized vars

(BSS segment)

(Reserved for OS)

Child #8

Stack

Heap

Initialized vars(data

segment)Code(text segment)

Uninitialized vars

(BSS segment)

(Reserved for OS)

Child #10

Stack

Heap

Initialized vars(data

segment)Code(text segment)

Uninitialized vars

(BSS segment)

(Reserved for OS)

Child #9

Page 30: CENG334 Introduction to Operating Systems

30

Problematic?

Page 31: CENG334 Introduction to Operating Systems

31

Memory concerns OS aggressively tries to share memory between processes.

Especially processes that are fork()'d copies of each other

Copies of a parent process do not actually get a private copyof the address space...

... Though that is the illusion that each process gets. Instead, they share the same physical memory, until one of them makes a change.

The virtual memory system is behind these shenanigans. We will discuss this in much detail later in the course

Page 32: CENG334 Introduction to Operating Systems

32

fork() and execve() How do we start a new program, instead of just a copy of the old

program? Use the UNIX execve() system call

int execve(const char *filename, char *const argv [], char *const envp[]);

filename: name of executable file to run argv: Command line arguments envp: environment variable settings (e.g., $PATH, $HOME, etc.)

Page 33: CENG334 Introduction to Operating Systems

33

fork() and execve() execve() does not fork a new process!

Rather, it replaces the address space and CPU state of the current process Loads the new address space from the executable file and starts it from main() So, to start a new program, use fork() followed by execve()

Page 34: CENG334 Introduction to Operating Systems

34

Using fork and execint main(int argc, char **argv) {

int rv;if (fork()) { /* Parent process */ wait(&rv);} else { /* Child process */ char *newargs[3]; printf(“Hello, I am the child process.\n”); newargs[0] = “/bin/echo”; /* Convention! Not required!! */ newargs[1] = “some random string”; newargs[2] = NULL; /* Indicate end of args array */ if (execv(“/bin/echo”, newargs)) { printf(“warning: execve returned an error.\n”); exit(-1); } printf(“Child process should never get here\n”); exit(42);}

}

Page 35: CENG334 Introduction to Operating Systems

35

UNIX File Abstraction In UNIX, the file is the basic abstraction used for I/O

Used to access disks, CDs, DVDs, USB and serial devices, network sockets, even memory!

Page 36: CENG334 Introduction to Operating Systems

36

stdin, stdout, stderr In UNIX, every process has three “special” files already open:

standard input (stdin) – filehandle 0 standard output (stdout) – filehandle 1 standard error (stderr) – filehandle 2

By default, stdin and stdout are connected to the terminal device of the process.

Originally, terminals were physically connected to the computer by a serial line These days, we use “virtual terminals” using ssh

VT100 terminal

Page 37: CENG334 Introduction to Operating Systems

37

Filehandles A filehandle (a.k.a. file descriptor) is a reference to an open file.

The OS maintains a list of open files for each process. The filehandle is just an index into this list.

The OS maintains an internal struct file for each open file. The struct file includes the current position into the file. This indicates the offset that the next read() or write() operation will affect.

Page 38: CENG334 Introduction to Operating Systems

38

Filehandles Each instance of the open file has its own position.

Can read and write at different offsets into the file independently. Different processes can also open the same file at the same time.

Page 39: CENG334 Introduction to Operating Systems

39

Shell redirection The shell allows stdin, stdout, and stderr to be redirected (say, to

or from a file).$ ./myprogram > somefile.txt

Connects stdout of “myprogram” to somefile.txt$ ./myprogram < input.txt > somefile.txt

Connects stdin to input.txt and stdout to somefile.txt$ ./myprogram 2> errors.txt

Connects stderr to errors.txt

In this case, the shell simply opens the file, making sure the file handle is 0, 1, or 2, as appropriate. Problem: open() decides what the file handle number is. How do we coerce the filehandle to be 0, 1, or 2?

Page 40: CENG334 Introduction to Operating Systems

40

dup() and dup2()

#include <unistd.h>

int dup(int filedes);

int dup2(int filedes, int filedes2);

Both will duplicate an existing file descriptor dup() returns lowest available file descriptor, now referring to whatever filedes

refers to dup2() - filedes2 (if open) will be closed and then set to refer to whatever filedes

refers to

Page 41: CENG334 Introduction to Operating Systems

41

dup()

#include <unistd.h>

int dup(int filedes);

dup() returns lowest available file descriptor, now referring to whatever filedes refers to

012

0123

int x = dup(1); // x has the value of 3 // x points to what 1 is pointing to

Page 42: CENG334 Introduction to Operating Systems

42

dup2()

#include <unistd.h>

int dup2(int filedes, int filedes2);

dup2() - filedes2 (if open) will be closed and then set to refer to whatever filedes refers to

0123

0123

int x = dup2(3,1);

Page 43: CENG334 Introduction to Operating Systems

43

Shell redirection The dup2() system call duplicates an open file descriptor, allowing you to specify

the filehandle number you want.

/* Redirect stdout to somefile.txt */

new_fh = open(“somefile.txt”, O_WRONLY);

/* This will close whatever filehandle 1 used to be. */

dup2(new_fh, 1);

/* Safe to close new_fh, since we only care about stdout */

close(new_fh);

Page 44: CENG334 Introduction to Operating Systems

44

Redirecting stdin & stdout in UNIX (cont’d)

0

1

2

3

stdinstdoutstderr

terminal

AFTER dup2()

outfile

0

1

2

3

stdinstdoutstderr

terminal

AFTER close()

outfile

list of openfile descriptors (in PCB)

0

1

2

3

stdinstdoutstderr

terminal

BEFORE dup2()

outfile

int fd = open(“outfile”, O_WRONLY);dup2(fd, 1);close(fd);

Page 45: CENG334 Introduction to Operating Systems

45

Pipes A form of inter-process communication between processes that have a common ancestor

Typical use: Pipe created by a process Process calls fork() Pipe used between parent and child

A pipe provides a one-way flow of data- example: who | sort| lpr

+ output of who is input to sort+ output of sort is input to lpr

The difference between a file and a pipe:- pipe is a data structure in the kernel.

A pipe is created by using the pipe system callint pipe(int* filedes);

Two file descriptors are returned- filedes[0] is open for reading- filedes[1] is open for writing

Typical size is 512 bytes (Minimum limit defined by POSIX)

Page 46: CENG334 Introduction to Operating Systems

46

Pipes#include <unistd.h>#include <stdio.h>int main(void){ int n; // to keep track of num bytes read int fd[2]; // to hold fds of both ends of pipe pid_t pid; // pid of child process char line[80]; // buffer to hold text read/writtenif (pipe(fd) < 0) // create the pipe perror("pipe error");

if ((pid = fork()) < 0) { // fork off a child perror("fork error"); } else if (pid > 0) { // parent process close(fd[0]); // close read end write(fd[1], "hello world\n", 12); // write to it }else { // child process close(fd[1]); // close write end n = read(fd[0], line, 80); // read from pipe write(1, line, n); // echo to screen } exit(0);}

Page 47: CENG334 Introduction to Operating Systems

47

After the pipe() call

5

4

3

stderr 2

stdout 1

stdin 0

3 4

Filedes 0 1

Page 48: CENG334 Introduction to Operating Systems

48

The process then calls fork()

5

4

3

stderr 2

stdout 1

stdin 0

5

4

3

stderr 2

stdout 1

stdin 0

Parent Child

Page 49: CENG334 Introduction to Operating Systems

49

Parent writing to child

5

4

X 3

stderr 2

stdout 1

stdin 0

5

X 4

3

stderr 2

stdout 1

stdin 0

Parent Child

Page 50: CENG334 Introduction to Operating Systems

50

Child writing to parent

5

X 4

3

stderr 2

stdout 1

stdin 0

5

4

X 3

stderr 2

stdout 1

stdin 0

Parent Child

Page 51: CENG334 Introduction to Operating Systems

51

Fun with file descriptors#include "csapp.h"int main(int argc, char *argv[]){

int fd1, fd2, fd3;char c1, c2, c3;char *fname = argv[1];fd1 = Open(fname, O_RDONLY, 0);fd2 = Open(fname, O_RDONLY, 0);fd3 = Open(fname, O_RDONLY, 0);Dup2(fd2, fd3);Read(fd1, &c1, 1);Read(fd2, &c2, 1);Read(fd3, &c3, 1);printf("c1 = %c, c2 = %c, c3 = %c\n", c1, c2, c3);return 0;

}

What would this program print for file containing “abcde”?