Wednesday, February 5, 2014

THE BASIC INPUT AND OUTPUT OPERATIONS

THE I/O PROCESSING

One of the ways to classify the Unix I/O is to think of it as buffered or unbuffered.

The Unbuffered I/O has following path of data flow:

 Data->Kernel Buffer->Disk
       

Most of the system calls like: read, write, open, gets,puts, close are unbuffered.

The buffered I/O has following path of data flow:

 Data->User Buffer -> Kernel Buffer -> Disk
       

The standard I/O are usually buffered: fread,fwrite, fopen fclose,getchar,putchar.

Please note that : STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO are file descriptors whose type is 'int' and they are system calls themselves.

Please note that : stdin, stdout and stderr are standard I/O and they are pointers of type FILE*.

USING UNBUFFERED I/O

In this section we are going to encounter following functions:
read(2)
write(2)
perror(3)
exit(3)
     

Before going ahead and creating a program, let us have a brief look at the information from man pages. Here is what we have for read function:
man 2 read
Library:
#include <unistd.h >
Prototype:
  ssize_t read(int fd, const void *buf, size_t count);
Description:
  attempts to read up to count bytes from file
  descriptor fd into the buffer starting at buf.
Notes:
  0. If count=0, then zero is returned and no other effects.
  1. Commences at current file offset.
  2. If offset is past end of file, nothing read, zero returned
  3. If count > SSIZE_MAX, result unspecified.
Return:
  On Success: number of bytes read.
  On Error: returns -1, set 'errno'
       

Now we shall look at the function perror(3):
Library:
    #include <stdio.h>
   #include <errno.h>
Prototype:
   void perror(const char *s);
escription:
    produces  a message on the standard error output,
    describing the last error encountered during a call to
    a system or library function
Return:
    On Success: number of bytes returned.
    On Error: returns -1, set 'errno'
       

Finally we need to know about the exit call
Library:
  #include <stdlib.h>
Prototype:
  void exit(int status);
Description:
  causes normal process termination and the value o
Return:
  no return
   

Now here comes the exiting part: The actual program.
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>

#define BUFFERSIZE  8192

int main(int argc, char* argv[]){
          /*Size of data read in single go*/
          int numRead;  
   
          /*Buffer to store the data read in one go*/
          char buffer[8192]; 
 
   /*attempt a first read from STDIN_FILENO*/
   numRead = read ( STDIN_FILENO, buffer, BUFFERSIZE );
  
   while(numRead>0){
   
   /*Write numBytes bytes into the stdout*/
   int numWrite = write (STDIN_FILENO, buffer, numRead);
   
   /*Check if all the bytes sent to write, got written*/
          if(numRead != numWrite){
   perror("Error while writing");
   exit(1);
   }
 
  /*Write the next record.*/
   numRead = read ( STDIN_FILENO, buffer, BUFFERSIZE );
   }
  
   
   /*If we see a negative value of numRead, its error*/
   if(numRead<0){
         perror("Error while reading");
         exit(2);
         }
         
   /*If you manage to reach here, exit normally*/
    exit(0);
}
 

USING BUFFERED I/0

In this program we shall use buffered I/O methods to do what we did in last program. Here are the functions that we gonna use:
fgetc(3)
fputc(3)
ferror(3)
perror(3)
exit(3)

So we start with man information on fgetc:
Library:
    #include <stdio.h>
Prototype:
    void fgetc(FILE *stream);
Description:
    reads the next character from stream.
    
Returns:
    returns the caharacter read as an unsigned char cast to an int,
    or EOF on end of file or error.

And here is a bit on fputc:
Library:
    #include <stdio.h>
Prototype:
    void fputc(FILE *stream);
Description:
    writes the character c, to stream.
Returns:
    nothing

and finally we need to talk about ferror:
Library:
    #include 
Prototype:
    void ferror(FILE *stream);
Description:
    test the error indicator on stream.
Returns:
    if error indicator on stream is set, ferror returns nonzero

And now we are ready to have a look at our program:
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>

#define BUFFERSIZE  8192

int main(int argc, char* argv[]){
  
  char datum; /*variable to hold the data*/

  /*Attempt a first read from stdin*/
  datum = fgetc (stdin);

  while(datum != EOF){
    
    /*Write the datum into stdout*/
    if(fputc(datum, stdout)==EOF){
      perror("Error while trying to write: fputc");
      exit(1);
    }
    /*Read the next record.*/
    datum = fgetc (stdin);
  }


  /*If a stdin error brought you here: its bad*/
  if(ferror(stdin)){
    perror("Error while reading: fgetc");
    exit(2);
  }

  /*If you manage to reach here, exit normally*/
  exit(0);
}

SUMMARY

We in last post took a brief tour into the basic ideas that are needed to begin Linux System Programming. In this post we further developed those ideas and examined the buffered and unbuffered I/O modes. In the next post we shall continue to build upon these points and see how to open and read directories.

No comments:

Post a Comment