10/1/16 COMP 530: Operating Systems COMP 530: Operating Systems Recap Basic OS Programming • We’ve introduced the idea of a process as a Abstractions container for a running program • This lecture: Introduce key OS APIs for a process (and Lab 1 Overview) – Some may be familiar from lab 0 – Some will help with lab 1 Don Porter Portions courtesy Kevin Jeffay 1 COMP 530: Operating Systems COMP 530: Operating Systems Lab 1: A (Not So) Simple Shell Tasks • Last year: Most of the lab focused on just processing • Turn input into commands; execute those commands input and output – Support PATH variables – Kind of covered in lab 0 • Be able to change directories – I’m giving you some boilerplate code that does basics • Print the working directory at the command line – Reminder: demo • Add debugging support • My goal: Get some experience using process APIs • Add variables and scripting support – Most of what you will need discussed in this lecture • Pipe indirection: <, >, and | • You will incrementally improve the shell • Job control (background & foreground execution) • goheels – draw an ASCII art Tar Heel Significantly more work than Lab 0 – start early! 3 4 COMP 530: Operating Systems COMP 530: Operating Systems Outline Process Creation: fork/join in Linux • The execution context for the child process is a copy of • Fork recap the parent’s context at the time of the call • Files and File Handles • Inheritance main { fork() int childPID; • Pipes S 1 ; childPID = fork(); • Sockets childPID if(childPID == 0) Code Code • Signals < code for child process > = 0 else { • Synthesis Example: The Shell Data Data < code for parent process > wait(); childPID Stack Stack } = xxx S 2 ; Child Parent } 1
10/1/16 COMP 530: Operating Systems COMP 530: Operating Systems Process Creation: exec in Linux Process Creation: Abstract fork in Linux • The original fork semantics can be realized in Linux via a • exec allows a process to replace itself with another program – (The contents of another binary file) (UNIX) fork followed by an exec foo: main { main { S’ fork() int childPID; } exec() S 1 ; exec() childPID = fork(); a.out: main { if(childPID == 0) Code Code S 0 Code exec(filename) exec( foo ) main { else { Data Data S 1 S’ Data < code for parent process > S 2 } wait(); Stack Stack } Stack } . /foo Memory S 2 ; Child Parent Context } COMP 530: Operating Systems COMP 530: Operating Systems 2 Ways to Refer to a File Path-based calls • Path, or hierarchical name, of the file • Functions that operate on the directory tree – Absolute: “/home/porter/foo.txt” – Rename, unlink (delete), chmod (change permissions), etc. • Starts at system root • Open – creates a handle to a file – Relative: “foo.txt” – int open (char *path, int flags, mode_t mode); • Assumes file is in the program’s current working directory • Flags include O_RDONLY, O_RDWR, O_WRONLY • Handle to an open file • Permissions are generally checked only at open – Handle includes a cursor (offset into the file) – Opendir – variant for a directory COMP 530: Operating Systems COMP 530: Operating Systems Handle-based calls Example • ssize_t read (int fd, void *buf, size_t count) char buf[9]; PC Awesome\0 Awesome\0 int fd = open (“foo.txt”, O_RDWR); – Fd is the handle buf ssize_t bytes = read(fd, buf, 8); fd: 3 – Buf is a user-provided buffer to receive count bytes of the if (bytes != 8) // handle the error file bytes: 8 memcpy(buf, “Awesome”, 7); – Returns how many bytes read buf[7] = ‘\0’; User-level stack • ssize_t write(int fd, void *buf, size_t count) bytes = write(fd, buf, 8); if (bytes != 8) // error Kernel – Same idea, other direction Handle 3 close(fd); • int close (int fd) – Close an open file Contents\0 Awesome Contents foo.txt 2
10/1/16 COMP 530: Operating Systems COMP 530: Operating Systems Handles But what is a handle? Logical View can be shared • A reference to an open file or other OS object Virtual Address Space – For files, this includes a cursor into the file 50 Handle Table Hello! Foo.txt • In the application, a handle is just an integer Process A inode – This is an offset into an OS-managed table Handle indices 20 are process- Process B specific Disk Handle Table Process C COMP 530: Operating Systems COMP 530: Operating Systems Handle Recap Rearranging the table • Every process has a table of pointers to kernel handle • The OS picks which index to use for a new handle objects • An application explicitly copy an entry to a specific – E.g., a file handle includes the offset into the file and a index with dup2(old, new) pointer to the kernel-internal file representation (inode) – Be careful if new is already in use… • Application’s can’t directly read these pointers – Kernel memory is protected – Instead, make system calls with the indices into this table – Index is commonly called a handle COMP 530: Operating Systems COMP 530: Operating Systems Other useful handle APIs Outline • mmap() – can map part or all of a file into memory • Files and File Handles • seek() – adjust the cursor position of a file • Inheritance – Like rewinding a cassette tape • Pipes • Sockets • Signals • Synthesis Example: The Shell 3
10/1/16 COMP 530: Operating Systems COMP 530: Operating Systems Inheritance Standard in, out, error • By default, a child process gets a reference to every • Handles 0, 1, and 2 are special by convention handle the parent has open – 0: standard input – Very convenient – 1: standard output – Also a security issue: may accidentally pass something the – 2: standard error (output) program shouldn’t • Command-line programs use this convention • Between fork() and exec(), the parent has a chance – Parent program (shell) is responsible to use to clean up handles it doesn’t want to pass on open/close/dup2 to set these handles appropriately between fork() and exec() – See also CLOSE_ON_EXEC flag COMP 530: Operating Systems COMP 530: Operating Systems Example Outline • Files and File Handles int pid = fork(); • Inheritance if (pid == 0) { • Pipes int input = open (“in.txt”, O_RDONLY); • Sockets dup2(input, 0); • Signals exec(“grep”, “quack”); • Synthesis Example: The Shell } //… COMP 530: Operating Systems COMP 530: Operating Systems Pipes Example • FIFO stream of bytes between two processes int pipe_fd[2]; PC W Virtual Address Space int rv = pipe(pipe_fd); • Read and write like a file handle Handle Table PC int pid = fork(); – But not anywhere in the hierarchical file system Parent if (pid == 0) { – And not persistent close(pipe_fd[1]); – And no cursor or seek()-ing dup2(pipe_fd[0], 0); – Actually, 2 handles: a read handle and a write handle close(pipe_fd[0]); R exec(“grep”, “quack”); Child • Primarily used for parent/child communication } else { – Parent creates a pipe, child inherits it close (pipe_fd[0]); ... 4
10/1/16 COMP 530: Operating Systems COMP 530: Operating Systems Sockets Select • Similar to pipes, except for network connections • What if I want to block until one of several handles has data ready to read? • Setup and connection management is a bit trickier • Read will block on one handle, but perhaps miss data – A topic for another day (or class) on a second… • Select will block a process until a handle has data available – Useful for applications that use pipes, sockets, etc. COMP 530: Operating Systems COMP 530: Operating Systems Outline Signals • Files and File Handles • Similar concept to an application-level interrupt • Inheritance – Unix-specific (more on Windows later) • Each signal has a number assigned by convention • Pipes – Just like interrupts • Sockets • Application specifies a handler for each signal • Signals – OS provides default • Synthesis Example: The Shell • If a signal is received, control jumps to the handler – If process survives, control returns back to application COMP 530: Operating Systems COMP 530: Operating Systems Signals, cont. How signals work • Can occur for: • Although signals appear to be delivered immediately… – Exceptions: divide by zero, null pointer, etc. – They are actually delivered lazily… – IPC: Application-defined signals (USR1, USR2) – Control process execution (KILL, STOP, CONT) – Whenever the OS happens to be returning to the process from an interrupt, system call, etc. • Send a signal using kill(pid, signo) • So if I signal another process, the other process may – Killing an errant program is common, but you can also not receive it until it is scheduled again send a non-lethal signal using kill() • Use signal() or sigaction() to set the handler for a • Does this matter? signal 5
Recommend
More recommend