%3F.png)
sobre lo anteriorenlace¿Qué se entiende por parent_tidptr
y child_tidptr
sobre do_fork()
qué crea un nuevo proceso?
Respuesta1
Comencemos mirando la interfaz de llamada al sistema sin formato. Varía un poco según la arquitectura, pero en x86-64 es:
long clone(unsigned long flags, void *child_stack,
int *ptid, int *ctid,
unsigned long newtls);
ptid
y ctid
son tu parent_tidptr
y child_tidptr
. Ahora veamos cuál es elclone(2)
La página del manual tiene que decir:
CLONE_CHILD_CLEARTID (since Linux 2.5.49)
Erase the child thread ID at the location ctid in
child memory when the child exits, and do a wakeup on
the futex at that address.
CLONE_CHILD_SETTID (since Linux 2.5.49)
Store the child thread ID at the location ctid in the
child's memory.
CLONE_PARENT_SETTID (since Linux 2.5.49)
Store the child thread ID at the location ptid in the
parent's memory.
Estas banderas fueron diseñadas principalmente para implementar bibliotecas de subprocesos. Si echamos un vistazo a la implementación NPTL depthread_create()
dentro de glibc, eventualmente encontramos código ensysdeps/unix/sysv/linux/createthread.c
que hace una clone()
llamada que incluye CLONE_PARENT_SETTID
y CLONE_CHILD_CLEARTID
en flags
.
En esa clone()
llamada, también podemos ver que los argumentos ptid
yctid
apuntar a la misma dirección. (Recuerde que los subprocesos POSIX comparten un espacio de direcciones; esto se logra con la clone()
CLONE_VM
bandera).
Entonces, lo que está pasando aquí es lo siguiente.
CLONE_PARENT_SETTID
se utiliza para garantizar que el ID del subproceso del núcleo se almacene en una ubicación determinada en el espacio del usuario. El lado del espacio de usuario de la implementación del subproceso necesita conocer el ID del subproceso.CLONE_CHILD_CLEARTID
se está utilizando para borrar (es decir, poner a cero) esa misma ubicación cuandoclone()
termina el hilo creado por.
Vayamos un poco más allá...
El ID del hilo que se devuelve a través de ptid
/ ctid
esnoLo mismo que un ID de subproceso POSIX ( pthread_t
), aunque en las implementaciones de subprocesos 1:1 como NPTL, existe una correspondencia uno a uno entre los ID de subprocesos del núcleo y los ID de subprocesos POSIX. El ID del hilo del núcleo es el mismo que se obtiene al utilizar Linux.gettid()
llamar. También se devuelve clone()
como valor de retorno de la llamada al sistema, lo que genera la pregunta: ¿por qué necesitamos ptid
/ ctid
? El problema es que desde el lado del espacio de usuario, las cosas se ven así:
tid = clone(...);
Desde el punto de vista de la implementación de subprocesos en el espacio de usuario, aquí hay una carrera, porque la asignación a tid
ocurre sólodespués clone()
devoluciones. Esto significa que la biblioteca de subprocesos del espacio de usuario puede tener ciertos problemas si quiere esa información antes de que el nuevo subproceso haga algo (como terminar, por ejemplo). El uso CLONE_PARENT_SETTID
garantiza que el nuevo ID del hilo se coloque en la ubicación señalada porptid
antes
clone()
devuelve y, por lo tanto, permite que una biblioteca de subprocesos evite tales condiciones de carrera. ( CLONE_CHILD_SETTID
también se puede utilizar con un efecto similar).
La razón que CLONE_CHILD_CLEARTID
se utiliza para borrar el ptid
/ ctid
es proporcionar una manera para unapthread_join()
llame a otro hilo para descubrir que el hilo ha terminado. En esencia, la ubicación ptid
/ ctid
se utiliza comofutex, y elfutex()
La llamada al sistema se utiliza para bloquear y esperar a que cambie el número entero en esta ubicación. (Los detalles son un poco complicados, pero grep
para usos de lll_wait_tid
y lll_futex_wait
en el código fuente de glibc. En última instancia, se está FUTEX_WAIT
llevando a cabo una operación. Recuerde lo anterior que CLONE_CHILD_CLEARTID
realiza una activación futex en la dirección de destino).
Respuesta2
tid
significa "identificación del hilo". Los parámetros parent_tidptr
y child_tidptr
apuntan a la memoria del espacio de usuario en el espacio de direcciones del proceso principal y en el espacio de direcciones del proceso secundario, respectivamente. La identificación del hilo recién creado se almacena en las variables int a las que apuntan los punteros.
Para obtener más información, consulte laclone(2)
página de manual.