Updated: April 19, 2023 |
Finally, we need to set the size of the shared memory segment:
... sts = ftruncate (shmem_fd, size); // error check code omitted ...
and map it into our address space via mmap():
... shmem_ptr = mmap (0, size, PROT_READ | PROT_WRITE, MAP_SHARED, shmem_fd, 0); // error checking code omitted ...
The flags to mmap() are:
Now that our shared memory region exists and is the correct size, we assign some utility pointers into the areas within the shared memory:
... // set up our utility pointers sig = (adios_signature_t *) shmem_ptr; daq = (adios_daq_status_t *) (shmem_ptr + sizeof (*sig)); cis = (adios_cis_t *) (shmem_ptr + sizeof (*sig) + sizeof (*daq)); ...
Then we fill the shared memory structure:
... // clear the signature (just for safety, a // new shmem region is zeroed anyway) memset (sig -> signature, 0, sizeof (sig -> signature)); sig -> datablock = size_c + FILLER_ALIGN_4kbytes (size_c); sig -> datablock /= 4096; // convert to blocks sig -> num_cis = nadios; sig -> num_elems = optS; database = shmem_ptr + sig -> datablock * 4096; daq -> element_size = size_element; // head points to the last entry in the buffer, so that // when we add our first entry head will point to 0 daq -> tail = daq -> head = optS - 1; for (i = 0; i < nadios; i++) { strncpy (cis [i].name, adios [i].name, MAXNAME); cis [i].nai = adios [i].nai; cis [i].nao = adios [i].nao; cis [i].ndi = adios [i].ndi; cis [i].ndo = adios [i].ndo; cis [i].nbpc = adios [i].nbpc; cis [i].maxresai = adios [i].maxresai; } }
Filling the shared memory structure means that we set:
Notice that we did not fill in the signature field (we only zeroed it). That's because we validate the signature only when we have at least one valid sample in the shared memory ring buffer.
That was a lot of work. Compared to this, managing the shared memory ring buffer data is much simpler!