我有程序A和程序B.程序A创建一个队列,用shmget存储到共享内存中,然后是shmat。进程B启动,然后使用相同的shmid获取进程A没有问题的队列。进程A(显然A和B同时运行)然后运行一个修改队列中某个元素的方法。当程序A这样做时,指向该内存块的指针给我一个分段错误。可能是因为程序B现在有指向它的指针我想。 我的问题是如何解决这个问题,以便程序A可以编辑和读取队列以及程序B.我知道我需要某种锁,但不知道什么样的锁是最好的或如何正确实现这个。如果您可以提供一些示例代码以配合您的解释,这将有很大帮助。我正在用C语言编写所有这些,进程A有2个键,一个到队列,另一个到一个数组,为程序B的共享内存中分配的每个段保存所有的shmid,供程序B使用那个信息。
答案 0 :(得分:1)
我同意评论可能有更好的方法来解决潜在的问题,例如:用管道。但是,由于我的测试代码完全符合您的描述,因此我将与您分享。请注意,运行此代码时,应始终在启动客户端之前启动服务器。
除共享内存外,代码还会创建一对信号量。客户端使用REQUEST_SEM
向服务器发出数据可用信号。服务器使用RESPONSE_SEM
表示已完成客户端的请求。
如果您决定更改共享内存的大小,则需要使用ipcrm
命令删除以前分配的共享内存。另一个有用的命令是ipcs
,它列出了您创建的IPC对象。
最后一点说明。使用硬编码的key
是不好的。有关生成ftok
的更好方法,请参阅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" );
}
#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" );
}