Thread: ftruncate, mmap, posix shared memory of changing size.

  1. #1
    Registered User
    Join Date
    May 2010
    Posts
    269

    ftruncate, mmap, posix shared memory of changing size.

    Hi,

    I have two processes that communicate over posix shared memory (only in one direction, one process is a writer, another is a reader). They do this for a number of iterations.

    This seems to be pretty straight forward when the data the writer is writing is always the same size. If in a later iteration the writer has to send over more data, I ftruncate the size to the new size.

    The question is then, for the reader, does the reader have to unmap and then mmap the file again?

    Thanks

  2. #2
    Registered User
    Join Date
    May 2010
    Posts
    269
    I have done a quick test and it seems to work fine. Yes, I know the sleeps lead to race conditions and all that. It's not the way the real code is written, it was just meant to be a quick and dirty test. It works, but I'm just wondering if this is expected behavior or if this is undefined behavior that's not guaranteed to work??

    Code:
    #include <stdio.h>                                                                                                                                                                                          
    #include <fcntl.h>                                                                                                                                                                                          
    #include <sys/shm.h>                                                                                                                                                                                        
    #include <sys/stat.h>                                                                                                                                                                                       
    #include <sys/mman.h>                                                                                                                                                                                       
    #include <stdlib.h>                                                                                                                                                                                         
    #include <string.h>                                                                                                                                                                                         
                                                                                                                                                                                                                
    void                                                                                                                                                                                                        
    do_writers()                                                                                                                                                                                                
    {                                                                                                                                                                                                           
        fprintf(stderr, "starting writer.\n");                                                                                                                                                                  
        int fd = shm_open("/example", O_CREAT | O_RDWR, 0666);                                                                                                                                                  
        int val1 = 8;                                                                                                                                                                                           
        int val2 = 16;                                                                                                                                                                                          
        int val3 = 32;                                                                                                                                                                                          
        ftruncate(fd, sizeof(val1));                                                                                                                                                                            
                                                                                                                                                                                                                
        char *buf = mmap(0, 8, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);                                                                                                                                      
        memcpy(buf, &val1, sizeof(val1));                                                                                                                                                                       
        sleep (15);                                                                                                                                                                                             
        ftruncate(fd, sizeof(val2) + sizeof(val3));                                                                                                                                                             
        memcpy(buf, &val2, sizeof(val2));                                                                                                                                                                       
        memcpy(&buf[sizeof(val2)], &val3, sizeof(val3));                                                                                                                                                        
        sleep (15);                                                                                                                                                                                             
        fprintf(stderr, "writer leaving.\n");                                                                                                                                                                   
    }                                                                                                                                                                                                           
                                                                                                                                                                                                                
    void                                                                                                                                                                                                        
    do_readers()                                                                                                                                                                                                
    {                                                                                                                                                                                                           
        fprintf(stderr, "starting reader.\n");                                                                                                                                                                  
        int val1, val2, val3;                                                                                                                                                                                   
        int fd = shm_open("/example", O_RDONLY, 0666);                                                                                                                                                          
        while (fd == -1) {                                                                                                                                                                                      
            sleep(1);                                                                                                                                                                                           
            fd = shm_open("/example", O_RDONLY, 0666);                                                                                                                                                          
            fprintf(stderr, "reader trying and waiting.\n");                                                                                                                                                    
        }                                                                                                                                                                                                       
                                                                                                                                                                                                                
        char *buf = mmap(0, sizeof(val1), PROT_READ, MAP_SHARED, fd, 0);                                                                                                                                        
        memcpy(&val1, buf, sizeof(val1));                                                                                                                                                                       
        fprintf(stderr, "reader so far: %d\n", val1);                                                                                                                                                           
        sleep(20);                                                                                                                                                                                              
        memcpy(&val2, buf, sizeof(val2));                                                                                                                                                                       
        memcpy(&val3, &buf[sizeof(val2)], sizeof(val3));                                                                                                                                                        
                                                                                                                                                                                                                
        fprintf(stderr, "Reader read: %d %d %d\n", val1, val2, val3);                                                                                                                                           
                                                                                                                                                                                                                
    }                                                                                                                                                                                                           
                                                                                                                                                                                                                
    int main(int argc, char **argv)                                                                                                                                                                             
    {                                                                                                                                                                                                           
        if (argc != 2) {                                                                                                                                                                                        
            fprintf(stderr, "stupid <mode> \n");                                                                                                                                                                
            return -1;                                                                                                                                                                                          
        }                                                                                                                                                                                                       
        int mode = atoi(argv[1]);                                                                                                                                                                               
        if (mode == 0) {                                                                                                                                                                                        
            do_writers();                                                                                                                                                                                       
        }                                                                                                                                                                                                       
        else {                                                                                                                                                                                                  
            do_readers();                                                                                                                                                                                       
        }                                                                                                                                                                                                       
        return 1;                                                                                                                                                                                               
    }

  3. #3
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    Well, it must be wrong on some level since your reader is only mapping the size of an int but ultimately reads the size of two ints.

    I always thought that mappings should be a multiple of the page size (typically 4096). To get the page size you can use getconf PAGESIZE from the command line and sysconf(_SC_PAGESIZE) in a program. Maybe if you map something less than the page size you actually get a full page.

    What does ll /dev/shm/example show for the file size?

    Your reader could fstat the object to see if it actually sees the change in size.

    BTW, the code you posted has hundreds of extra spaces on each line after the visible text.

    And you're returning 1 (failure) at the end instead of the usual 0.

  4. #4
    Registered User
    Join Date
    May 2010
    Posts
    269
    Quote Originally Posted by algorism View Post
    Well, it must be wrong on some level since your reader is only mapping the size of an int but ultimately reads the size of two ints.

    I always thought that mappings should be a multiple of the page size (typically 4096). To get the page size you can use getconf PAGESIZE from the command line and sysconf(_SC_PAGESIZE) in a program. Maybe if you map something less than the page size you actually get a full page.

    What does ll /dev/shm/example show for the file size?

    Your reader could fstat the object to see if it actually sees the change in size.

    BTW, the code you posted has hundreds of extra spaces on each line after the visible text.

    And you're returning 1 (failure) at the end instead of the usual 0.
    That's a good point actually, both about not doing subsequent mmaps, and the page size. I think it's working because mmap will map a multiple of the page size, so it seems it's getting one page size.

    I need to do 2 mmaps for this example it seems.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Initialize a 1D or 2D array in shared memory (POSIX)
    By Louis Sutter in forum C Programming
    Replies: 5
    Last Post: 12-08-2014, 03:12 PM
  2. Segment Fault with shared memory set using mmap
    By AKalair in forum C Programming
    Replies: 12
    Last Post: 11-18-2011, 02:20 PM
  3. Posix shared memory Q
    By homer_3 in forum C Programming
    Replies: 10
    Last Post: 03-01-2010, 09:13 PM
  4. Posix shared memory
    By rutledmj in forum C Programming
    Replies: 2
    Last Post: 10-04-2009, 09:42 PM
  5. BSD mmap for shared memory - am I right?
    By sean in forum Linux Programming
    Replies: 21
    Last Post: 03-09-2009, 01:57 PM

Tags for this Thread