Lecture 17

Monday, 9 November 1998


Created 9/11/1998

More on UNIX's file descriptors

The following program is an example of file descriptor manipulation. It implements the ">" file redirection operator commonly found in shell languages. source (compile with g++)

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

main() {
	char *line = new char[100];

	int f = open("test", O_WRONLY | O_CREAT, 0700);

	dup2(f, 1);	// or ... close(1); dup(f);

	puts(gets(line));
}
The open system call creates a file and assigns it the next available descriptor in the process' file descriptor table -- that is, file descriptor 3, because 0, 1, 2 are already allocated by default. The system call dup2 then makes file descriptor 1 point to the same file as file descriptor 3. As a result, the output of puts goes to the file instead of stdout which was originally pointed to by file descriptor 1. Here is what happens in picture:

The following one is slightly more elaborate; it implements a pipe between two programs, cat and wc. source (compile with gcc)

#include <stdio.h>

main() {
	int fd[2];
	pipe(fd);
	if (fork() == 0) {	// first child
		dup2(fd[1], 1);	// or ... close(1); dup(fd[1]);
		close(fd[0]);
		close(fd[1]);
		execlp("cat", "cat", NULL);
	}
	if (fork() == 0) {	// second child
		dup2(fd[0], 0);	// or ... close(0), dup(fd[0]);
		close(fd[0]);
		close(fd[1]);
		execlp("wc", "wc", "-c", NULL);
	}
	close(fd[0]);
	close(fd[1]);
	while (wait(NULL) != -1)
		;
}
The pipe system call grabs the next two available file descriptors, i.e., 3 and 4, and store them in fd[0] and fd[1]. fd[0] is connected to the input end of the pipe, and fd[1] the output end.

When a child is forked, its parent's file descriptors table is copied to the child so that all the opened files (including any pipes) are automatically pointed to by both processes.

A pipe is a FIFO type of file implemented as a memory object by the kernel.

Using dup2 and close, we can achieve the desired effect, as shown below.