Hi,
I was asked to summarize my experiences with using shared memory in
Genode. Apologies for the extremely late reply. My project involves
implementing a profiling infrastructure, whereby i have a profiling
server that coordinates the execution of profiling ie. the collection
and processing of samples. Samples are to be collected from a range of
sources, where the samples generated are analysed by the profiling
server. The issue I was having was the sharing of memory between the
profiling server and the component where the samples were being generated.
Via regular communication with the Genode developers, I got to reading
up on the use of Dataspaces as the mechanism for sharing data between
two components. Essentially, memory sharing between components is
achieved by creating a dataspace, where a memory region is defined such
that data written to this memory is shared. The actual sharing occurs by
having a component (in this case a client) establish a connection to the
server, which allocates the dataspaces. In my profiling design, a
sampling buffer that is shared between a client and a server is only
relevant to that connection only ie. other components do not really need
to know about this data. To illustrate this, i will use a diagram that
Christian used in helping me with establishing data sharing between
components:
Address | Dataspaces and Sharing
spaces |
----------------------------------------------
----------------------------------------------
Sampling | Sample Sample
Server | buffer A buffer B
----------------------------------------------
Sampled | Sample -
client A | buffer A -
----------------------------------------------
Sampled | - Sample
client B | - buffer B
In the above diagram, the data generated in "Sampled client A" has no
relevance whatsoever to "Sampled client B". Hence, I don't need to worry
about Sampled client A and Sampled client B having to share its
profiling data with each other (i'm sure there might be cases where such
sharing is to occur, for instance, if the intention is to write sampling
data to the same buffer). The motivation for this design is that each
sampling buffer represents a particular part of the system being
profiled. For example, Sampled client A could represent a HTTP server
for profiling network activity, and Sampled client B could represent a
kernel buffer to obtain CPU samples. I could then have another sampled
client that measures the rate at which Genode threads are being created
(there obviously might be better examples of another client). Sample
processing is then performed by the server, via a language I have
implemented (the code gets converted to C++ code).
The client-server approach that Genode motivates makes the profiling
environment easily extensible because the creation of a sampling buffer
simply involves having the client to be sampled establish a connection
to the profiling server (I have a connection.h file as part of the
sampling_session interface, which I learned about from the hello world
tutorial). After declaring the connection to the profiling server, a
dataspace capability is obtained from this connection and from there,
the dataspace is attached to the client's local address space, which
results in data sharing now working. The code snippet below should
illustrate what I just explained.
Sampling::Connection samp;
Dataspace_capability ds = samp.get_cap();
void *ptr = Genode::env()->rm_session()->attach(ds);
I can then write data via *ptr, knowing that the data is shared with the
profiling server.
So i've probably gone all over the place with this email, but hopefully
someone might get something out of this.
Peter