7

I've got 2 processes (Client and Server) that are communicating through shared memory.

I need to create a 2D Array that is Dynamic (based on parameters). The array is stored in a struct and then written to the shared segment.

I can write the array to the shared memory, but cannot retrieve it from the other process.

Client Code:

struct shared_use_st {
    int     written_by_you;
    int     **PID_PRI_array;
};
            /* Prepare Dynamic 2D array */
        data_store = malloc(/*ROWS*/ 5 * sizeof(int*));
        for(i=0;i<5; i++)
            data_store[i] = malloc(/*COLS*/ 2 * sizeof(int));


        /* Prepare Dynamic 2D array - Shared Memory Seg */
        shared_stuff->PID_PRI_array = malloc(/*ROWS*/ 5 * sizeof(int*));
        for(i=0;i<5; i++)
            shared_stuff->PID_PRI_array[i] = malloc(/*COLS*/ 2 * sizeof(int));


        /* Write PID and PRI to data_store array */
        data_store[0][0] = pid;
        data_store[0][1] = 1;

        data_store[1][0] = 12345;
        data_store[1][1] = 2;

        data_store[2][0] = 12346;
        data_store[2][1] = 3;

        data_store[3][0] = 12347;
        data_store[3][1] = 4;   

        data_store[4][0] = 12348;
        data_store[4][1] = 5;   

            for(i=0;i<5;i++){
                for(x=0;x<=1;x++){
                    shared_stuff->PID_PRI_array[i][x] = data_store[i][x];
                }
            }

Server Code:

    for(i=0;i<5;i++){
    printf("PID: %d, PRI:%d\n", shared_stuff->PID_PRI_array[i][0], shared_stuff->PID_PRI_array[i][1]);              
}

I get a "Segmentation Fault" error.

Thanks.

Jake Evans
  • 978
  • 5
  • 13
  • 33

1 Answers1

6

Even if your shared_stuff object is in shared memory, you are not writing the array to shared memory. You are allocating space with malloc, writing data to that space, and then putting pointers to that space into shared_stuff. malloc allocates space within the current process‘ normal address space, not in a shared memory segment you have created. You need to write the array contents to the shared memory.

Presuming there is enough space for the array within the shared memory segment, you will have to manage the addresses yourself, not using malloc. (If there is not enough space, you must make the shared memory segment larger or convey the information in pieces over time.)

You can place a variable-length array within the shared memory segment as follows.

First, define a structure that contains all the “management” information you need, such as the array sizes:

struct StuffStruct
{
    size_t NumberOfRows, NumberOfColumns;
    … Other information as desired.
};

Create a pointer to that structure and set it to point to the shared memory segment:

struct StuffStruct *Stuff = shm;    // shm contains the address from shmat, performed previously.

Create a pointer to an array with the desired number of columns and set it to point into the shared memory segment after the initial structure:

int (*data_store)[NumberOfColumns] = (int (*)[NumberOfColumns]) ((char *) Stuff + sizeof *Stuff);

(Note for C purists: Yes, the C standard does not guarantee what happens when you do pointer arithmetic like this. However, any implementation providing shared memory support must provide support for this sort of pointer arithmetic.)

Note that sizeof *Stuff + NumberOfRows * NumberOfColumns * size(int) must be no greater than the size of the shared memory segment. Otherwise you will overrun the shared memory segment in the next step.

For the next step, fill the array with data: Assign values to the elements of data_store as for a normal two-dimensional array.

In the server, set Stuff the same way. Then, after the client has written the shared memory segment, read the numbers of rows and columns from Stuff. Then set data_store the same way. Then read from data_store.

fodma1
  • 3,485
  • 1
  • 29
  • 49
Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • Sorry, forgot to mention I have this above; `shared_stuff = (struct shared_use_st *)shm;` Where SHM is the result of shmat;
    `/* Attatch segment to data space */ if((shm = shmat(shmid,NULL,0)) == (char *)-1) { perror("shmat"); _Exit(1); } printf("[+] Segment Attatched\n");` I wrote this test piece of code in the client, and it outputs exactly what I expect; `printf("TEST\n\n"); for(i=0; i < 5; i++) printf("PID: %d, PRI:%d\n", shared_stuff->PID_PRI_array[i][0],shared_stuff->PID_PRI_array[i][1]); `
    – Jake Evans Feb 26 '13 at 21:53
  • Your comment is consistent with my diagnosis. The code in the client prints what you expect because the data is at the expected places in the client’s address space. However, the data is not visible in the server’s address space. Only the structure directly pointed to by `shared_stuff` is in the shared segment, because you set `shared_stuff` to point to the shared segment. The pointers inside that structure point to places outside the shared segment, places allocated by `malloc`. Because those places are outside the shared segment, they are not visible in the server process. – Eric Postpischil Feb 26 '13 at 22:17
  • I see. If I do; `shared_stuff->written_by_you = 1;` this is visible by the server process, because it isn't pointing outside the structure's address space, right? How would I go about solving the problem at hand? Thanks! – Jake Evans Feb 26 '13 at 22:23
  • Thanks Eric! That reply has been a great help! I've corrected a couple of Syntax errors in the post ;-). Just a couple of things I'm still a bit confused about... How do I set the values of NumberOfColumns and NumberOfRows in the Stuff Structure? Stuff->NumberOfRows = 5 doesn't seem to be working properly? Also you mentioned the shared memory segment has to be the same size as the formula you posted, however, how does the server know what size this is going to be since it's dynamic? – Jake Evans Feb 26 '13 at 23:29
  • The numbers of rows and columns are up to you. Your problem statement says they are based on parameters, so it is up to you to set them and use them. The shared memory size either has to be large enough to handle any size array you will have, or you have to get the array dimensions then create a shared memory segment that is large enough. `shmat` in the server will assign all of the space necessary; it gets the shared memory size from internal system information, and the server just needs to use the array dimensions in the natural way. – Eric Postpischil Feb 26 '13 at 23:52
  • The parameters will be set when the client is executed (./client 5 10) for example. Ideally the server does not need to have any parameters passed to it, but rather the client sorts out all the memory allocations etc. Sorry for the confusion. – Jake Evans Feb 26 '13 at 23:58