Поскольку вы хотите использовать разделяемую память, я рекомендую переписать структуру, поскольку адрес разделяемой памяти может быть изменен при mmap
ing (здесь невозможно) или mremap
.
ИМХО, всегда лучше использовать смещение внутри разделяемой памяти, чем при использовании указателя и при условии, что адрес не изменится, даже если вы можете быть уверены, что адрес не изменится сейчас.
Итак:
struct Paths
{
int totalDistance;
int quantity;
int path[0];
};
Поскольку path
хранится встроенным с Paths
непрерывно, нет необходимости в int *path
.
Когда вы выделяете память с использованием mmap
, size
должно быть sizeof(Paths)
плюс размер, необходимый для хранения path
.
size_t size = sizeof(Paths) + /* Additional size needed for storing path */;
int protection = PROT_READ | PROT_WRITE;
int visibility = MAP_ANONYMOUS | MAP_SHARED;
PtPath shmem = (PtPath) mmap(NULL, size, protection, visibility, -1, 0);
Когда вы обращаетесь к path
из Paths
, компилятор будет использовать смещение от адреса Paths
для доступа к нему, так чтоПока вы держите действительный указатель на разделяемую память с допустимым Paths
, вы можете получить к нему доступ, независимо от того, является ли он mmap
ed или mremap
ed.
Копирование данных из newPath
будетпросто:
Path newPath = createPath();
for(int i = 0 ; i < shmem->quantity ; i++)
shmem->path[i] = newPath.path[i];
Этот метод имеет небольшое преимущество передd используется в вопросе: он не нуждается в дополнительном указателе, который может быть полезен, если вы выделите много Path
.
Теперь лучше использовать void initializePath(Path*, int)
вместо Path createPath(int)
:
void initializePath(Path *newPath, int quantity)
{
if (quantity < 0)
quantity = 0;
newPath->quantity = quantity;
newPath->totalDistance = 0;
randomPath(shmem);
setPathTotalDistance(shmem, distances);
}
И у вас может быть другая функция Path* allocatePath(int)
для выделения Path
:
Path* allocateSharedPath(int quantity)
{
size_t size = sizeof(Paths) + quantity * sizeof(int);
int protection = PROT_READ | PROT_WRITE;
int visibility = MAP_ANONYMOUS | MAP_SHARED;
Path *shmem = (Path*) mmap(NULL, size, protection, visibility, -1, 0);
if (shmem == NULL)
/* Handle failure */;
return shmem;
}
Path* allocatePath(int quantity)
{
size_t size = sizeof(Paths) + quantity * sizeof(int);
Path *mem = (Path*) calloc(size, 1);
if (mem == NULL)
/* Handle failure */;
return mem;
}
Кстати, если вы хотите сохранить что-то еще между quantity
и path
или вы хотите сохранить path
до Paths
, вы можете сделать это:
struct Paths
{
int totalDistance;
int quantity;
offset_t offset_to_path;
};
size
требуется выделить sizeof(Paths) + /* Additional size needed for storing path */ + /* sizeof whatever else you need to store */
.При инициализации инициализируйте offset_to_path
до pointer_to_path - pointer_to_Paths
, чтобы вы могли получить к нему доступ, добавив offset_to_path
к указателю на Paths
.