466: Operating Systems¶
Principles of operating system design, including process management, IPC, and networking.
Topics¶
Process and thread management
Scheduling algorithms
Memory management and virtual memory
File systems
Inter-process communication (pipes, signals, sockets)
Unix system call interface
Projects¶
Custom Unix Shell (466/shell/)¶
The final iteration of a multi-stage shell project. Implements a POSIX-style command interpreter with:
Input/output redirection (
<,>,>>)Pipes (
|) chaining arbitrary commandsBackground execution (
&)Built-in commands:
cd,exit
int main(void) {
char **tokenv;
char *s;
int tokenc;
s = prompt();
while (s != NULL) {
tokenv = tokenize(s, &tokenc);
if (tokenv[0] != NULL) {
handle_tokens(tokenv, &tokenc); /* dispatch: fork, pipe, redir, builtins */
}
free(tokenv);
free(s);
s = prompt();
}
return EXIT_SUCCESS;
}
Socket Programming Utilities (466/tok/socket.c)¶
Low-level network programming examples using BSD sockets. Demonstrates TCP client/server
setup, connect/accept lifecycle, and streaming data over a socket.
int create_socket(u_short portnum) {
struct sockaddr_in sa;
gethostname(myname, MAXHOSTNAMELEN);
hp = gethostbyname(myname);
sa.sin_family = hp->h_addrtype;
sa.sin_port = htons(portnum);
s = socket(AF_INET, SOCK_STREAM, 0);
bind(s, (struct sockaddr *)&sa, sizeof sa);
listen(s, 3);
return s;
}
int wait_for_connection(int s) {
struct sockaddr_in isa;
int len = sizeof isa;
return accept(s, (struct sockaddr *)&isa, &len);
}
Token Ring Election (466/tok/tok.c)¶
Implements a distributed token ring leader-election algorithm using BSD sockets. Processes communicate in a ring topology, passing tokens to elect a coordinator — demonstrating socket setup, process coordination, and distributed consensus.
typedef union {
char as_char[2];
short as_short;
} tToken; /* 16-bit token value */
#define NO_TOKEN ((tToken)(short)-1)
#define send_token(s, t) { tToken _t = t; write(s, &_t, sizeof(_t)); }
/* Each process passes the token to the next in the ring;
* a process keeps the token only if its ID is the highest seen. */
External Sort via Fork/Exec (466/sort/main.c)¶
Forks a child process and uses exec to pipe file input through the system sort
utility, demonstrating the Unix process model, file descriptor manipulation, and
fork/exec/wait patterns.
pipe(a); /* parent → child (input to sort) */
pipe(b); /* child → parent (output from sort) */
if (fork() == 0) {
/* child: wire stdin/stdout to the pipes, then exec sort */
dup2(a[0], STDIN_FILENO);
dup2(b[1], STDOUT_FILENO);
execvp("sort", (char *[]){ "sort", NULL });
} else {
/* parent: write lines, then read sorted output */
while (fgets(line, sizeof line, infile))
write(a[1], line, strlen(line));
close(a[1]); /* signal EOF to sort */
FILE *fin = fdopen(b[0], "r");
while (fgets(buf, sizeof buf, fin))
printf("%s", buf);
}
Directory Reader (466/dir/main.c)¶
Reads and prints a file character-by-character using low-level POSIX I/O, an introductory
exercise in file descriptor usage and the read system call.
FILE *dir = fopen("dir", "r");
char c;
/* Read one byte at a time and print char + its ASCII value */
while ((c = fgetc(dir)) != EOF)
printf("%c %d\n", c, (unsigned char)c);