Ich schaute auf das Commit, bei dem Ulrich Drepper diesen Code zu glibc hinzufügte, und es gab keine Erklärung im Commit-Protokoll (oder anderswo).
Hier finden Sie aktuelle Linux-Implementierung von fork
, aber:
return _do_fork(SIGCHLD, 0, 0, NULL, NULL, 0);
Und hier ist clone
:
return _do_fork(clone_flags, newsp, 0, parent_tidptr, child_tidptr, tls);
Offensichtlich sind sie fast genau das gleiche. Der einzige Unterschied besteht darin, dass Sie beim Aufruf von clone
verschiedene Flags setzen können, eine Stack-Größe für den neuen Prozess angeben können usw. fork
akzeptiert keine Argumente.
Mit Blick auf Drepper-Code sind die clone
Flags CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD
. Wenn fork
verwendet wurde, wäre das einzige Flag SIGCHLD
. Hier
ist, was der clone
manpage sagt über diese zusätzliche Fahnen:
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.
... Und man kann sehen, dass er einen Zeiger auf nicht passiert, wo der Kernel soll zuerst das Thread-ID des Kindes speichern und dann später mach ein Futex Wakeup. Steht glibc auf die Adresse? Ich weiß es nicht. Wenn ja, würde das erklären, warum Drepper clone
gewählt hat.
(Und wenn nicht, wäre es nur ein weiteres Beispiel für die extreme Anhäufung von Cruft, die unser geliebter Glibc ist! Wenn du einen schönen, sauberen, gepflegten Code finden wolltest, bleib einfach in Bewegung! schau dir musl libc an!)
'pthread_join()' macht das Wecken. Ähnlich wie bei der Verbindung mit Threads ruft glibc 'set_tid_address()' auf, so dass der "main" -Thread verknüpft werden kann: http://StackOverflow.com/questions/6975098/when-is-the-system-call-set -tid-address-used – ninjalj
@usr: Dieser neue Prozess kann Threads erzeugen. Wenn diese Threads in der Lage sein sollen, 'pthread_join()' auf dem Haupt-Thread des neuen Prozesses zu verwenden, benötigt glibc die Adresse des Futex. – ninjalj
@usr: 'execve()' kümmert sich darum, indem er 'set_tid_address()' aufruft. BTW, wenn Sie sofort exec ausführen, gibt es 'vfork()' oder 'posix_spawn()', wenn Ihre libc das bietet. – ninjalj