diff options
Diffstat (limited to 'web/l1.html')
| -rw-r--r-- | web/l1.html | 288 | 
1 files changed, 288 insertions, 0 deletions
| diff --git a/web/l1.html b/web/l1.html new file mode 100644 index 0000000..9865601 --- /dev/null +++ b/web/l1.html @@ -0,0 +1,288 @@ +<title>L1</title> +<html> +<head> +</head> +<body> + +<h1>OS overview</h1> + +<h2>Overview</h2> + +<ul> +<li>Goal of course: + +<ul> +<li>Understand operating systems in detail by designing and +implementing miminal OS +<li>Hands-on experience with building systems  ("Applying 6.033") +</ul> + +<li>What is an operating system? +<ul> +<li>a piece of software that turns the hardware into something useful +<li>layered picture: hardware, OS, applications +<li>Three main functions: fault isolate applications, abstract hardware,  +manage hardware +</ul> + +<li>Examples: +<ul> +<li>OS-X, Windows, Linux, *BSD, ... (desktop, server) +<li>PalmOS Windows/CE (PDA) +<li>Symbian, JavaOS (Cell phones) +<li>VxWorks, pSOS (real-time) +<li> ... +</ul> + +<li>OS Abstractions +<ul> +<li>processes: fork, wait, exec, exit, kill, getpid, brk, nice, sleep, +trace +<li>files:  open, close, read, write, lseek, stat, sync +<li>directories: mkdir, rmdir, link, unlink, mount, umount +<li>users + security: chown, chmod, getuid, setuid +<li>interprocess communication: signals, pipe +<li>networking: socket, accept, snd, recv, connect +<li>time: gettimeofday +<li>terminal: +</ul> + +<li>Sample Unix System calls (mostly POSIX) +<ul> +	<li> int read(int fd, void*, int) +	<li> int write(int fd, void*, int) +	<li> off_t lseek(int fd, off_t, int [012]) +	<li> int close(int fd) +	<li> int fsync(int fd) +	<li> int open(const char*, int flags [, int mode]) +	  <ul> +		<li> O_RDONLY, O_WRONLY, O_RDWR, O_CREAT +	  </ul> +	<li> mode_t umask(mode_t cmask) +	<li> int mkdir(char *path, mode_t mode); +	<li> DIR *opendir(char *dirname) +	<li> struct dirent *readdir(DIR *dirp) +	<li> int closedir(DIR *dirp) +	<li> int chdir(char *path) +	<li> int link(char *existing, char *new) +	<li> int unlink(char *path) +	<li> int rename(const char*, const char*) +	<li> int rmdir(char *path) +	<li> int stat(char *path, struct stat *buf) +	<li> int mknod(char *path, mode_t mode, dev_t dev) +	<li> int fork() +          <ul> +		<li> returns childPID in parent, 0 in child; only +		difference +           </ul> +	<li>int getpid() +	<li> int waitpid(int pid, int* stat, int opt) +           <ul> +		<li> pid==-1: any; opt==0||WNOHANG +		<li> returns pid or error +	   </ul> +	<li> void _exit(int status) +	<li> int kill(int pid, int signal) +	<li> int sigaction(int sig, struct sigaction *, struct sigaction *) +	<li> int sleep (int sec) +	<li> int execve(char* prog, char** argv, char** envp) +	<li> void *sbrk(int incr) +	<li> int dup2(int oldfd, int newfd) +	<li> int fcntl(int fd, F_SETFD, int val) +	<li> int pipe(int fds[2]) +	  <ul> +		<li> writes on fds[1] will be read on fds[0] +		<li> when last fds[1] closed, read fds[0] retursn EOF +		<li> when last fds[0] closed, write fds[1] kills SIGPIPE/fails +		EPIPE +           </ul> +	<li> int fchown(int fd, uind_t owner, gid_t group) +	<li> int fchmod(int fd, mode_t mode) +	<li> int socket(int domain, int type, int protocol) +	<li> int accept(int socket_fd, struct sockaddr*, int* namelen) +	  <ul> +		<li> returns new fd +          </ul> +	<li> int listen(int fd, int backlog) +	<li> int connect(int fd, const struct sockaddr*, int namelen) +	<li> void* mmap(void* addr, size_t len, int prot, int flags, int fd, +	off_t offset) +	<li> int munmap(void* addr, size_t len) +	<li> int gettimeofday(struct timeval*) +</ul> +</ul> + +<p>See the <a href="../reference.html">reference page</a> for links to +the early Unix papers. + +<h2>Class structure</h2> + +<ul> +<li>Lab: minimal OS for x86 in an exokernel style (50%) +<ul> +<li>kernel interface: hardware + protection +<li>libOS implements fork, exec, pipe, ... +<li>applications: file system, shell, .. +<li>development environment: gcc, bochs +<li>lab 1 is out +</ul> + +<li>Lecture structure (20%) +<ul> +<li>homework +<li>45min lecture +<li>45min case study +</ul> + +<li>Two quizzes (30%) +<ul> +<li>mid-term +<li>final's exam week +</ul> + +</ul> + +<h2>Case study: the shell (simplified)</h2> + +<ul> +<li>interactive command execution and a programming language +<li>Nice example that uses various OS abstractions. See  <a +href="../readings/ritchie74unix.pdf">Unix +paper</a> if you are unfamiliar with the shell. +<li>Final lab is a simple shell. +<li>Basic structure: +<pre> +       +       while (1) { +	    printf ("$"); +	    readcommand (command, args);   // parse user input +	    if ((pid = fork ()) == 0) {  // child? +	       exec (command, args, 0); +	    } else if (pid > 0) {   // parent? +	       wait (0);   // wait for child to terminate +	    } else { +	       perror ("Failed to fork\n"); +            } +        } +</pre> +<p>The split of creating a process with a new program in fork and exec +is mostly a historical accident.  See the  <a +href="../readings/ritchie79evolution.html">assigned paper</a> for today. +<li>Example: +<pre> +        $ ls +</pre> +<li>why call "wait"?  to wait for the child to terminate and collect +its exit status.  (if child finishes, child becomes a zombie until +parent calls wait.) +<li>I/O: file descriptors.  Child inherits open file descriptors +from parent. By convention: +<ul> +<li>file descriptor 0 for input (e.g., keyboard). read_command:  +<pre> +     read (1, buf, bufsize) +</pre> +<li>file descriptor 1 for output (e.g., terminal) +<pre> +     write (1, "hello\n", strlen("hello\n")+1) +</pre> +<li>file descriptor 2 for error (e.g., terminal) +</ul> +<li>How does the shell implement: +<pre> +     $ls > tmp1 +</pre> +just before exec insert: +<pre> +    	   close (1); +	   fd = open ("tmp1", O_CREAT|O_WRONLY);   // fd will be 1! +</pre> +<p>The kernel will return the first free file descriptor, 1 in this case. +<li>How does the shell implement sharing an output file: +<pre> +     $ls 2> tmp1 > tmp1 +</pre> +replace last code with: +<pre> + +	   close (1); +	   close (2); +	   fd1 = open ("tmp1", O_CREAT|O_WRONLY);   // fd will be 1! +	   fd2 = dup (fd1); +</pre> +both file descriptors share offset +<li>how do programs communicate? +<pre> +        $ sort file.txt | uniq | wc +</pre> +or +<pre> +	$ sort file.txt > tmp1 +	$ uniq tmp1 > tmp2 +	$ wc tmp2 +	$ rm tmp1 tmp2 +</pre> +or  +<pre> +        $ kill -9 +</pre> +<li>A pipe is an one-way communication channel.  Here is an example +where the parent is the writer and the child is the reader: +<pre> + +	int fdarray[2]; +	 +	if (pipe(fdarray) < 0) panic ("error"); +	if ((pid = fork()) < 0) panic ("error"); +	else if (pid > 0) { +	  close(fdarray[0]); +	  write(fdarray[1], "hello world\n", 12); +        } else { +	  close(fdarray[1]); +	  n = read (fdarray[0], buf, MAXBUF); +	  write (1, buf, n); +        } +</pre> +<li>How does the shell implement pipelines (i.e., cmd 1 | cmd 2 |..)? +We want to arrange that the output of cmd 1 is the input of cmd 2. +The way to achieve this goal is to manipulate stdout and stdin. +<li>The shell creates processes for each command in +the pipeline, hooks up their stdin and stdout correctly.  To do it +correct, and waits for the last process of the +pipeline to exit.  A sketch of the core modifications to our shell for +setting up a pipe is: +<pre>	     +	    int fdarray[2]; + +  	    if (pipe(fdarray) < 0) panic ("error"); +	    if ((pid = fork ()) == 0) {  child (left end of pipe) +	       close (1); +	       tmp = dup (fdarray[1]);   // fdarray[1] is the write end, tmp will be 1 +	       close (fdarray[0]);       // close read end +	       close (fdarray[1]);       // close fdarray[1] +	       exec (command1, args1, 0); +	    } else if (pid > 0) {        // parent (right end of pipe) +	       close (0); +	       tmp = dup (fdarray[0]);   // fdarray[0] is the read end, tmp will be 0 +	       close (fdarray[0]); +	       close (fdarray[1]);       // close write end +	       exec (command2, args2, 0); +	    } else { +	       printf ("Unable to fork\n"); +            } +</pre> +<li>Why close read-end and write-end? multiple reasons: maintain that +every process starts with 3 file descriptors and reading from an empty +pipe blocks reader, while reading from a closed pipe returns end of +file. +<li>How do you  background jobs? +<pre> +        $ compute & +</pre> +<li>How does the shell implement "&", backgrounding?  (Don't call wait +immediately). +<li>More details in the shell lecture later in the term. + +</body> + + | 
