08 - UNIX I-O file descriptors, redirection and standard I-O

Class: CSCE-313


Notes:

Outline:

  1. File Descriptors
  2. Redirection
  3. Standard I/O (stdio)

File Descriptors

Why File Descriptors?

00 - TAMU Brain/6th Semester (Spring 26)/CSCE-313/Lecture/Visual Aids/image-20.png449

Why do we need to open and close sessions when we read-from or write-to files?

Because the system can internally store (cache) information about the file as we access it.

File Descriptors practice - I

int main() {
    char c1, c2, c3;
    char *fname = "file.txt";
    
    int fd1 = open(fname, O_RDONLY);
    int fd2 = open(fname, O_RDONLY);
    int fd3 = open(fname, O_RDONLY);
    
    dup2(fd2, fd3);
    read(fd1, &c1, 1);
    read(fd2, &c2, 1);
    read(fd3, &c3, 1);
    printf("c1 = %c, c2 = %c, c3 = %c\n", c1, c2, c3);
}

What would this program print for a file containing “abcde”?

Try online: https://csce313.schnekli.top/gform/fd-1

Answer: c1 = a, c2 = a, c3 = b

File Descriptors practice - II

int main(int argc, char *argv[]) {
    int fd1, fd2, fd3;
    char *fname = argv[1];
    fd1 = open(fname, O_CREAT|O_TRUNC|O_RDWR, S_IRUSR|S_IWUSR);
    write(fd1, "pqrs", 4);
    fd2 = open(fname, O_APPEND|O_WRONLY, 0);
    write(fd2, "jklmn", 5);
    fd3 = dup(fd1); /* Allocates descriptor */
    write(fd3, "wxyz", 4);
    write(fd2, "ef", 2);
    // set fd1 to point to the beginning of the file
    lseek (fd1, 0, SEEK_SET);
    write (fd1, "ab", 2);
    return 0;
}

Answer: abrswxyznef

File Descriptors and fork()

With fork(), child inherits content of parent’s address space, including its file descriptor table.

00 - TAMU Brain/6th Semester (Spring 26)/CSCE-313/Lecture/Visual Aids/image-21.png252

File Descriptors and fork() - I

int main(void) {
    char c;
    int myfd=open("myf.txt",O_RDONLY);
    fork();
    read(myfd, &c, 1);
    printf("Got %c\n", c);
}

00 - TAMU Brain/6th Semester (Spring 26)/CSCE-313/Lecture/Visual Aids/image-2.png250

File Descriptors and fork() - II

int main(void) {
    char c;
    fork();
    int myfd=open("myf.txt",O_RDONLY);
    read(myfd, &c, 1);
    printf("Got %c\n", c);
}

What would this program print for a file containing "abcde"?

00 - TAMU Brain/6th Semester (Spring 26)/CSCE-313/Lecture/Visual Aids/image-1.png250

Answer: aa

Example of duplicated FD's

Suppose the disk file foobar.txt consists of the six ASCII characters “foobar”. What is the output of the following program?

int main () {
	char c;
	int fd = open("foobar.txt", O_RDONLY);
	
	if (fork() == 0) {
		read(fd, &c, 1);
		return 0;
	} else {
		wait(0);
		read(fd, &c, 1);
		cout << "c=" << c << endl;
	}
}

Answer: The child inherits the parent’s descriptor table and both processes share the same file table. Thus the descriptor fd in both the parent and child points to the same open file table entry.

When the child reads the first byte of the file, the file position increments by 1. Thus the parent reads the second byte and output is “c=o

Example - Descriptor Recycling

What is the output of the following program?

int main (){
    int fd1 = open("foo.txt",O_RDONLY);
    close(fd1);
    int fd2 = open("baz.txt", O_RDONLY);
    cout << "fd2 = " << fd2 << endl;
}

Unix processes begin life with open descriptors assigned to stdin ( fd=0 ), stdout ( fd=1 ), and stderr ( fd=2 ).

The open function always returns the lowest unopened descriptor so the output will be "fd2 = 3"

Notes:

Redirection

Standard I/O Functions

The C standard library (libc.so) contains a collection of higher-level standard I/O functions

Examples of standard I/O functions:

Notes:

Standard I/O models open files as streams

C programs begin life with three open streams (defined in stdio.h)

#include <stdio.h>
extern FILE *stdin; /* standard input (descriptor 0) */
extern FILE *stdout; /* standard output (descriptor 1) */
extern FILE *stderr; /* standard error (descriptor 2) */
int main() {
    fprintf(stdout, "Hello, world\n");
}

Motivations

00 - TAMU Brain/6th Semester (Spring 26)/CSCE-313/Lecture/Visual Aids/image-3.png500

Notes:

Buffering in Standard I/O

Standard I/O functions use buffered I/O
00 - TAMU Brain/6th Semester (Spring 26)/CSCE-313/Lecture/Visual Aids/image-4.png400

Buffer flushed to output fd on "\n" or fflush() call

Unix I/O vs. Standard I/O

Standard I/O is implemented using low-level Unix I/O

00 - TAMU Brain/6th Semester (Spring 26)/CSCE-313/Lecture/Visual Aids/image-5.png400
Which ones should you use in your programs?

Pros and Cons of Standard I/O

Pros of Unix I/O over standard I/O

Cons of Unix I/O over standard I/O

Notes:

Choosing I/O Functions

General rule: use the highest-level I/O functions you can

Use standard I/O

Use raw Unix I/O