Advanced Programming in the UNIX® Environment

(lily) #1
ptg10805159

530 Advanced I/O Chapter 14


We first open both files and then callfstatto obtain the size of the input file. We
need this size for the call tommapfor the input file, and we also need to set the size of
the output file.We callftruncateto set the size of the output file. If we don’t set the
output file’s size, the call tommapfor the output file is successful, but the first reference
to the associated memory region generates aSIGBUSsignal.
We then callmmapfor each file, to map the file into memory,and finally callmemcpy
to copy data from the input buffer to the output buffer.Wecopy at most 1 GB of data at
atime to limit the amount of memory we use (it might not be possible to map the entire
contents of a very large file if the system doesn’t have enough memory). Before
mapping the next sections of the files, we unmap the previous sections.
As the bytes of data arefetched from the input buffer (src), the input file is
automatically read by the kernel; as the data is stored in the output buffer (dst), the
data is automatically written to the output file.

Exactly when the data is written to the file depends on the system’s page management
algorithms. Some systems have daemons that write dirty pages to disk slowly over time. If
we want to ensurethat the data is safely written to the file, we need to callmsyncwith the
MS_SYNCflag beforeexiting.

Let’s comparethis memory-mapped file copy to a copy that is done by callingread
andwrite(with a buffer size of 8,192). Figure14.28 shows the results. The times are
given in seconds and the size of the file copied was 300 MB. Note that we don’t synch
the data to disk beforeexiting.

Linux 3.2.0(Intel x86) Solaris 10(SPARC)
User System Clock User System Clock
Operation

read/write 0.01 0.54 5.67 0.29 10.60 43.67
mmap/memcpy 0.08 0.65 22.54 1.89 8.56 38.42

Figure 14.28 Timing results comparingread/writeversusmmap/memcpy

For both Linux 3.2.0 and Solaris 10, the total CPU time (user+system) is almost the
same for both approaches. On Solaris, copying usingmmapandmemcpytakes more
user time but less system time than copying usingreadandwrite.OnLinux, the
results aresimilar for the user time, but the system time for usingreadandwriteis
slightly better than usingmmapandmemcpy.The two versions do the same work, but
they go about it differently.
The major difference is that withreadandwrite, we execute a lot moresystem
calls and do morecopying than withmmapandmemcpy.Withreadandwrite,we
copy the data from the kernel’s buffer to the application’s buffer (read), and then copy
the data from the application’s buffer to the kernel’s buffer (write). Withmmapand
memcpy, we copy the data directly from one kernel buffer mapped into our address
space into another kernel buffer mapped into our address space. This copying occurs as
aresult of page fault handling when we reference memory pages that don’t yet exist
(there is one fault per page read and one fault per page written). If the overhead for the
Free download pdf