runc internals, part 3: runc double clone
Now that we have analyzed the general process of ‘runc create’ and know that the ‘runc create’ will execute ‘runc init’ parent process, the parent process will clone child process, and the child process will clone a grandchild process, and this grandchild process will execute the user defined process.
Once I decide to draw a pic of these four process’ relation. But I found a detail pic here. I just reference it here.
So let’s see these process’ work.
parent
This is runc:[0:PARENT].
-
Got the config from runc create process. This is done by
nl_parse(pipenum, &config); //corresponding runc create code :io.Copy(p.messageSockPair.parent, p.bootstrapData)
- Create two socketpair ‘sync_child_pipe’ and ‘sync_grandchild_pipe’ to sync with the child and grandchild.
- Clone child process
- Update the uid/gid mapping for child process
- Receive the pid of children and grand children, and send these two to runc create process. So runc create can send config data to the grandchild.
- Wait the grandchild to run
child
This is runc:[1:CHILD].
- Join the namespace specified in the config.json
- Ask the parent process to set the uid/gid mapping
- unshare the namespace specified in config.json
- Clone grandchild process
- Send the pid of grandchild to parent
grandchild
This is runc:[2:INIT].
- Now this process is in the new pid namespace.
- Notify the parent process we are ready
- factory.StartInitialization()
- Config the environment specified in config.json and execute the process
summary
The first clone is to let the parent to set the uid/gid mapping. The second clone is to make the pid namespace take effect. After these double clone, the child process is totally in the desirable new environment.
reference
blog comments powered by Disqus