Low Level Disk I/O in C

In low level disk I/O, data cannot be written as individual characters, or as strings or as formatted data. There is only one way data can be written or read in low level disk I/O functions—as a buffer full of bytes.

Writing a buffer full of data resembles the fwrite( ) function. However, unlike fwrite( ), the programmer must set up the buffer for the data, place the appropriate values in it before writing, and take them out after writing. Thus, the buffer in the low level I/O functions is very much a part of the program, rather than being invisible as in high level disk I/O functions

Low level disk I/O functions offer following advantages:

  • Since these functions parallel the methods that the OS uses to write to the disk, they are more efficient than the high level disk I/O functions
  • Since there are fewer layers of routines to go through, low level I/O functions operate faster than their high level counterparts

A Low Level File-copy Program

#include "fcntl.h" 
#include "types.h" /* if present in sys directory use
"c:tc\\include\\sys\\types.h" */ 
#include "stat.h" /* if present in sys directory use 
 "c:\\tc\\include\\sys\\stat.h" */ 
main ( int argc, char *argv[ ] ) 
{ 
 char buffer[ 512 ], source [ 128 ], target [ 128 ] ; 
 int inhandle, outhandle, bytes ; 
 printf ( "\nEnter source file name" ) ; 
 gets ( source ) ; 
 inhandle = open ( source, O_RDONLY | O_BINARY ) ; 
 if ( inhandle == -1 ) 
 { 
 puts ( "Cannot open file" ) ; 
 exit( ) ; 
 } 
 printf ( "\nEnter target file name" ) ; 
 gets ( target ) ; 
 outhandle = open ( target, O_CREAT | O_BINARY | O_WRONLY, 
 S_IWRITE ) ; 
 if ( inhandle == -1 ) 
 { 
 puts ( "Cannot open file" ) ; 
 close ( inhandle ) ; 
 exit( ) ; 
 } 
 while ( 1 ) 
 { 
 bytes = read ( inhandle, buffer, 512 ) ; 
 if ( bytes > 0 ) 
 write ( outhandle, buffer, bytes ) ; 
 else
break ; 
 } 
 close ( inhandle ) ; 
 close ( outhandle ) ; 
}

Declaring the Buffer

The first difference that you will notice in this program is that we declare a character buffer,

char buffer[512] ;

This is the buffer in which the data read from the disk will be placed. The size of this buffer is important for efficient operation. Depending on the operating system, buffers of certain sizes are handled more efficiently than others

Opening a File

We have opened two files in our program, one is the source file from which we read the information, and the other is the target file into which we write the information read from the source file.

As in high level disk I/O, the file must be opened before we can access it. This is done using the statement,

inhandle = open ( source, O_RDONLY | O_BINARY ) ;

We open the file for the same reason as we did earlier—to establish communication with operating system about the file. As usual, we have to supply to open( ), the filename and the mode in which we want to open the file. The possible file opening modes are given below:

O_APPEND – Opens a file for appending

O_CREAT – Creates a new file for writing (has no effect
if file already exists)

O_RDONLY – Creates a new file for reading only
O_RDWR – Creates a file for both reading and writing
O_WRONLY – Creates a file for writing only
O_BINARY – Creates a file in binary mode
O_TEXT – Creates a file in text mode

These ‘O-flags’ are defined in the file “fcntl.h”. So this file must be included in the program while usng low level disk I/O. Note that the file “stdio.h” is not necessary for low level disk I/O. When two or more O-flags are used together, they are combined using the bitwise OR operator ( | )

The other statement used in our program to open the file is,

outhandle = open ( target, O_CREAT | O_BINARY | O_WRONLY,
S_IWRITE ) ;

Leave a Comment