对于家庭作业,我需要使用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";
}
答案 0 :(得分:1)
我对此进行了测试,实际上服务器进程首先运行(StockExchangeServer::start2
)但是问题在于
while(*shm == 0) {
sleep(1);
}
由于孩子从未执行过StockExchangeClient::start2()
{} {} {} }
相反,可以在*shm
中输入循环之前执行sem_wait
,以便从其sem_post
释放父级。为此,您需要将sem_post
发送给StockExchangeServer::start2
。可以将其原型更改为sem_wait
。
但由于&sem
是未命名的信号量,并且存在2个副本,一个在父级,一个在子级中,如果您希望父级和子级都使用它,则需要使用StockExchangeServer::start2
在共享内存区域中创建它,然后跨进程访问它。如果你不想要所有这些痛苦,你可以切换到命名信号量,甚至可以被不相关的进程访问。 简而言之,未命名的信号量通常用于线程(作为线程共享数据)和命名的进程信号量。
同样正如David Schwartz在评论中所观察到的那样,请确保防止意外优化StockExchangeServer::start2( sem_t *sem )
循环。比如说,在循环之前打印出sem
的值。