i have assignment requiring me write multi-processed program works memory-mapped file containing string of characters. after parent process maps file memory, spawns 2 children processes modify file. child 1 outputs contents of file, converts file's contents upper case equivalent, outputs file's new contents. child 2 waits 1 second let child 1 finish, outputs file's contents, removes hyphen " - " characters, outputs file's new contents. problem both child processes after first displaying file's contents, processes attempt modify contents of file, neither child outputs file's new contents. no errors when running or compiling can't find out problem is. , of course, i'm new memory mapping feel free let me know i'm doing wrong. here source code:
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <sys/mman.h> #include <fcntl.h> #include <sys/stat.h> #include <signal.h> #include <string.h> int main (int argc, char *argv[]) { struct stat buf; int fd, length, status, i, j, k; char *mm_file; char *string = "this lowercase-sentence."; length = strlen(string); fd = open(argv[1], o_creat | o_rdwr, 0666); //creates file name given @ command line write(fd, string, strlen(string)); //writes string modified file fstat(fd, &buf); //used determine size of file //establishes mapping if ((mm_file = mmap(0, (size_t) buf.st_size, prot_read|prot_write, map_shared, fd, 0)) == (caddr_t) - 1) { fprintf(stderr, "mmap call fails\n"); } //initializes child processes pid_t mc0; pid_t mc1; //creates series of child processes share same parent id if((mc0 = fork()) == 0) { printf("child 1 %d reads: \n %s\n", getpid(), mm_file); //{convert file content uppercase string}; (i = 0; < length; i++) { string[i] = toupper(string[i]); } //sync new contents file msync(0, (size_t) buf.st_size, ms_sync); printf("child 1 %d reads again: \n %s\n", getpid(), mm_file); exit(exit_success); //exits process } else if ((mc1 = fork()) == 0) { sleep(1); //so child 2 perform task after child 1 finishes ("child 2 %d reads: \n %s\n", getpid(), mm_file); //{remove hyphens} (j = 0; j < length; i++) { if (string[i] == '-') { string[i] = ' '; } } //sync new contents file msync(0, (size_t) buf.st_size, ms_sync); printf("child 2 %d reads again: \n %s\n", getpid(), mm_file); exit(exit_success); //exits process } // waits child processes finish before continuing. waitpid(mc0, &status, 0); waitpid(mc1, &status, 0); return 0; }
then output follows:
**virtual-machine:~$** ./testt file child 1 3404 reads: lowercase-sentence. child 2 3405 reads: lowercase-sentence. child processes have finished. exiting program. **virtual-machine:~$**
but desired result be:
**virtual-machine:~$** ./testt file child 1 3404 reads: lowercase-sentence. child 1 3404 reads again: lowercase-sentence. child 2 3405 reads: lowercase-sentence. child 2 3405 reads: lowercase sentence. child processes have finished. exiting program. **virtual-machine:~$**
any appreciated.
there few errors here. firstly, write file , map memory. mapping correct, writing not. if string has n characters, have write n+1 characters, since strings in c null-terminated. have n, c string functions try access @ least 1 more byte, not good. , if 1 byte not null (zero), functions go further. in debug more might zeroed, in optimized code not. have use
write(fd, string, strlen(string)+1); //writes string modified file
then this:
(i = 0; < length; i++) { string[i] = toupper(string[i]); }
this changes data referred pointer string
, has nothing memory mapped file. should have:
(i = 0; < length; i++) { mm_file[i] = toupper(mm_file[i]); }
the same second child process.
also msync()
call bit suspect. give memory address 0, not within memory mapped file, not sync contents. need call msync(mm_file, (size_t) buf.st_size, ms_sync);
also, many compilers put constant strings read-only memory, might not allowed change data referred string
. in case seems allowed.
do remember, length of file 1 byte larger length of string, use variables correctly. do, since sync file file length , handle string string length.