Try Firefox!

IC221 Lab 6: Basic kerenel-based I/O with file descriptors

Background
Up 'til now, we've been using the C standard library routines fopen, fclose, fscanf and fprintf for I/O. We know from last class, that these standard libary routines must, at some point, use system calls to do thier job. The basic I/O system calls are open, close, read and write. Whereas C standard library routines use FILE* (file stream pointer) objects to reference connections to files, system calls use file descriptors. How they fit into the kernel's I/O architecture was explained last class.

In this lab, you'll implement the basic wc functionality using system calls for I/O. Your simple wc function will take a list of files and print the total number of bytes in all the files put together.

Basic I/O operations with file streams vs. file descriptors
Operation/conceptC standard librarysystem call
reference to file connection file stream ponter (FILE*) file descriptor (int)
open a file connection FILE *fopen(const char *filename, const char *mode); int open(const char *path, int oflag, /* mode_t mode */);
close file connection int fclose(FILE *stream); int close(int fildes);
read from file connection int fscanf(FILE *restrict stream, const char *restrict format, ...); ssize_t read(int fildes, void *buf, size_t nbyte);
write to file connection int fprintf(FILE *restrict stream, const char *restrict format,/* args*/ ...); ssize_t write(int fildes, const void *buf, size_t nbyte);
predefined file connections stdin, stdout, stderr STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO (0, 1 and 2, respectively)

Questions to answer: 25 points
Create a lab06 dirctory. Copy these questions into a file ans.txt (in your lab06 directory) and add the answers to the questions. Do this before the rest of the lab!

Part 1: 25 Points
Create a C source code file named lab06.c that compiles to a program mywc that reads a character/byte at a time from standard input using the read system call, and writes out the number of characters/bytes read 'til end of file. You may use fprintf to produce the output. Here's an example run:
bash$ mywc < /usr/bin/gs
8304168

Part 2: 20 Points
The time utility takes a shell-command string, executes it, and returs the number of seconds of "user" time, "system" time, and actual "wall-clock" time required to execute. Use it to time your solution to Part 1, i.e.
bash$ time mywc < /usr/bin/gs
	
and record the number in ans.txt. Now modify your lab06.c so that your mywc calls to read attempt to read 100 characters/bytes at a time into a 100-character array. Rerun the timing command, and add the new time to ans.c along with an explanation for the difference in the times. NOTE: pay close attention to read's return value in order to get this right!

Part 3: 20 Points
Now modify your lab06.c so that your mywc accepts a command-line argument. With no arguments, the program runs as before, with an argument, however, it treats the argument as a file name and reads from that file instead of standard input. Note that you need to spit out error messages and exit if the filename is bad. Read the man page for open in order to do that. Here are some example runs:
bash$ mywc < /usr/bin/gs
8304168
bash$ mywc /usr/bin/gs
8304168
bash$ mywc lkjlkjk
mywc: Error!  File "lkjlkjk" not found!
	

Part 4: 10 Points
Now modify your lab06.c so that your mywc accepts an arbitrary number of command-line arguments, each of which are file names. Your mywc program should return the total combined number of characters/bytes in all the files listed on the command line. If none are listed, return the number of bytes read from standard input, as before. Here are some example runs:
bash$ mywc < /usr/bin/gs
8304168
bash$ mywc /usr/bin/gs /etc/hosts /usr/include/math.h 
8315730
bash$ mywc /usr/bin/gs /etc/hosts lkjlkjk /usr/include/math.h
mywc: Error!  File "lkjlkjk" not found!
	

Submission
Submit the lab06 directory via the usual submit script.


Christopher W Brown
Last modified: Wed Feb 4 16:38:13 EST 2009