对于家庭作业,我需要使用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 errorn";
} 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 errorn";
exit(1);
}
else{}
if((shm = (int *)shmat(sharedMemoryId,NULL,0)) == (int *)-1) {
std::cout<<"Shared memory attach errorn";
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 errorn";
exit(1);
}
else{}
if((shm = (int *)shmat(sharedMemoryId,NULL,0)) == (int *)-1) {
std::cout<<"Shared memory attach errorn";
exit(1);
}
else{}
*shm = 0;
while(*shm == 0) {
sleep(1);
}
std::cout<<"Shared memory succededn";
}
我对此进行了测试,事实上服务器进程首先运行(StockExchangeServer::start2
),但问题出在中
while(*shm == 0) {
sleep(1);
}
这导致了一个无限循环,并且您没有给StockExchangeClient::start2()
更改*shm
的机会,因为父级在sem_wait
无限期等待,因为子级从未执行sem_post
相反,可以在进入StockExchangeServer::start2
中的循环之前执行sem_post
,以便从其sem_wait
中释放父级。为此,您需要将&sem
发送到StockExchangeServer::start2
。可能是通过将其原型更改为类似StockExchangeServer::start2( sem_t *sem )
的东西。
但是,由于sem
是一个未命名的信号量,并且存在两个副本,一个在父级,一个位于子级,如果您希望父级和子级都使用它,则需要使用shmget
在共享内存区域中创建它,然后跨进程访问它。如果您不想所有这些痛苦,您可以切换到命名信号量,甚至可以由不相关的进程访问简而言之,未命名信号量通常用于线程(因为线程共享数据),而命名信号量用于进程
正如David Schwartz在评论中所观察到的,确保防止while
循环的意外优化。例如,在循环之前打印出shm
的值。