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