shmget confusion?????


 
Thread Tools Search this Thread
Top Forums Programming shmget confusion?????
# 1  
Old 01-30-2012
shmget confusion?????

Hi friends,
This is a small program built on the concept of shared memory. The producer is a separate program and process, and the consumer is a seperate program and process. Both are executed under the same user account. The producer takes some string from the user and adds that string to the shared memory, and the consumer reads that string. You can see my code here.

Code:
 
$ cat producer.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
#define MEM_SZ 4096
struct shared_use_st
{
        int written_by_you;
        char some_text[MEM_SZ];
};
int main()
{
int running = 1;
void *shared_memory = (void *)0;
struct shared_use_st *shared_stuff;
char buffer[MEM_SZ];
int shmid;
shmid = shmget((key_t)1234, MEM_SZ, 0666 | IPC_CREAT);
if(shmid == -1)
{
printf("shmget failed\n");
exit(EXIT_FAILURE);
}
shared_memory = shmat(shmid, (void *)0, 0);
if(shared_memory == (void *)-1)
{
printf("\nshmat failed\n");
exit(EXIT_FAILURE);
}
printf("Memory attached at %x\n", (int)shared_memory);
shared_stuff = (struct shared_use_st *)shared_memory;
while(running)
{
        while(shared_stuff->written_by_you == 1)
        {
        sleep(1);
        printf("\nwaiting for client...\n");
        }
        printf("Enter some text: ");
        fgets(buffer, MEM_SZ, stdin);
        strcpy(shared_stuff->some_text, buffer);
        shared_stuff->written_by_you = 1;
        if(strncmp(buffer, "end", 3) == 0)
        {
                running = 0;
        }
}
if(shmdt(shared_memory) == -1)
{
printf("shmdt failed\n");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}


Code:
 
$ cat consumer.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define MEM_SZ 4096
struct shared_use_st
{
int written_by_you;
char some_text[MEM_SZ];
};
int main()
{
        int running = 1;
        void *shared_memory=(void *)0;
        struct shared_use_st *shared_stuff;
        int shmid;
        srand((unsigned int)getpid());
        shmid = shmget((key_t)1234, MEM_SZ, 0666 | IPC_CREAT);
        if(shmid ==-1)
        {
        printf("shmget failed\n");
        exit(EXIT_FAILURE);
        }
        shared_memory = shmat(shmid, (void *)0, 0);
        if(shared_memory == (void *)-1)
        {
        printf("\nshmat failed\n");
        exit(EXIT_FAILURE);
        }
printf("Memory attached at %x\n", (int)shared_memory);
shared_stuff=(struct shared_use_st *)shared_memory;
shared_stuff->written_by_you = 0;
while(running)
{
if(shared_stuff->written_by_you)
{
printf("You wrote: %s", shared_stuff->some_text);
sleep( rand()%4);
shared_stuff->written_by_you = 0;
if(strncmp(shared_stuff->some_text, "end", 3)==0)
{
running = 0;
}
}
}
if(shmdt(shared_memory)==-1)
{
        printf("shmdt failed\n");
        exit(EXIT_FAILURE);
}
if(shmctl(shmid, IPC_RMID, 0)==-1)
{
printf("shmctl(IPC_RMID)failed\n");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}

Now my question and confusion is.
1) Both producer and consumer create structures and shared memory spaces
2) Both are separate programs and seperate processes.
3) How do they know that a common memory space is shared between them, I mean we don't tell the consumer which part of memory is created by the producer, nor the producer is aware of the consumer's created memory.
4) Then how come the producer produces some string and the consumer gets that string.
Could you please throw some light on it. And when I change the first argument of shmget to
Code:
IPC_PRIVATE

, the program doesn't work then.
Could you please help me on this.
Looking forward to your kind replies.
Thanks in advance!
# 2  
Old 01-30-2012
First, I'm going to let you know that there is A LOT wrong with these programs. I'll go into a few things, then answer your questions:

1) First and foremost, an integer (shared_stuff->written_by_you) is not a proper synchronization primitive. Depending on architecture, it is quite possible that a change to this variable by either producer or consumer is never visible to the other. It is also possible that the variable be updated before the text (write re-ordering), which will cause corruption.

There are mutexes and condition variables (created with a process shared attribute) that are proper ways to synchronize shared memory access. There are also semaphores, which is the classic way of doing this. I suggest you look them up!

2) You're polling -- consider the loop in the consumer is eating many CPU cycles because it never sleeps if shared_stuff->written_by_you == 0. This is bad practice. Of course, considering you're not properly synchronizing, this is the least of your worries.

3) You're not creating the shared memory segment of the correct size. You should be using sizeof(struct shared_use_st) rather than MEM_SZ in your shmget call.

4) Consider putting struct shared_use_st in a header file both applications include -- also good practice.

There are probably many other things, but these strike me initially. Now, on to your questions:

1) Both producer and consumer create structures and shared memory spaces

Wrong, read "man shmget". If the key already exists, it'll return its ID. If it doesn't, it'll create it. If you want it to fail if the key already exists, and you use the IPC_EXCL flag, then it'll fail. You can NOT create two shared memory segments on a system with the same key! That's the point of the key.

2) Both are separate programs and seperate processes.

Yep.

3) How do they know that a common memory space is shared between them, I mean we don't tell the consumer which part of memory is created by the producer, nor the producer is aware of the consumer's created memory.

That's what shmat does. The shared memory space is created by the kernel (by shmget) in a place accessible across different process spaces. shmat maps that memory space into your process, hence allowing it to be shared.

