LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Forking and Shared Memory program. (https://www.linuxquestions.org/questions/programming-9/forking-and-shared-memory-program-710584/)

the_satsuma_man 03-10-2009 04:37 PM

Forking and Shared Memory program.
 
Hi, im trying to make a program that forks, and reads its process ids into shared memory, a second process then reads the PIDs and outputs them to the screen. I am unsure how to do this as for each the second process seems to just be outputting a random number. any help would be much much appreciated.

process one (create segment, fork, put PIDs in segment)-
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>

#define SHMSZ 27

int main(void)
{
int shmid;
key_t key;
char *shm;
char *s;
int a;

key = 34569;

if((shmid=shmget(key, SHMSZ, IPC_CREAT |0666)) ==-1)
{
printf("shmget\n");
_Exit(1);
}
printf("Segment Made\n");

/*attach segment to data space */
if((shm = shmat(shmid,NULL,0)) == (char*)-1)
{
printf("Shmat\n");
_Exit(1);
}
printf("Segment Attatched\n");

fork();

a = getpid();
printf("Process ID: %d\n", a);
s = shm;
*s++ = a;
*s = 0;

/*wait for signal to end*/
while(*shm != '*')
{
sleep(1);
}


printf("%s\n",shm);
return 0;
printf("\n");
}


process 2 (reading shared memory and outputting PIDs)
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <stdlib.h>

#define SHMSZ 27

int main(void)
{
int shmid;
key_t key;
char *shm, *s;
key = 34569;

if((shmid = shmget(key, SHMSZ, 0666)) == -1)
{
printf("shmget\n");
exit(EXIT_FAILURE);
}
printf("Segment found");
printf("\n");
if((shm = shmat(shmid, NULL, 0)) == (char*)-1)
{
printf("shmat\n");
exit(EXIT_FAILURE);
}
printf("Segment attatched\n");

for(s = shm; *s !=0; s++)
{
putchar(*s);
putchar('\n');
}

*shm = '*';
return 0;
}

wje_lq 03-10-2009 05:21 PM

You have at least three problems.
  1. Since s is of type char *, each time you increment it you'll point to the next byte. But something of type pid_t occupies more than one byte. So you'll be trying to cram each pid into a single byte, and you'll get just the least significant eight bits of each pid. Solution: declare s as pid_t *. Then when you do these things:
    Code:

    s = shm                    /* in the first  program */
    for(s = shm; *s !=0; s++)  /* in the second program */

    do these things instead:
    Code:

    s = (pid_t *)shm                    /* in the first  program */
    for(s = (pid_t *)shm; *s !=0; s++)  /* in the second program */

  2. In your first program, the one that fork()s into two processes, the two processes share the same memory buffer, but each has its own local variables, including s. This means that each process will plant its pid in the same location. You'll end up with one pid. You can, if you wish, adopt the convention that the parent places its pid in the first location, and the child places its pid in the second. Sharing variable s (by, say, placing it in the shared memory area or by using a separate shared memory area for that) is only a good idea if you can synchronize things so that each processes accesses and changes that variable at a separate point in time. This can be done; how to do so is beyond the scope of what I'm currently writing.

  3. In your second program, when you pick up the data, even when you've corrected the type of s, you're picking it up in binary, just as you stored it. That's fine, but just don't expect it to be legible when you try to print it as is. Take your final loop and change it thus (assuming you've made the other changes I've recommended):
    Code:

    for(s = (pid_t *)shm; *s !=0; s++)
    {
      printf("%d\n",*s);
    }

Hope this helps.

Hko 03-10-2009 06:02 PM

You write the PID's to memory. They are int's. Then in the other process you print them as if you had stored a string!

After you fork the first program, both processes write at the same address in the shared memory segment. So in the reading proces, you will read only one of them: that last one that was written at that address. It is not defined which process will be the last to write.

(partly) fixed code: (changed lines are bold and commented)
Code:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>

#include <sys/types.h> /* added, was missing */
#include <unistd.h>    /* added, was missing */

#define SHMSZ 27

int main(void)
{
    int shmid;
    key_t key;
    pid_t *shm; /* pid_t not int */
    pid_t *s;  /* pid_t not int */
    pid_t a;    /* PID's should be of pid_t, not int (though int works) */

    key = 34569;

    if((shmid=shmget(key, SHMSZ, IPC_CREAT |0666)) ==-1)
    {
        printf("shmget\n");
        _Exit(1);
    }
    printf("Segment Made\n");

    /*attach segment to data space */
    if((shm = (pid_t*)shmat(shmid,NULL,0)) == (pid_t*)-1) /* pointer to pid_t, not char */
    {
        printf("Shmat\n");
        _Exit(1);
    }
    printf("Segment Attatched\n");

    fork();

    a = getpid();
    printf("Process ID: %d\n", a);
    s = shm;  /* Two processes writing at the same place in shared memory! */
    *s++ = a; /* So you will read only one of them in the other program */
    *s = 0;  /* impossible to know which one... Left it for you to fix this.. */

    /*wait for signal to end*/
    while(*shm != (pid_t)'*') /* quick n dirty fix ;-) */
    {
        sleep(1);
    }


    printf("%d\n", *shm);  /* print an pid_t (== some kind of integer) */
    return 0;
    /* printf("\n");  REMOVED, never executes after return */
}

Code:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <stdlib.h>

#define SHMSZ 27

int main(void)
{
    int shmid;
    key_t key;
    pid_t *shm, *s; /* pid_t, instead of int */

    key = 34569;
    if((shmid = shmget(key, SHMSZ, 0666)) == -1)
    {
        printf("shmget\n");
        exit(EXIT_FAILURE);
    }
    printf("Segment found");
    printf("\n");
    if((shm = (pid_t*)shmat(shmid, NULL, 0)) == (pid_t*)-1)  /* pointer to pid_t */
    {
        printf("shmat\n");
        exit(EXIT_FAILURE);
    }
    printf("Segment attatched\n");

    for(s = shm; *s !=0; s++)
    {
        printf("PID: %d\n", *s); /* Print pid_t (some kind of integer), not a string */
    }

    *shm = (pid_t)'*';  /* quick n dirty fix :-) */
    return 0;
}


the_satsuma_man 03-10-2009 06:06 PM

sorry, you posted at same time as me HKO, thank you both, ill have a crack on with it later. Im learing C as i do this so having quite a few difficulties.

Hko 03-10-2009 06:11 PM

Quote:

Originally Posted by the_satsuma_man (Post 3471203)
Im learing C as i do this so having quite a few difficulties.

Then maybe better to start with something easier than shared memory? OTOH, you did quite well if you're just starting to learn C...

the_satsuma_man 03-10-2009 07:51 PM

im having to do this for my course at college, some people have a better background knowledge so im jsut trying to keep up.


All times are GMT -5. The time now is 12:30 PM.