For homework I need to use IPC. I write some code for shared memory but it does not work as I want. I want server process to run before client. What I am doing wrong? How to fix it?
//main.cpp
#include "stockexchangeserver.h"
#include "stockexchangeclient.h"
#include <semaphore.h>
int main(int argc,char *argv[])
{
StockExchangeServer server;
StockExchangeClient client;
pid_t pid;
sem_t sem;
int pshared = 1;
unsigned int value = 0;
sem_init(&sem,pshared,value);
if ((pid = fork()) < 0) {
std::cout<<"fork error\n";
} else if (pid > 0) {
sem_wait(&sem);
client.start2();
sem_post(&sem);
} else {
server.start2();
sem_post(&sem);
}
return 0;
}
//stockexchangeclient.cpp
void StockExchangeClient::start2() {
int sharedMemoryId;
key_t key;
int *shm;
key = 6000;
if((sharedMemoryId = shmget(key,sizeof(int),0666)) < 0) {
std::cout<<"Shared memory create error\n";
exit(1);
}
else{}
if((shm = (int *)shmat(sharedMemoryId,NULL,0)) == (int *)-1) {
std::cout<<"Shared memory attach error\n";
exit(1);
}
else{}
*shm = 1;
exit(0);
}
//stockexchangeserver.cpp
void StockExchangeServer::start2()
{
int sharedMemoryId;
key_t key;
int *shm;
key = 6000;
if((sharedMemoryId = shmget(key,sizeof(int),IPC_CREAT | 0666)) < 0) {
std::cout<<"Shared memory create error\n";
exit(1);
}
else{}
if((shm = (int *)shmat(sharedMemoryId,NULL,0)) == (int *)-1) {
std::cout<<"Shared memory attach error\n";
exit(1);
}
else{}
*shm = 0;
while(*shm == 0) {
sleep(1);
}
std::cout<<"Shared memory succeded\n";
}
I tested this and in fact server process is running first (
StockExchangeServer::start2) But the problem is inThis is resulting in an infinite loop and you are not giving an opportunity to
StockExchangeClient::start2()to change*shmas parent is waiting indefinitely atsem_waitas the child never executedsem_postInstead can do a
sem_postbefore entering the loop inStockExchangeServer::start2so that you release the parent from itssem_wait. For this you need to send&semtoStockExchangeServer::start2. May be by changing its prototype into something likeStockExchangeServer::start2( sem_t *sem ).But as
semis an unnamed semaphore, and 2 copies exist, one in parent and one in child, and if you want both parent and child to use it, you need to create it in a shared memory region usingshmgetand then access it across processes. If you don’t want all this pain, you can switch to named semaphores which can be even accessed by unrelated processes. In short, unnamed semaphores are generally used for threads ( as threads share data )and named semaphores for processes.Also as observed by David Schwartz in comments make sure to prevent unintended optimization of the
whileloop. Say for example, print out the value ofshmbefore the loop.