I have question regarding shared memory segmentation in c using POSIX system calls. Is it right that I am detaching and removing segment from client and server or i just need to remove from server?
Consider I have 2 programmes
One for server and one for client
the steps for the server
1)create memory segment
2)attach
3)detach
4)remove
steps for the client
1)create
2)attach
3)detach
4)remove
this is my code:
//server
#include<stdlib.h>
#include<stdio.h>
#include<sys/ipc.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<sys/shm.h>
#define SHMSZ 100
int main()
{
key_t key;
char c;
int shmid;
char *shm;
key=1025;
//locate
if((shmid=shmget(key,SHMSZ,0666 | IPC_CREAT))<0)
{
perror("shmget");
exit(-1);
}
//attach
if((shm=shmat(shmid,NULL,0))==(char*)-1)
{
perror("shmat");
exit(-1);
}
sprintf(shm,"Hi there");
//shm="Hi There";
while(*shm!='*');
sleep(1);
//detach
shmctl(shmid,IPC_RMID,NULL);
return 0;
}
this is client side
//client
#include<stdlib.h>
#include<stdio.h>
#include<sys/ipc.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<sys/shm.h>
#define SHMSZ 100
int main()
{
key_t key;
int shmid;
char c;
char *shm, *s;
key=1025;
//locate
if((shmid=shmget(key,SHMSZ,0666 | IPC_CREAT))<0)
{
perror("shmget");
exit(-1);
}
//attach
if((shm=shmat(shmid,NULL,0))==(char*)-1)
{
perror("shmat");
exit(-1);
}
printf("%s\n",shm);
*shm='*';
shmdt(&shmid);
shmctl(shmid, IPC_RMID,NULL);
return 0;
}
Since you’re using System V IPC rather than POSIX IPC, check the value of
shm_nattchin the data-structure associated with the ID of the shared memory segment. You can get this value by callingshmctlwith a flag ofIPC_STAT. Callingshmdtwill reduce this value by one, and the last process to call this function will set the value ofshm_nattachto0. Once the value is zeroed-out, you can safely make a call toshmctlto remove the memory segment.So in both your client and server code if the server is not guaranteed to outlive a client, you should check the value of
shm_nattchwith a separate call toshmctlafter callingshmdtto see if the number of processes accessing the shared memory segment has been reduced to zero. You should also make sure to error-check the results of thisIPC_STATcall in order to avoid a race-condition where two separate processes callshmdt, reducing the value ofshm_nattchto zero, but the process that was actually the last to callshmdtis suspended by the OS, and the other process sees the value ofshm_nattchis zero and removes the memory segment. Since both checking and removing the shared memory segment requires calls toshm_ctl, and that call will fail if the ID of the shared-memory segment is invalid, you theoretically shouldn’t run into any race-conditions if you only make calls toshm_ctlorshmdtafter a single process has removed the shared memory segment. The thing you want to avoid though would be accessing a pointer to the shared memory segment after it’s been removed. Checking for failed calls toshm_ctlwill help you avoid those types of situations. In other words if the call fails, then you can’t safely access the pointer anymore.If on the other-hand your server is guaranteed to outlive any of the clients, then the server can safely make the call to remove the shared memory segment, since it will be the last process using it … all of the other clients will not need to remove the memory segment, but simply detach from it.