Hello Norman,
thank you for your great answer. I will follow your advise and virtualize all necessary services that a target component uses.
Kind regards, Denis
On 09.09.2016 10:58, Norman Feske wrote:
Hi Denis,
The child component shall be migrated from one ECU to another. The Genode system on the other ECU may have the Rpc_objects, which the child needs (e.g. shared dataspaces), but their object identities are different (e.g. other addresses in memory) or the Rpc_objects do not exist (e.g. a session object between the child and a service).
so the problem goes much deeper than merely requesting and populating the child's capability space. You need the replicate the entire child's execution environment at the destination ECU. That means for each capability in possession of the child, your runtime needs to know the exact meaning. E.g., if the child has a session capability to a session created with certain session arguments, the same kind of session must be re-created at the destination ECU. Of course, the same holds for all dataspaces, threads, and other RPC objects that the child can reference via the capabilities present in its capability space.
The logical consequence is that the runtime must virtualize all services used by the child. E.g. if the child creates a LOG session, the runtime would create a session to a LOG service in the child's name but hand out a capability locally implemented LOG-session wrapper - similar to what you have already done for the RAM service. So when migrating the child, you now exactly what the various capabilities in the child's capability space mean and can transfer the underlying state to the destination ECU.
In principle, this is how Noux solves the fork problem. But in the case of Noux, I deliberately avoid populating the child's capability space with Genode capabilities in order to alleviate the need to virtualize many Genode services. Instead, I let the child use the Noux session as its only interface to the outside world. At the Noux-session level, the child does not talk about Genode capabilities but about file descriptors, for which Noux knows the meaning. Of course there exist a few capabilities in the child's capability space, in particular the parent cap, the Noux-session cap, and the caps of the child's environment. But these few capabilities are manually re-initialized by the freshly created process after the fork.
In your case, you want to replicate the child's capability space in a way that is transparent to the child. Like Noux, you need the have a complete model of the child's execution environment in your runtime. Unlike Noux, however, you want to let the child interact with various Genode services. Consequently, your model needs to capture the those services.
During a restore, I will have to relink the Native_capability to the available Rpc_object or simply recreate the Rpc_object. In both cases I have to know the types of the Native_capabilities, when I snapshot them from the Cap Space of the child. Is there a way to find out the type of a Native_capability through an API function?
As discussed above, the type alone does not suffice. Your runtime needs to know the actual semantics behind each capability, e.g., not just the knowledge that a certain capability is a RAM-session capability but also the information how much quota the RAM session has and which dataspaces belong to it. Or as another example, you don't just need to know that a capability is a file-system session but also the session arguments that were used when the session was created.
If there is no ready-to-use function/approach, can I intercept the type to which a Native_capability is reinterpreted in Rpc_entrypoint::manage as a workaround solution?
Since your runtime needs to create a representative for each RPC object the child interacts with in the form of a locally implemented RPC object (managed by the runtime's entrypoint), you can in principle use the 'Rpc_entrypoint::apply' method to look up the local RPC object for a given capability.
Best regards Norman