C 中具有共享内存和信号量的客户端服务器程序
Posted
技术标签:
【中文标题】C 中具有共享内存和信号量的客户端服务器程序【英文标题】:Client server program with shared memory and semaphores in C 【发布时间】:2014-05-28 18:58:32 【问题描述】:我不太了解共享内存的工作原理,我正在尝试编写一个服务器-客户端程序,其中服务器和客户端使用共享内存和信号量相互通信。
共享内存结构:
typedef struct shared_mem
int board[BOARD_SIZE * BOARD_SIZE];
int goal;
int client;
int direction;
sem_t sem_server;
shared_mem;
shared_mem *msg;
服务器:
int shmid;
key_t key=ftok("2048_client.c", 42);
if(key == -1)
printf("ftok failed");
return -1;
shared_mem *shm;
if ((shmid = shmget(key, sizeof(msg), IPC_CREAT|0600)) < 0)
perror("shmget");
exit(1);
if ((shm = shmat(shmid, NULL, 0)) == (char *) -1)
perror("shmat");
exit(1);
msg=shm;
int direction = -1;
srand(time(NULL));
//SERVER SETS VALUES FOR SHARED MEMORY STRUCTURE
sem_wait(&msg->sem_server);
// setup the board
initialize();
// the board starts with 2 pieces
create_game_piece();
printf("pieces created");
create_game_piece();
msg->client=0;
int i;
for (i = 0; i < BOARD_SIZE * BOARD_SIZE; i++)
msg->board[i] = board[i];
sem_post(&msg->sem_server);
// game loop
while (1)
//CLIENT READS AND CHANGES VALUES
//SERVER READS VALUES CHANGED BY CLIENT
if (!move_board(direction))
continue;
sem_wait(&msg->sem_server);
moves++;
direction=msg->direction;
if (check_win())
print_board(-1);
printf("congratulations! you've won in %d moves\r\n", moves);
return 0;
create_game_piece();
if (!has_moves_left())
print_board(-1);
printf("you lose! try again\r\n");
//sleep(1);
return 1;
sem_post(&msg->sem_server);
客户:
int shmid;
key_t key=ftok("2048_client.c", 42);
if(key == -1)
printf("ftok failed");
return -1;
shared_mem *shm;
msg=(shared_mem *)malloc(sizeof(shared_mem));
if ((shmid = shmget(key, sizeof(msg), IPC_CREAT|0600)) < 0)
perror("shmget");
exit(1);
if ((shm = shmat(shmid, NULL, 0)) == (char *) -1)
perror("shmat");
exit(1);
atexit(on_exit2);
system("stty raw");
srand(time(NULL));
while (1)
// CLIENT READS VALUES CHANGED BY SERVER AND CHANGES THEM
sem_wait(&msg->sem_server);
print_board(direction);
direction = keypress();
msg->direction=direction;
sem_post(&msg->sem_server);
有人能告诉我如何协调客户端和服务器访问共享内存的方式,以便它根据代码中的 cmets 工作吗?
【问题讨论】:
【参考方案1】:SHM_UNLOCK 不会按照你的想法去做。它试图锁定内存中的页面而不是阻止访问。您需要一个信号量来控制对共享内存的访问。请参阅 semctl、semget 等,并在客户端和服务器中使用它们以实现互斥访问。
【讨论】:
添加了信号量,但我仍然认为我做错了什么,因为它仍然无法按预期工作。 我看不到你在哪里创建/初始化信号量。 (1) 客户端和服务器是不相关的 pgms 还是分叉? (2) 你用的是sem_init还是sem_open? 请不要提倡使用 semctl/semget 和朋友 - 他们是“旧界面”。使用较新的 POSIX 接口 sem_init/sem_post/sem_wait,使用起来麻烦很多。 @Klaas van Gend,OP 已经在使用 sysV 共享内存,而我(通常)更喜欢并推荐 posix 接口 sysV 信号量确实具有 posix ipc 系列中不可用的功能。他们不会消失。【参考方案2】:您的代码有很多问题。
您根本没有初始化信号量。对于此操作, 信号量位于共享内存中,请确保将 pshared 参数设置为非零。 您不能以这种方式仅使用一个信号量进行双向同步 (否则你做一个 sem_post,即立即 sem_waited 进程,因此该线程可能会继续,另一个不会运行)。 您在客户端 malloc'ed msg,从未将其推送到共享内存, 因此共享内存仍未初始化。 您认为 system("stty raw") 除了打开一大堆安全问题之外,还能完成什么? 显然它不是可运行的代码。我已经修复了很多小东西,但半小时后就放弃了,因为它有太多错误。将 char* 与 shared_mem* 进行比较是错误的。在您的编译器上启用 -Wall 和 -Wextra 并修复您收到的所有警告。您的代码充满了它,不幸的是,所有这些都表明存在严重问题。从设计的角度来看,还有更多的问题。
显然您正在使用服务器中全局的一维数组“板”。这不合适有两个原因:
电路板始终是二维的,为什么不使用二维数组? 您将其用作全局变量,所有函数均可访问。这是“javascript”风格的编程。请将板子本地化为 main 并将其传递给各种功能。【讨论】:
以上是关于C 中具有共享内存和信号量的客户端服务器程序的主要内容,如果未能解决你的问题,请参考以下文章
具有共享内存和文件作为数据库的 IPC V 客户端/服务器应用程序,用 C 编写
从共享内存段复制数据会导致客户端出现段错误(信号量和共享内存)
如果我使用 select() 服务器而不使用 fork()、线程、共享内存、信号量来编写对等 2 对等应用程序,这可以吗?