与信号量共享内存同步

时间:2012-03-20 09:12:04

标签: c++ linux ipc semaphore shared-memory

对于家庭作业,我需要使用IPC。我为共享内存编写了一些代码,但它不能按我的意愿工作。我希望服务器进程在客户端之前运行。我做错了什么?如何解决?

//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";
}

1 个答案:

答案 0 :(得分:1)

我对此进行了测试,实际上服务器进程首先运行(StockExchangeServer::start2)但是问题在于

while(*shm == 0) {
    sleep(1);
}

由于孩子从未执行过StockExchangeClient::start2() {} {} {} }

相反,可以在*shm中输入循环之前执行sem_wait,以便从其sem_post释放父级。为此,您需要将sem_post发送给StockExchangeServer::start2。可以将其原型更改为sem_wait

但由于&sem未命名的信号量,并且存在2个副本,一个在父级,一个在子级中,如果您希望父级和子级都使用它,则需要使用StockExchangeServer::start2在共享内存区域中创建它,然后跨进程访问它。如果你不想要所有这些痛苦,你可以切换到命名信号量,甚至可以被不相关的进程访问。 简而言之,未命名的信号量通常用于线程(作为线程共享数据)和命名的进程信号量。

同样正如David Schwartz在评论中所观察到的那样,请确保防止意外优化StockExchangeServer::start2( sem_t *sem )循环。比如说,在循环之前打印出sem的值。

相关问题