Forcing Data to Media

When the UNIX file system objects were reviewed in Chapter 2, it was documented that file systems use block raw devices. This is done so that disk accesses are buffered in the UNIX disk cache for performance reasons. However, a disk cache presents certain dangers for your valuable data.

When a file is opened, written to, and closed to update its contents, changes may still be sitting in disk cache in the kernel's memory for quite some time. If the system suddenly loses power or your UNIX kernel panics for some other reason, those changes may never be written to your disk media. When you examine the file after such a catastrophe, you'll discover that the file's content is not what you had thought it was. There must be a way to force critical data to be written to the intended media immediately.

The sync(2) Function

A popular command for those writing a lot of source code under UNIX is the sync(8) command (on many UNIX platforms it is sync(1M)). After making several changes to shell scripts or to source code, it is nice to be able to say

$ sync

and know that all your changes are being written to the disk media. After the command finishes, you can rest assured that your work will not be lost if the lights should suddenly go out.

The sync(8) command ends up calling the system call sync(2). The function synopsis is as follows:

#include <unistd.h>

void sync(void);

As you can see, this function takes no arguments and returns no values. It couldn't be simpler to use.

If you should find that the sync(8) command is restricted on the system on which you have an account, you can easily write one of your own. Listing 4.4 shows how simple it is to do so.

Code Listing 4.4. sync.c—Building Your Own sync Command
1:   /* sync.c */
2:
3:   #include <unistd.h>
4:
5:   int
6:   main(int argc,char **argv) {
7:
8:       sync();
9:       return 0;
10:}

The following shows the program being compiled and run:

$ make sync
cc -c -D_POSIX_C_SOURCE=199309L -Wall sync.c
cc sync.o -o sync
$ ./sync
$

If you were running this program on your own computer, then you might have heard some disk activity when the command was invoked. Perhaps you watched the disk activity light instead. In any case, this was the result of all unwritten changes being forced out to the disk media.

The Disadvantages of sync(2)

The sync(8) command is sometimes restricted in shared UNIX environments to prevent its abuse. For example, an abusive user can issue the following command:

$ while true; do sync; sleep 1; done
						

This shell command would be forcing disk writes every second. Of course, this would hurt the performance of the disk cache.

Assume you have an application that updates a custom database, which is stored within a file. At certain points in the update process, you will want to make certain that these changes are forced out to disk. However, to issue a frequent call to sync(2) would affect other users too much. The solution is found in the fsync(2) function.

The fsync(2) Function

This function provides the power of sync(2) but limits the scope to one file. See the function synopsis:

#include <unistd.h>

int fsync(int fd);

This function simply accepts the file descriptor as an argument, which indicates the file for which all cached changes must be written out. Note that if several processes are modifying the same file, all changed data for that file is written out. Changes are not traced back to a particular file descriptor and kept separate.

The fsync(2) function returns zero if successful and -1 if an error occurs. One of the more interesting possible errors is EIO, which will tell your application that an I/O error has occurred, while it was forcing the written data out to disk.

Tip

If you need to be certain that all data changes for a file have been successfully written to the disk media, call fsync(2) prior to calling close(2). Without a call to fsync(2), the close(2) call may succeed, since the changes remain in the disk cache. Later the UNIX kernel may discover that the cached changes cannot be written out due to a media error. By this time, your application not only is unaware of the problem, it also cannot take corrective action.

Calling fsync(2) prior to close(2) allows your application to decide what to do about media problems.


..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
52.14.172.93