Spojrzałem na commit, w którym Ulrich Drepper dodał ten kod do glibc, a nie było żadnego wyjaśnienia w dzienniku zatwierdzenia (lub w innym miejscu).
Wystarczy popatrzeć na wdrożenie Linuksa z fork
, choć:
return _do_fork(SIGCHLD, 0, 0, NULL, NULL, 0);
A oto clone
:
return _do_fork(clone_flags, newsp, 0, parent_tidptr, child_tidptr, tls);
Oczywiście, są one niemal identyczne. Jedyna różnica polega na tym, że wywołując clone
, możesz ustawić różne flagi, określić rozmiar stosu dla nowego procesu itp. fork
nie przyjmuje żadnych argumentów.
Patrząc na kod Dreppera, flagi clone
to CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD
. Jeśli użyto fork
, jedyną flagą byłaby SIGCHLD
.
Oto co clone
podręcznika mówi o tych dodatkowych flag:
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.
... I widać, że ma przekazać wskaźnik do miejsca, gdzie jądro należy najpierw zapisać dziecka identyfikator wątku, a później zrobić przebudzenie futex. Czy Glibc robi gdzieś futex na ten adres? Nie wiem Jeśli tak, to wyjaśnia to, dlaczego Drepper zdecydował się użyć clone
.
(A jeśli nie, byłby to tylko jeden przykład ekstremalnej akumulacji cruftu, który jest naszą ukochaną glibc! Jeśli chcesz znaleźć ładny, czysty, dobrze utrzymany kod, po prostu ruszaj się i idź spójrz na musl libc!)
'pthread_join()' robi przebudzenie. Podobnie jak w przypadku łączenia z wątkami, glibc wywołuje 'set_tid_address()', więc można połączyć wątek "główny": http://stackoverflow.com/questions/6975098/when-is-the-system-call-set -tid-address-used – ninjalj
@usr: ten nowy proces może spawnować wątki. Jeśli chcesz, aby te wątki były w stanie 'pthread_join()' w głównym wątku nowego procesu, glibc potrzebuje adresu futex. – ninjalj
@usr: 'execve()' zajmuje się tym, wywołując 'set_tid_address()'. BTW, jeśli od razu wykonasz exec, istnieje 'vfork()' lub 'posix_spawn()', jeśli twoja libc to zapewnia. – ninjalj