Why is sys_fork not used by the glibc fork implementation?

In eglibc nptl/sysdeps/unix/sysv/linux/i386/fork.c there is a definition:

 #define ARCH_FORK() \ INLINE_SYSCALL (clone, 5, \ CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, 0, \ NULL, NULL, &THREAD_SELF->tid) 

which is used in actual __libc_fork() as the basis of the implementation. But, for example, in Linux arch/x86/entry/syscalls/syscall_32.tbl there is a sys_fork entry, as well as in syscalls_64.tbl . Thus, it is obvious that Linux has its own special syscall for fork .

So now I wonder: why does glibc implement fork() in terms of clone if the kernel already provides fork syscall?

+7
c linux glibc fork
source share
2 answers

I looked at commit, where Ulrich Drapper added this code to glibc, and there was no explanation in the commit log (or elsewhere).

Take a look at the Linux fork implementation though:

 return _do_fork(SIGCHLD, 0, 0, NULL, NULL, 0); 

And here is clone :

 return _do_fork(clone_flags, newsp, 0, parent_tidptr, child_tidptr, tls); 

Obviously, they are almost the same. The only difference is that when you call clone you can set various flags, specify the stack size for the new process, etc. fork does not accept any arguments.

Looking at the Drepper code, the clone flags CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD . If fork used, the only value will be SIGCHLD .

Here's what the clone manpage says about these extra flags:

 CLONE_CHILD_CLEARTID (since Linux 2.5.49) Erase child thread ID at location ctid in child memory when the child exits, and do a wakeup on the futex at that address. The address involved may be changed by the set_tid_address(2) system call. This is used by threading libraries. CLONE_CHILD_SETTID (since Linux 2.5.49) Store child thread ID at location ctid in child memory. 

... And you can see that it passes a pointer to where the kernel should first store the identifier of the child thread, and then wake up futex. Does glibc make futex wait at this address somewhere? I dont know. If so, this explains why Drepper decided to use clone .

(And if not, this will be another example of extreme torsional motion accumulation, which is our favorite glibc! If you would like to find nice, clean, well-groomed code, just keep moving and go look at musl libc!)

+6
source share

In short: why not?

You have one system column, which is guaranteed to exist on all platforms (you understand that Intel is not the only platform there, right?), And the other, which is deprecated because it is not needed. Both of them carry the same semantics. Your code is much more compact when you call only the one that is guaranteed to exist.

I will talk about this a little bit.

The fork is defined by Posix, and the clone by Linux. However, Linux sometimes allocates Posix "system calls" and implements them in user space. This is the case of fork (both vfork and pthread_create). All of them are implemented in user space, causing a "clone".

Thus, fork is considered unnecessary at the kernel level. If a thin user space shell can implement it, the kernel is fine. Thus, on Linux , the clone is guaranteed to exist on all platforms, and fork may or may not exist depending on the particular platform.

+1
source share

All Articles