Upload
sitara
View
31
Download
0
Tags:
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
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.
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?
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.
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)
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.
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?
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
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.
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
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
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
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
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
14
Context Switching in Linux
Process A
time
Process A is happily running along...
15
Context Switching in Linux
Process A
time
Timer interrupt handler
1) Timer interrupt fires
2) PC saved on stackUserKernel
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
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
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
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
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)
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
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(); }}
}
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
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?
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.
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 ... */}
}
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 */
}
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...
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
30
Problematic?
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
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.)
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()
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);}
}
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!
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
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.
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.
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?
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
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
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);
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);
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);
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)
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);}
47
After the pipe() call
5
4
3
stderr 2
stdout 1
stdin 0
3 4
Filedes 0 1
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
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
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
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”?