Think of it like this: shmget looks up a particular shared memory segment by key, if it doesn't exist (and IPC_CREAT is specified) then it'll create one. If it's IPC_PRIVATE, then it'll just create a new one. When a new shared memory segment is created (or an existing one looked up) it gets a system identifier. When shmget succeeds this system identifier is what it returns. shmat takes as its first argument that system identifier (shmid) and maps that memory segment into your process space (assuming it has all the correct permissions). Thus, every process mapping that shmid into their process space sees the same shared memory.

I believe maybe running the "ipcs -m" command may help you understand. Once your shmget succeeds once, you'll see your key (1234) listed (which in hex is 0x000004D2) along with its shmid. It'll go away when all attached programs complete, as your program asks it to be removed by shmctl. You can also remove it manually via the ipcrm command (but, again, it can only be removed once all programs detach).

I also wonder if you're seeing the same "memory attached at" printfs and confusing what's really going on. Or, even different ones (which is quite possible as well) and confusing it even more so. You'd really have to understand how process memory is mapped in your particular O/S (and I'm not going to explain it to you) to "get it". But, just understand that shmat takes a memory region outside of your process space and maps it into your process space (similar to things like mmap).

4) Then how come the producer produces some string and the consumer gets that string.

See everything above -- also realize that due to some very large problems with your application, it's quite possible it doesn't get it. Not because of the shared memory, but because of your failure to correctly synchronize it (with a semaphore or mutex, etc).

5) And when I change the first argument of shmget to IPC_PRIVATE, the program doesn't work then.

man "shmget". IPC_PRIVATE creates an ID that is not accessible by a key. Therefore, in the case of IPC_PRIVATE you are indeed creating two different shared memory segments. Using IPC_PRIVATE requires passing the ID (returned by shmget) to everyone who is going to attach it (via shmat) so that shmat can attach that ID. This can be done by fork (because it'll have a copy of the ID) or by any other means of passing the value.

Last edited by DreamWarrior; 01-30-2012 at 06:39 PM..
Login or Register to Ask a Question

Previous Thread | Next Thread

9 More Discussions You Might Find Interesting

1. Shell Programming and Scripting

Confusion in hash

Hi folks, If a declare a direct hash , then the hash element works fine. my %test = ("test",1); print %test; print "\n"; Here in the above, the name of the hash is predeclared... Suppose now I need to create the hash elements dynamically in the for loop. $test="hash"; my... (1 Reply)
Discussion started by: scriptscript
1 Replies

2. Shell Programming and Scripting

confusion in use of exit 0

hi i am new to shell scripting. i was going thru the part option and arguments. on this section i fail to understand the use of exit 0 in below example . #!/bin/sh USAGE="Usage: $0 " case "$1" in -t) TARGS="-tvf $2" ;; -c) TARGS="-cvf $2.tar $2" ;; *) echo "$USAGE" exit 0 ;; esac... (13 Replies)
Discussion started by: scriptor
13 Replies

3. Shell Programming and Scripting

Confusion with PS

Hello All, I have a problem in counting number of process getting run with my current script name.. Here it is ps -ef | grep $0 | grep -v grep This display just one line with the PID, PPID and other details when i print it in the script. But when I want to count the numbers in my... (11 Replies)
Discussion started by: sathyaonnuix
11 Replies

4. Linux

shmget failed - cannot allocate memory

Hi, In my proj, one process was running for 2 days. after 2 days its throwing an error message "shmget failed cannot allocate memory". the same problem happened every time.i.e. i can reproduce the same issue if my process is running for every 2 days for a same operation.Within this 2 days there... (1 Reply)
Discussion started by: ManoharanMani
1 Replies

5. Linux

shmget failed - cannot allocate memory

Hi, In my proj, one process was running for 2 days. after 2 days its throwing an error message "shmget failed cannot allocate memory". the same problem happened every time.i.e. i can reproduce the same issue if my process is running for every 2 days for a same operation.Within this 2 days there... (1 Reply)
Discussion started by: ManoharanMani
1 Replies

6. SuSE

shmget failed - cannot allocate memory

Hi, In my proj, one process was running for 2 days. after 2 days its throwing an error message "shmget failed cannot allocate memory". the same problem happened every time.i.e. i can reproduce the same issue if my process is running for every 2 days for a same operation.Within this 2 days there... (1 Reply)
Discussion started by: ManoharanMani
1 Replies

7. Solaris

Printer confusion

I have printer old about 5 year , but I can not determine which driver to use output of ls -al /usr/share/lib/terminfo/h -rw-r--r-- 1 root bin 961 Jan 22 2005 h1000 -rw-r--r-- 1 root bin 1002 Jan 22 2005 h1420 -rw-r--r-- 1 root bin 1009... (2 Replies)
Discussion started by: solaris_user
2 Replies

8. UNIX for Dummies Questions & Answers

'tr' confusion

Good day, everyone! Could anybody explain me the following situation. If I'm running similar script: Var="anna.kurnikova" Var2="Anna Kurn" echo $Var | tr -t "$Var" "$Var2" Why the output is : anna KurniKova instead of Anna Kurnikova? :confused: Thank you in advance for any... (2 Replies)
Discussion started by: Nafanja
2 Replies

9. UNIX for Dummies Questions & Answers

unix confusion

:confused: some one please tell me where i can possibly find out what is unix 10.2 and the basic system functions of it is. I really need help! (1 Reply)
Discussion started by: tribb24
1 Replies
Login or Register to Ask a Question