c++ - 与信号量共享内存同步

标签 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";
}

最佳答案

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

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

这会导致无限循环,并且您没有机会让 StockExchangeClient::start2() 更改 *shm,因为父级正在无限期地等待 sem_wait 因为 child 从未执行过 sem_post

相反,可以在进入 StockExchangeServer::start2 中的循环之前执行 sem_post,以便您从其 sem_wait 中释放父级。为此,您需要将 &sem 发送到 StockExchangeServer::start2。可能是通过将其原型(prototype)更改为类似 StockExchangeServer::start2( sem_t *sem ) 的东西。

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

此外,正如 David Schwartz 在评论中所观察到的,确保防止对 while 循环进行意外优化。比方说,在循环之前打印出 shm 的值。

关于c++ - 与信号量共享内存同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9783982/

相关文章:

linux - 可以在文件句柄的基础上设置 io 调度优先级吗?

linux - 如何创建自定义 Ubuntu 镜像

linux - Xshell 的配色方案在 GNU screen 中无法正确显示

没有 JNI 的 Java C++

c++ - Stroustrup 的 The C++ Programming Language 有错误吗?

c++ - 我将如何解决 "multiply defined symbols found"

sockets - IPC速度及比较

terminology - 什么是硬件信号量?

c++ - 为什么我的图片出现在文字之前?

c++ - 如何在图中找到所有前向和交叉边