如何协调两个进程之间的共享内存 [英] How to coordinate shared memory between 2 processes

查看:78
本文介绍了如何协调两个进程之间的共享内存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have program A and program B. Program A makes a queue that's stored into the shared memory with shmget, then shmat. Process B starts up and then uses the same shmid to obtain the queue that process A made without a problem. Process A (both A and B are running at the same time obviously) then runs a method that modifies a certain element in the queue. When program A does this, the pointer to that memory block gives me a segmentation fault. probably because program B now has the pointer pointing to it I suppose. My question is how can I fix this so that program A can edit and read from queue as well as program B. I know that I need some sort of locks but don't know what kind of lock would be best or how to correctly implement this. If you can put up some example code to go along with your explanation that would help a lot. I'm writing all of this in C by the way and process A has 2 keys, one to the queue and another to an array holding all the shmids for every segment allocated in shared memory from Program A to be used by program B to retrieve that information.

推荐答案

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

I agree with the comment that there may be better ways to solve the underlying problem, e.g. with pipes. However, since I have test code that does exactly what you describe, I'll share it with you. Note that when running this code, you should always start the server before starting the client.

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

The code creates a pair semaphores in addition to the shared memory. The REQUEST_SEM is used by the client to signal the server that data is available. The RESPONSE_SEM is used by the server to indicate that it's done with the client's request.

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

If you decide to change the size of the shared memory, you'll need to use the ipcrm command to remove the previously allocated shared memory. Another useful command is ipcs, which lists the IPC objects that you've created.

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

One final note. Using a hardcoded key is bad. See the documentation for ftok for a better way to generate a key.

#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" );
}

Client.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" );
}

这篇关于如何协调两个进程之间的共享内存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