【问题标题】:How to coordinate shared memory between 2 processes如何协调2个进程之间的共享内存
【发布时间】:2014-12-06 21:35:02
【问题描述】:

我有程序 A 和程序 B。程序 A 使用 shmget 和 shmat 创建一个存储到共享内存中的队列。进程 B 启动,然后使用相同的 shmid 来获取进程 A 没有问题的队列。进程 A(显然 A 和 B 都在同时运行)然后运行一个修改队列中某个元素的方法。当程序 A 执行此操作时,指向该内存块的指针会给我一个分段错误。我想可能是因为程序 B 现在有指向它的指针。 我的问题是如何解决这个问题,以便程序 A 可以从队列和程序 B 中编辑和读取。我知道我需要某种锁,但不知道哪种锁最好或如何正确实现这。如果您可以提供一些示例代码来配合您的解释,那将有很大帮助。顺便说一句,我正在用 C 编写所有这些,并且进程 A 有 2 个键,一个用于队列,另一个用于一个数组,该数组包含从程序 A 分配到共享内存中的每个段的所有 shmid,以供程序 B 用于检索这些信息。

【问题讨论】:

  • 您可能不想以这种方式解决您的问题。如果您真的需要好的帮助,您应该说明您的根本问题。
  • 您将使用命名的(系统范围的)信号量/互斥量。这是一个相关的讨论:stackoverflow.com/questions/8359322/…

标签: c shared-memory


【解决方案1】:

我同意可能有更好的方法来解决潜在问题的评论,例如用管道。但是,由于我有完全符合您描述的测试代码,因此我将与您分享。请注意,在运行此代码时,您应该始终在启动客户端之前启动服务器。

代码在共享内存之外创建了一对信号量。客户端使用REQUEST_SEM 向服务器发出数据可用的信号。服务器使用RESPONSE_SEM 来表明它已经完成了客​​户端的请求。

如果您决定更改共享内存的大小,则需要使用ipcrm 命令删除之前分配的共享内存。另一个有用的命令是ipcs,它列出了您创建的 IPC 对象。

最后一点。使用硬编码的key 是不好的。有关生成key 的更好方法,请参阅ftok 的文档。

服务器.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <errno.h>

#define REQUEST_SEM   0
#define RESPONSE_SEM  1

#define SEM_RA    (SEM_R | SEM_A)
#define SEM_FLAGS (SEM_RA | (SEM_RA >> 3) | (SEM_RA >> 6))
#define MEM_RW    (SHM_R | SHM_W)
#define MEM_FLAGS (MEM_RW | (MEM_RW >> 3) | (MEM_RW >> 6))

static void error( const char *msg )
{
    perror( msg );
    exit( 1 );
}

void waitForIt( int semid, int semnum )
{
    struct sembuf operations = { semnum, -1, 0 };

    if ( semop( semid, &operations, 1 ) < 0 )
        error( __func__ );
}

void signalIt( int semid, int semnum )
{
    struct sembuf operations = { semnum, 1, 0 };

    if ( semop( semid, &operations, 1 ) < 0 )
        error( __func__ );
}

int main( int argc, char *argv[] )
{
    int i, semID, memID, good, bad;
    char *memAddress;

    if ( (semID = semget( 0x1001, 2, IPC_CREAT | SEM_FLAGS )) < 0 )
        error( "Unable to create semaphores" );
    if ( semctl( semID, REQUEST_SEM, SETVAL, 0 ) < 0 )
        error( "Unable to initialize request semaphore" );
    if ( semctl( semID, RESPONSE_SEM, SETVAL, 0 ) < 0 )
        error( "Unable to initialize response semaphore" );

    if ( (memID = shmget( 0x1001, 1024, IPC_CREAT | MEM_FLAGS )) < 0 )
        error( "Unable to create shared memory" );
    memAddress = shmat( memID, NULL, 0 );    
    if ( memAddress == NULL || memAddress == ((void *) -1) )
        error( "Unable to attach shared memory" );

    good = 0;
    bad  = 0;
    for ( i = 0; i < 100; i++ )
    {
        waitForIt( semID, REQUEST_SEM );
        if ( memAddress[0] == i )
            good++;
        else
            bad++;

        memAddress[0] = 0x55;
        signalIt( semID, RESPONSE_SEM );
    }

    printf( "good=%d bad=%d\n", good, bad );

    if ( shmdt( memAddress ) < 0 )
        error( "Unable to detach shared memory" );
}

客户端.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <errno.h>

#define REQUEST_SEM   0
#define RESPONSE_SEM  1

static void error( const char *msg )
{
    perror( msg );
    exit( 1 );
}

void waitForIt( int semid, int semnum )
{
    struct sembuf operations = { semnum, -1, 0 };

    if ( semop( semid, &operations, 1 ) < 0 )
        error( __func__ );
}

void signalIt( int semid, int semnum )
{
    struct sembuf operations = { semnum, 1, 0 };

    if ( semop( semid, &operations, 1 ) < 0 )
        error( __func__ );
}

int main( void )
{
    int i, semID, memID, good, bad;
    char *memAddress;

    if ( (semID = semget( 0x1001, 0, 0 )) < 0 )
        error( "Unable to get semaphores" );

    if ( (memID = shmget( 0x1001, 0, 0 )) < 0 )
        error( "Unable to create shared memory" );
    memAddress = shmat( memID, NULL, 0 );
    if ( memAddress == NULL || memAddress == ((void *) -1) )
        error( "Unable to attach shared memory" );

    good = 0;
    bad  = 0;
    for ( i = 0; i < 100; i++ )
    {
        memAddress[0] = i;
        signalIt( semID, REQUEST_SEM );

        waitForIt( semID, RESPONSE_SEM );
        if ( memAddress[0] == 0x55 )
            good++;
        else
            bad++;
    }

    printf( "good=%d bad=%d\n", good, bad );

    if ( shmdt( memAddress ) < 0 )
        error( "Unable to detach shared memory" );
}

【讨论】:

    猜你喜欢
    • 2013-07-04
    • 2011-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-03
    • 2018-07-06
    • 2014-09-02
    • 1970-01-01
    • 2012-01-11
    相关资源
    最近更新 更多