The file_sys_example.cpp on Canvas opened an existing
input file for reading. It also created an output file for writing
the data read from the input file. It used the read and write
system calls. The input file we used was 68 bytes.
Now we will use memory mapped files instead of the read
and write. Also now the input file, inFile.txt will be of size 1
GB.
Create an input text file, called inFile.txt of size 1
GB by typing (and then pressing enter) the following command on the
terminal:
yes This is what my input file has...| head -c 1GB
>> inFile.txt
Note: The inFile.txt is 1 GB. Don’t bother opening to
see the file what it contains. Instead run stat command from
terminal to check its size. If you are curious to see what the yes
command does, try running the following command by creating a
smaller file:
yes This is what my input file has...| head -c 1KB
>> testFile.txt
and then open testFile.txt to look at it.
Now, start from the given mmap.cpp on Canvas. The stats
struct object is getting the file size.
Add to this program, the functionality of reading all
data from inFile.txt and writing to an output File. The output file
is to be created from within the program using creat. If creat does
not work, you can create a blank output file beforehand. And open
that file in the program.
Note that currently in mmap.cpp, only pagesize (4096
bytes) amount of data is being mapped to RAM. Now your file is 1
GB. In this project, you should map only 100 pages at a time. You
just have to figure out how to map the entire 1 GB file data in
chunks of 100 pages. Hint: Use a for or while loop.
Additionally, in mmap.cpp, you are not writing to an
output file. Add the functionality of writing the mapped data to an
output file, but not using a plain “write” system
call.
Hint: Use a combination of mmap and memcpy for this.
Also remember that the OS creates a backup of pages being modified
in the memory.
Answer the following briefly in a few sentences in
answer.txt.
Are the files in your program sharing the same memory
region ?
Should they ? Justify your answer.
(Note that you should not use read and write system
calls for this project. In fact, you should not be using “any
other” system calls / functions for this project, except of course
the open, creat, mmap, munmap, memcpy.)
Compile the program:
clang++ mmap.cpp -o test
Run the program:
./test inFile.txt outFile.txt
file_sys_example.cpp:
#include <sys/types.h>
#include <iostream>
#include <fcntl.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
using namespace std;
#define BUF_SIZE 4096 //
use a buffer size of 4096 bytes
#define OUTPUT_MODE 0700 // protection
bits for output file
int main(int argc, char* argv[])
{
int in_fd, out_fd, rd_count, wt_count;
char buffer[BUF_SIZE];
if (argc != 3) {
cout << "\n" << "enter
input file name, output file name: pgm will exit otherwise"
<< "\n";
exit(1);
}
// Open the input file and create the output
file
in_fd = open(argv[1], O_RDONLY); // open the input
file
if (in_fd < 0) {
cout << "\n" << "input file
cannot be opened" << "\n";
exit(1); //
if it cannot be opened, exit
}
out_fd = creat(argv[2], OUTPUT_MODE); // create
the output file
if (out_fd < 0) {
cout << "\n" << "output
file cannot be created" << "\n";
exit(1); //
if it cannot be created, exit
}
// Copy loop
while (true) {
rd_count = read(in_fd, buffer,
BUF_SIZE);
if (rd_count <= 0) { // if
end of file or error
break;
}
/*cout<<"\n
"<<"counting.......";
cout<<"\n"<<buffer;*/
wt_count = write(out_fd, buffer,
rd_count);
if (wt_count <= 0) { // if
error
cout << "\n"
<< "error on writing...exiting" << "\n";
exit(1);
}
}
close(in_fd);
close(out_fd);
if (rd_count == 0) { // no error on last
read
exit(0); //
successfully exit
}
else {
exit(1); // error on
last read
}
}
----------------------------------------------------------------------------
mmap.cpp
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
using namespace std;
int main(int argc, char** argv)
{
/* Make sure the command line is correct
*/
if (argc < 2)
{
cout << "FILE NAME
missing\n";
exit(1);
}
/* Open the specified file */
int fd = open(argv[1], O_RDWR);
if (fd < 0)
{
cout << "\n" <<
"input file cannot be opened" << "\n";
exit(1);
}
struct stat stats;
if (stat(argv[1], &stats) == 0)
cout << endl <<
"file size " << stats.st_size;
else
cout << "Unable to get
file properties.\n";
/* Get the page size */
int pagesize = getpagesize();
cout << endl << "page size is "
<< pagesize << "\n";
/* map the file into memory */
char* data = (char*)mmap(NULL, pagesize,
PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
/* Did the mapping succeed ? */
if (!data)
{
cout << "\n" <<
"mapping did not succeed" << "\n";
exit(1);
}
/* Print the whole file character-by-character
*/
for (int fIndex = 0; fIndex < pagesize;
++fIndex)
{
cout <<
data[fIndex];
}
cout << endl;
/* Write a string to the mapped region */
/* memcpy(data, "Hello world, this is a test\n",
sizeof("Hello world, this is a test"));*/
/* Unmap the shared memory region */
munmap(data, pagesize);
/* Close the file */
close(fd);
return 0;
}
The file_sys_example.cpp on Canvas opened an existing input file for reading. It also created an output file for writing
-
- Site Admin
- Posts: 899603
- Joined: Mon Aug 02, 2021 8:13 am