Memory-Mapped Files Programming language: c (under Linu) Modify the mmap-write a
ID: 3736481 • Letter: M
Question
Memory-Mapped Files
Programming language: c (under Linu)
Modify the mmap-write and mmap-read programs such that the former write n ran-
dom integers to the file and the latter reads and prints all integers. n is an argument to
both programs. It must be greater than zero. Include error handling when parsing the
argument n and for the system calls open() and mmap().
Example executions:
$ make
$ ./mmap-write /tmp/afile 10
$ cat /tmp/afile
-68 7 24 -10 48 24 -50 -97 52 -60
./mmap-read /tmp/afile 10
-68 7 24 -10 48 24 -50 -97 52 -60
$ ./mmap-write /tmp/afile 0
invalid number of integers
$ ./mmap-write /tmp/afile x
failed to parse number of integers
./mmap-read /tmp/invalidfile 10
open error: No such file or directory
--------------------------------------------------
mmap-write.c
/* Mapped-memory example - Writer program
*/
#include
#include
#include
#include
#include
#include
#include
#include "mmap.h"
/* return a uniformly generated random number in the range [low,high]
*/
int random_range (unsigned const low, unsigned const high) {
unsigned const range = high - low + 1;
return low + (int) (((double) range) * rand () / (RAND_MAX + 1.0));
}
/* Create and write to a shared file for communication with another process.
*
* argv[1] = file name
*
* Note: Error processing is omitted
*/
int main (int argc, char* const argv[]) {
int fd;
void* file_memory;
/* seed the random number generator */
srand (time (NULL));
/* open or create a file to hold an unsigned integer */
fd = open (argv[1], O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
/* write FILESIZE spaces */
for (int i=0; i write (fd, "", 1); /* write a NULL at EOF */
/* create the memory-mapping
1st param=start addr of mapping into memory, NULL means chosen by OS
2nd param=length of map (bytes)
3rd param=protection
4th param=options, MAP_SHARED used for interprocess communications
5th param=file descriptor of mapped file
6th param=offset from start of file where mapping starts
*/
file_memory = mmap (NULL, FILESIZE, PROT_WRITE, MAP_SHARED, fd, 0);
close (fd);
/* write a random integer to memory-mapped area */
sprintf((char*) file_memory, "%d ", random_range (-100, 100));
/* release the memory */
munmap (file_memory, FILESIZE);
}
--------------------------------------------------------------------
mmap-read.c
/* Mapped-memory example - Reader program
*/
#include
#include
#include
#include
#include
#include
#include "mmap.h"
int main (int argc, char* const argv[]) {
int fd;
void* file_memory;
int integer;
/* open the file */
fd = open (argv[1], O_RDWR, S_IRUSR | S_IWUSR);
/* create the memory-mapping */
file_memory = mmap (NULL, FILESIZE, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
close (fd);
/* read and print the integer */
sscanf (file_memory, "%d", &integer);
printf ("file contains: %d ", integer);
/* release the memory */
munmap (file_memory, FILESIZE);
return 0;
}
--------------------------------------------------------------------
mmap.h
/*(It has this line of code only)*/
#define FILESIZE 256
--------------------------------------------------------------------
Makefile
all: mmap-read.o mmap-write.o
gcc -o mmap-read mmap-read.o
gcc -o mmap-write mmap-write.o
mmap-read.o: mmap-read.c
gcc -c mmap-read.c
mmap-write.o: mmap-write.c
gcc -c mmap-write.c
clean:
rm -f *.o mmap-read mmap-write *~
Explanation / Answer
mapwrite.c
#include <stdlib.h> #include <stdio.h> #include <stdint.h> #include <fcntl.h> #include <sys/stat.h> #include <sys/mman.h> #include <unistd.h> int main(int argc, const char *argv[]) { const char *filepath = "/tmp/mmapped.bin"; int fd = open(filepath, O_RDONLY, (mode_t)0600); if (fd == -1) { perror("Error opening file for writing"); exit(EXIT_FAILURE); } struct stat fileInfo = {0}; if (fstat(fd, &fileInfo) == -1) { perror("Error getting the file size"); exit(EXIT_FAILURE); } if (fileInfo.st_size == 0) { fprintf(stderr, "Error: File is empty, nothing to do "); exit(EXIT_FAILURE); } printf("File size is %ji ", (intmax_t)fileInfo.st_size); char *map = mmap(0, fileInfo.st_size, PROT_READ, MAP_SHARED, fd, 0); if (map == MAP_FAILED) { close(fd); perror("Error mmapping the file"); exit(EXIT_FAILURE); } for (off_t i = 0; i < fileInfo.st_size; i++) { printf("Found character %c at %ji ", map[i], (intmax_t)i); } if (munmap(map, fileInfo.st_size) == -1) { close(fd); perror("Error un-mmapping the file"); exit(EXIT_FAILURE); } close(fd); return 0; }