3

Somehow it's easier to call fork and then unshare because many arguments are copied via fork that would otherwise be manually wrapped to clone. My question is, what is the difference between (1) calling clone which forks a new process in separate namespaces and (2) fork+unshare which forks a new process and then leaves parent's namespaces. Assume all namespace flags passed to clone and unshare are the same.

auto flag = CLONE_NEWUSER | CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWNET | SIGCHLD;

So, with fork, its very easy for child to reuse data inherited from parents.

int mydata;  // this could be even more complicated, class, struct, etc.
auto pid = fork();
if(pid == 0) {
  // reuse inherited data in a copy-on-write manner
  unshare(flag);
}

For clone, we sometimes have to wrap data into another struct and pass it as void* to the clone system call.

int mydata;
clone(func, stack+stack_size, flag, &wrapper_of_data);

It seems to me in the above example the only difference is the performance hit, where fork can be a bit more expensive. However, the nature of fork saves me many efforts in the way that both can create a process in new namespaces.

chrk
  • 4,037
  • 2
  • 39
  • 47
Jes
  • 2,614
  • 4
  • 25
  • 45

1 Answers1

0

Somehow it's easier to call fork and then unshare because many arguments are copied via fork that would otherwise be manually wrapped to clone.

This is only true for the libc wrapper function.
The underlying system call is more like fork(), and would probably work better in this case:

long flags = CLONE_NEWUSER | ... | SIGCHLD;
long pid = syscall(__NR_clone, flags, 0, 0, 0, 0);

if(pid == 0) {
    /* child with unshared namespaces */
}

Since about the time clone syscall was introduced, fork() is just a specific case of clone with flags=SIGCHLD and 0s for all other arguments.

There is probably no reason to prefer fork/unshare pair over just passing the same flags to clone.

arsv
  • 1,176
  • 9
  • 11