LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 03-10-2009, 04:37 PM   #1
the_satsuma_man
LQ Newbie
 
Registered: Feb 2009
Posts: 8

Rep: Reputation: 0
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;
}
 
Old 03-10-2009, 05:21 PM   #2
wje_lq
Member
 
Registered: Sep 2007
Location: Mariposa
Distribution: FreeBSD,Debian wheezy
Posts: 811

Rep: Reputation: 178Reputation: 178
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.
 
Old 03-10-2009, 06:02 PM   #3
Hko
Senior Member
 
Registered: Aug 2002
Location: Groningen, The Netherlands
Distribution: Debian
Posts: 2,536

Rep: Reputation: 111Reputation: 111
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;
}

Last edited by Hko; 03-10-2009 at 06:05 PM.
 
Old 03-10-2009, 06:06 PM   #4
the_satsuma_man
LQ Newbie
 
Registered: Feb 2009
Posts: 8

Original Poster
Rep: Reputation: 0
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.

Last edited by the_satsuma_man; 03-10-2009 at 06:12 PM. Reason: Slow post.
 
Old 03-10-2009, 06:11 PM   #5
Hko
Senior Member
 
Registered: Aug 2002
Location: Groningen, The Netherlands
Distribution: Debian
Posts: 2,536

Rep: Reputation: 111Reputation: 111
Quote:
Originally Posted by the_satsuma_man View Post
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...

Last edited by Hko; 03-10-2009 at 07:48 PM.
 
Old 03-10-2009, 07:51 PM   #6
the_satsuma_man
LQ Newbie
 
Registered: Feb 2009
Posts: 8

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


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Linux shared memory segment access problem and x86 Virtual Memory layout. regmee Linux - Kernel 1 08-23-2008 01:11 AM
Difference between resident memory,shared memory and virtual memory in system monitor mathimca05 Linux - Newbie 1 11-11-2007 05:05 AM
is shared memory expandable in memory size? Thinking Programming 4 08-16-2005 10:57 AM
Perl forking and memory allocation barkers Linux - Software 4 04-27-2005 07:04 AM
Starting a forking program in terminal Ztyx Linux - General 2 11-09-2002 06:06 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 02:11 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration