Código fuente del kernel: ¿Qué son parent_tidptr y child_tidptr en do_fork()?

Código fuente del kernel: ¿Qué son parent_tidptr y child_tidptr en do_fork()?

sobre lo anteriorenlace¿Qué se entiende por parent_tidptry child_tidptrsobre 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);

ptidy ctidson tu parent_tidptry 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.cque hace una clone()llamada que incluye CLONE_PARENT_SETTIDy CLONE_CHILD_CLEARTIDen flags.

En esa clone()llamada, también podemos ver que los argumentos ptidyctidapuntar a la misma dirección. (Recuerde que los subprocesos POSIX comparten un espacio de direcciones; esto se logra con la clone() CLONE_VMbandera).

Entonces, lo que está pasando aquí es lo siguiente.

  • CLONE_PARENT_SETTIDse 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_CLEARTIDse está utilizando para borrar (es decir, poner a cero) esa misma ubicación cuando clone()termina el hilo creado por.

Vayamos un poco más allá...

El ID del hilo que se devuelve a través de ptid/ ctidesnoLo 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 tidocurre 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_SETTIDgarantiza 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_SETTIDtambién se puede utilizar con un efecto similar).

La razón que CLONE_CHILD_CLEARTIDse utiliza para borrar el ptid/ ctides proporcionar una manera para unapthread_join()llame a otro hilo para descubrir que el hilo ha terminado. En esencia, la ubicación ptid/ ctidse 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 greppara usos de lll_wait_tidy lll_futex_waiten el código fuente de glibc. En última instancia, se está FUTEX_WAITllevando a cabo una operación. Recuerde lo anterior que CLONE_CHILD_CLEARTIDrealiza una activación futex en la dirección de destino).

Respuesta2

tidsignifica "identificación del hilo". Los parámetros parent_tidptry child_tidptrapuntan 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.

información relacionada