This implementation is an adaptation of the DPDK basicfwd example application and MinimalDPDKExamples.
Let us now transmit some real data. In this example, we use a royalty-free book from Project Gutenberg. Since a selection had to be made, we will transmit a book with witty statements, which supposedly were said or written by Epictetus and translated into not-so-modern-day English, available at https://gutenberg.org/ebooks/871.txt.utf-8.
mmapmmap is a dangerous choice though, and it is used only for
demonstration purposes.
lseek(fd, 0, SEEK_END); repositions the read/write offset of fd. The directive
SEEK_END leads to the file offset being set to the size of the file (plus the specified offset, in this case
0). When successful, lseek returns the resulting file offset (in bytes).
read or write system calls (because we use mmap) so
the position of the file offset is not relevant for our code. For this reason, we don't have to set the file offset back to the
start.
n bytes to a file with mmap, the file size needs to be at least n times
larger than the number of bytes that were already written to the file.
ftruncate(fd, size) to set the size of the
file that is referenced by fd to size. This
man page for
ftruncate states:
"If the effect of ftruncate() is to increase the size of a memory object, it is unspecified whether the contents
of any mapped pages between the old end-of-file and the new are flushed to the underlying object.". So using ftruncate on an mmaped file and then writing to the newly created pages will lead to
unspecified behavior. Better unmap, then ftruncate, then map again.
ftruncate changes the end of file pointer in the inode
[source]. If this also triggers space allocation on
the physical disc depends on if the file system supports sparse files,
(the Ubuntu default filesystem is ex4, which
supports sparse files)
[source]. Resizing a file in the ext4 filesystem with ftruncate thus does not directly lead to the usage of more disk
space
[source]. Only when reading the new pages, the filesystem transparently converts the metadata that represents the empty blocks into
pages filled with zeros.
[source]
This synergies nicely with mmap, that also maps every page to the
zero-page (the page at address 0x0) natively, and only loads
the real page when it is really accessed. (Accessing the zero-page results in a page-fault that is caught by the OS and used to
load the real required page).