【发布时间】:2018-04-07 06:30:17
【问题描述】:
我有两个代码:PRODUCER (PR) 和 CONSUMER (CO)。有一块内存(Mat)(准确地说是一个 3D 矩阵)需要在两个程序之间共享。我目前正在使用基于共享内存的 IPC 函数来共享两个代码之间的内存空间。
约束:
-
PR 是
Mat的所有者,并执行更改矩阵值的迭代。 CO 是Mat的用户,仅读取值并用于进一步计算 -
PR 应先写入数据,然后应等待 CO 读取并使用
Matrix的值,然后发出信号 PR 继续随着进一步的迭代,它应该像这样继续下去。
我目前使用的是-
制片人
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define NOT_READY -1
#define FILLED 0
#define TAKEN 1
#define nx (400)
#define ny (400)
#define nz (400)
struct Memory {
int status;
double u_x[nx+1][ny+2][nz+2];
}
int
main(int argc, char *argv[])
{
key_t ShmKEY;
int ShmID;
struct Memory *ShmPTR;
int i, j, k;
int niter = 5;
int sumX[niter],sumY[niter],sumZ[niter];
ShmKEY = ftok(".", 'x'); // getting the unique identifier key from directory location
ShmID = shmget(ShmKEY, sizeof(struct Memory), IPC_CREAT | 0666);
if (ShmID < 0) {
printf("*** shmget error (server) ***\n");
exit(1);
}
ShmPTR = (struct Memory *) shmat(ShmID, NULL, 0);
if ((int) ShmPTR == -1) {
printf("*** shmat error (server) ***\n");
exit(1);
}
printf("Server attached the memory to its virtual space...\n");
ShmPTR->status = NOT_READY; // setting the status to be not ready before filling it
for (int m = 0; m < niter; m++){
for (i=0; i<=nx; i++) for (j=0; j<=ny+1; j++) for (k=0; k<=nz+1; k++)
ShmPTR->u_x[i][j][k] = m; // filling the array with iteration number (just for depiction purpose)
ShmPTR->status = FILLED; // change the status to Filled
//printf("Please start the client in another window...\n");
while (ShmPTR->status != TAKEN)
sleep(1);
}
printf("Server has detected the completion of its child...\n");
shmdt((void *) ShmPTR);
printf("Server has detached its shared memory...\n");
shmctl(ShmID, IPC_RMID, NULL);
printf("Server has removed its shared memory...\n");
printf("Server exits...\n");
exit(0);
}
消费者
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define NOT_READY -1
#define FILLED 0
#define TAKEN 1
#define nx (400)
#define ny (400)
#define nz (400)
struct Memory {
int status;
double u_x[nx+1][ny+2][nz+2];
}
int
main(void)
{
key_t ShmKEY;
int ShmID;
struct Memory *ShmPTR;
int i, j, k;
int niter = 5;
int sumX[niter];
ShmKEY = ftok(".", 'x');
ShmID = shmget(ShmKEY, sizeof(struct Memory), 0666);
if (ShmID < 0) {
printf("*** shmget error (client) ***\n");
exit(1);
}
printf("Client has received a shared memory...\n");
ShmPTR = (struct Memory *) shmat(ShmID, NULL, 0);
if ((int) ShmPTR == -1) {
printf("*** shmat error (client) ***\n");
exit(1);
}
printf("Client has attached the shared memory to it's virtual memory space...\n");
for (int m =0; m<niter; m++){
sumX[m] = 0;
while (ShmPTR->status != FILLED)
;
printf("Client found the data is ready, performing sanity check...\n");
// read the integers and check for the sum
for (i=0; i<=nx; i++) for (j=0; j<=ny+1; j++) for (k=0; k<=nz+1; k++)
sumX[m] += ShmPTR->u_x[i][j][k];
printf("Cycle %d : sumX-> %d\n", m,sumX[m);
ShmPTR->status = TAKEN;
printf("Client has informed server data have been taken...\n");
}
shmdt((void *) ShmPTR);
printf("Client has detached its shared memory...\n");
printf("Client exits...\n");
exit(0);
}
我现在正在做的是使用名为status 的结构成员来防止出现竞争条件。从我到现在为止的阅读中,信号量允许在 IPC 中进行类似的操作。
问题:如何在此使用信号量,以便需要共享的内存空间只是数组而不是将其包装在具有自定义标志的结构中?
Edit1:或者 mutex 如果它比这个应用程序的信号量更好的话。
Edit2:遵循适用于此代码的@Stargateur 答案,但在nx、ny 和nz 是变量的生产代码中,如何为结构由一个成员组成,该成员是一个可变长度多维数组? (当然它会一直持续到调用shmdt 和shmctl)
【问题讨论】:
标签: c ipc semaphore shared-memory