Share segment

This is a discussion on Share segment within the C Programming forums, part of the General Programming Boards category; Here is my code. There is still a mess and some checks missing. But this is not my problem. Code: ...

  1. #1
    ch4
    ch4 is offline
    Newbeer ch4's Avatar
    Join Date
    Jan 2007
    Posts
    142

    Share segment

    Here is my code.
    There is still a mess and some checks missing. But this is not my problem.
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <time.h>
    #include <unistd.h>
    #include <sys/wait.h>
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/shm.h>
    
    #define BUF_SIZE 128
    
    typedef struct
    {
     int gifts_num;
     char **Gifts;
    
    }bucket;
    
    int getline(FILE *,char *,int );
    
    
    int main(int argc, char **argv)
    {
     int m=20,i,j,addr_num,id,err=0;
     int f_id;
     
     char address[BUF_SIZE],ch,l[10];
    
     bucket **buckets,**mem;
    
     FILE *Input;
     
    /////////////////////////////-A Part - /////////////////////
    
         //Allocate memory for bucket array
         buckets = malloc(m*sizeof(bucket*));
         if(buckets==NULL)
         {
           fprintf(stderr,"Allocation error.\n");
           exit(1);
         }
    
         for(i=0;i<m;i++)
         {
           buckets[i] = malloc(sizeof(bucket));
           if(buckets[i]==NULL)
           {
             fprintf(stderr,"Allocation error.\n");
             exit(1);
           }
         }
    
         //Open input file
         Input = fopen("prj3.txt","rb");
         if(Input==NULL)
         {
            fprintf(stderr,"Cannot open : %s\n","prj3.txt");
            exit(1);
         }
    
         //Count addresses
         addr_num=0;
         while(ch!=EOF)
         {
            ch=getc(Input);
            if(ch=='\n')
               addr_num++;
         }
    
         //Allocate memory for bucket addresses
         for(i=0;i<m;i++)
         {
            buckets[i]->gifts_num=0;
            buckets[i]->Gifts = malloc(addr_num*sizeof(char *));
            if(buckets[i]->Gifts==NULL)
            {
              fprintf(stderr,"Allocation error.\n");
              exit(1);
            }
    
            for(j=0;j<addr_num;j++)
            {
              buckets[i]->Gifts[j] = malloc(BUF_SIZE*sizeof(char));
              if(buckets[i]->Gifts[j]==NULL)
              {
                fprintf(stderr,"Allocation error.\n");
                exit(1);
              }
            }
         }
    
         //Get back to the start of the file
         fseek(Input,0,SEEK_SET);
    
         //Set seed of rand
         srand((unsigned int)time(NULL));
    
         //Read file and store it to buckets
         for(i=0;i<addr_num;i++)
         {
            //Get line as string
            getline(Input,address,BUF_SIZE);
    
            //Choose a random bucket
            j=(rand() % ((m-1) - 0 + 1) + 0);
    
            //Copy address to bucket and increase bucket's gifts num
            strcpy(buckets[j]->Gifts[(buckets[j]->gifts_num)],address);
            (buckets[j]->gifts_num)++;
         }
    
         //Close input file
         fclose(Input);
    
    ////////////////////////////-B Part - ////////////////////////////////
    
         // Make shared memroy segment
         id = shmget(IPC_PRIVATE,sizeof(bucket **),0666);  //Wrong ???
         if (id == -1) 
    	perror ("Creation");
    
    
         // Attach the segment
         mem = shmat(id, (void*)0, 0);
         if ( (int)mem == -1) 
         	perror("Attachment.");
    
    
         mem = buckets;//Here is the hot part
         memcpy(); // ?????
    
    
        //Call here children processes by fork
    
         // Remove segment
         err = shmctl(id, IPC_RMID, 0);
         if (err == -1) 
         	perror ("Removal.");
    
    
    /////////////////////////////-C Part - /////////////////////////
    
         //Free buckets and their contents
         for(i=0;i<m;i++)
         {
           for(j=0;j<addr_num;j++)
               free(buckets[i]->Gifts[j]);
    
           free(buckets[i]->Gifts);
           free(buckets[i]);
         }
         free(buckets);
    
     return 0;
    }
    In the A Part i make an array of bucket structs, each of it has an array of strings.

    In the B Part (in which i have the problem) i want to allocate memory for a share segment in order children processes can access. But the problem is that i can't allocate the real size of all buckets.

    I read that share segments are fixed and i can't increase/decrease their size that's why i decided to make an array of buckets and then to copy it to Share Segment using memcpy, but at hot part of my code is obviously wrong.

    How can i make the SS with the appropriate size of all bucket array and their contents?
    How can i copy the bucket array to SS ?
    Is there a possible way ?

    In the C Part i free all those buckets and their content

    *Thanks in advance*
    Last edited by ch4; 12-28-2008 at 04:29 AM.

  2. #2
    ch4
    ch4 is offline
    Newbeer ch4's Avatar
    Join Date
    Jan 2007
    Posts
    142
    Ok i will change my question.

    How can i use a flexible SS ?

    I want to allocate Share Segment memory for an array of structs but i do not know from the beginning the size of Gifts of structs string array.

  3. #3
    ch4
    ch4 is offline
    Newbeer ch4's Avatar
    Join Date
    Jan 2007
    Posts
    142
    Ok i'll change my question again.
    Let's say that i have this struct
    Code:
    typedef struct
    {
     int gifts_num;
     char **Gifts;
    
    }bucket;
    I want to make a Share Segment with m(known from the beginning) array buckets with unknown number of strings each of it from the beginning.

    In the middle of the program i achieve the number of strings of each bucket but it is too late because i have already allocate the SS.

    Any ideas ?

  4. #4
    Registered User
    Join Date
    Oct 2001
    Posts
    62
    Idea 1: Let the shared memory segment have a pre-defined maximum size that must never be exceeded.

    Idea 2: Let the shared memory segment have an initial size and resize it if necessary. "Resize" means: Allocate a second shared memory segment, attach it, copy the data and delete the first one. Problem: How to tell the clients which memory segment they have to use.

  5. #5
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,417
    > id = shmget(IPC_PRIVATE,sizeof(bucket **),0666);
    Well you'll need to allocate all the data space as well.
    Simply allocating enough to store the root pointer to the data structure isn't enough.

    Also (IIRC), you can't store pointers directly inside shared memory, since you can't guarantee that it will be mapped to the same address in both processes.

    Something like this
    Code:
    typedef struct header {
        size_t bucket_offset;
        size_t nBuckets;
        size_t string_offset;
        size_t nStrings;
    } header;
    This you store at the start of the shared memory segment.

    Then you do something like
    Code:
    unsigned char ........ = shmat(id, (void*)0, 0);
    header *h = (header*)ss;
    bucket *b = (bucket*)&ss[h->bucket_offset];
    strings *s = (strings*)&ss[h->string_offset];
    Likewise, nested pointers become nested offsets, relative to some previously calculated pointer (say b or s in this example).
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  6. #6
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Salem View Post
    Also (IIRC), you can't store pointers directly inside shared memory, since you can't guarantee that it will be mapped to the same address in both processes.
    Yes, that would be what I would say too. Of coruse, there is no law of physics to prevent us from storing pointers in the shared memory - the problem becomes, however, that if the shared memory is located in some other place in the other process, the pointer points to some undefined portion of memory,

    That can happen whenever the OS for whatever reason decides to do put the shared memory at a different address in the other process - usually bacause the memory is used for something else [e.g. some other shared memory, heap memory or shared library code occupying the original shared memory space], but the OS has the right to decide where it goes with no motivation for it's decision.

    Where I work we recently had to change some code that is related to shared memory, where the owning process would pass pointers to the sharing processes. But a new memory manager in our embedded OS was not placing shared memory at the same place in every process [which by the way was never guaranteed, just HAPPENED to be the case with the old memory management code] - and of course we got "invalid memory access" problems all over those bits of code.

    One possible solution is to store the offset from the start of the shared memory as a placement of the pointer. But there are many other ways to solve that type of problem.

    Just "no pointers in shared memory" if you want your code to be robust.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  7. #7
    ch4
    ch4 is offline
    Newbeer ch4's Avatar
    Join Date
    Jan 2007
    Posts
    142
    Thank all of you.

  8. #8
    Registered User
    Join Date
    Apr 2008
    Posts
    395
    A quick note: you _can_ force to map a shared memory block at a given address (and it's posix compliant) using shm_open() and mmap() with the appropriate MAP_FIXED option. mmap() is free to fail, if the provided address does not suit the system. The recommended technique* is to let the system map the segment wherever it sees fits for the very first process and then use this address for the other processes (the address will still be valid), in which case pointers stored in this shared block are ok for everyone. I did not check if it could be done with classic ipc objects (via shmget etc.) but if you say it cannot be done, so be it.

    * posix.4 programming book...a bit old but interesting

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Mutex and Shared Memory Segment Questions.
    By MadDog in forum Linux Programming
    Replies: 14
    Last Post: 06-20-2010, 04:04 AM
  2. Replies: 16
    Last Post: 03-08-2008, 04:42 AM
  3. execute a code in data segment...
    By ravindragjoshi in forum Windows Programming
    Replies: 1
    Last Post: 06-12-2007, 11:43 PM
  4. Declare an array in the BSS segment
    By ^xor in forum C Programming
    Replies: 1
    Last Post: 05-27-2005, 05:12 PM
  5. C++ Share Interface Problem
    By Morphios in forum C++ Programming
    Replies: 0
    Last Post: 04-28-2003, 07:30 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21