CS444 Lab Week 3

Front Matter

  • The shell assignment is due on GitLab next Thursday at 11:55pm!

  • You are required to implement pipes, redirection, and backgrounding

  • Use man pages and the information page on the course website.

  • Let us know if you need help!

This week

  • File descriptors

  • System calls you’ll need

  • Examples of the working shell

File Descriptors (fd’s)

  • To user programs, they are small non-negative integers

  • They are received from and passed as arguments to various system calls

  • Internally, an index into a "file descriptor table"

File-like objects

Objects in the file descriptor table are all file-like objects:

  • Possibly (and straightforwardly) an actual file on a disk

  • Possibly a pipe

  • Possibly a device

  • Possibly a network socket

Manipulating files

  • open(path, flags) opens the file named by path and returns a new fd. Flags are for opening as read, read/write, etc.

  • close(fd) closes the object referenced by fd

  • write(fd, buf, len) writes at most len bytes from buf to the object referenced by fd

  • read(fd, buf, len) reads at most len bytes from the object referenced by fd into buf

Open Example

int fd = open("some/file", O_RDONLY);
printf("%d\n", fd);
$ ./a.out
3

3?

On process start, three "standard" files are open:

  • fd 0 is "stdin"

  • fd 1 is "stdout"

  • fd 2 is "stderr"

This is just a convention! But, it’s enforced by the shell, and other programs with fork/exec usually maintain it.

Close Example

close(1);
int fd = open("some/file", O_RDONLY);
printf("%d\n", fd);
$ ./a.out
1

1?

When creating a new object, the first unused file descriptor is used.

Pipes

Pipes (also called "fifo’s" (first-in first-out)) are file-like objects that don’t actually reference a file.

Instead, it’s a first-in first-out queue, backed by a kernel buffer.

The buffer is only stored in volatile memory, so it can’t be seeked; data written can only be read forward, and exactly once.

Pipe example

int p[2];
char buf[6];

pipe(p);

printf("read fd: %d\nwrite fd: %d\n", p[0], p[1]);

write(p[1], "hello", 6);
read(p[0], buf, 6);

printf("%s\n", buf);
read fd: 3
write fd: 4
hello

fd table manipulation

  • dup(fd) creates a new fd refering to the same object that fd names

  • dup2(from_fd, to_fd) makes to_fd refer to the same object that from_fd names. (Not available in XV6.)

dup example

close(0);
int fd = dup(2);
printf("%d\n", fd)

What does it print?

Answer

0

Remember: creating a new fd uses the lowest free file descriptor

Fork

  • fork() creates a new process, duplicating the state of the current process.

  • Returns either -1 for failure, or 0 in the new process (child), or the non-zero PID of the new child process.

  • Almost all state is duplicated, including fd table. Not shared after the fork.

  • So open files in the parent will be open in the child, but opening a new file in the parent will not also open it in the child.

Exec

  • A family of system calls on POSIX. On XV6, only plain execv, named exec.

  • execv(path, argv) will run the program named by path in the current process.

  • Does not return, unless the system call fails!

  • The newly-running program inherits all the old process’s state, including open file descriptors.

chdir and getcwd

char buf[512];
chdir("/tmp");
printf("%s\n", getcwd(buf, 512));
/tmp

Shell demo

To the source!

Redirection

Redirection

First, the shell

Diagram

Redirection

Fork a child process

Diagram

Redirection

Close the desired file descriptor

Diagram

Redirection

Open the new file

Diagram

Piping

Piping

First, the shell

Diagram

Piping

After a pipe and a fork

Diagram

Piping

Another fork

Diagram

Piping

Close stdin in the reading process

Diagram

Piping

Dup the read end of the pipe in the reading process

Diagram

Piping

Close the extra file descriptors to the pipe in the reading process

Diagram

Piping

Close the stdout of the writing process

Diagram

Piping

Dup the write end of the pipe in the writing process

Diagram

Piping

Close the extra file descriptors to the pipe in the writing process

Diagram

Piping

Close the extra file descriptors in the shell process

Diagram