커널 소스 코드: do_fork()의 parent_tidptr 및 child_tidptr은 무엇입니까?

커널 소스 코드: do_fork()의 parent_tidptr 및 child_tidptr은 무엇입니까?

위에링크새로운 프로세스를 생성한다는 것은 무엇 parent_tidptr을 의미합니까 ?child_tidptrdo_fork()

답변1

원시 시스템 호출 인터페이스를 살펴보는 것부터 시작해 보겠습니다. 아키텍처에 따라 조금씩 다르지만 x86-64에서는 다음과 같습니다.

   long clone(unsigned long flags, void *child_stack,
              int *ptid, int *ctid,
              unsigned long newtls);

ptid그리고 ctid당신의 parent_tidptr및 입니다 child_tidptr. 이제 무엇인지 봅시다clone(2)매뉴얼 페이지는 다음과 같이 말해야 합니다:

   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. 

이러한 플래그는 주로 스레딩 라이브러리를 구현하도록 설계되었습니다. NPTL 구현을 살펴보면pthread_create()glibc 내부에서 우리는 결국 코드를 ​​찾습니다.sysdeps/unix/sysv/linux/createthread.c이는 및 를 clone()포함하는 호출을 수행합니다 .CLONE_PARENT_SETTIDCLONE_CHILD_CLEARTIDflags

해당 호출에서 및 인수 clone()도 볼 수 있습니다.ptidctid같은 주소를 가리키세요. (POSIX 스레드는 주소 공간을 공유한다는 점을 기억하세요. 이는 플래그를 사용하여 수행됩니다 clone() CLONE_VM.)

그래서 여기서 무슨 일이 일어나고 있는지는 다음과 같습니다.

  • CLONE_PARENT_SETTID커널 스레드 ID가 사용자 공간의 특정 위치에 저장되고 있는지 확인하는 데 사용됩니다. 스레딩 구현의 사용자 공간 측에서는 해당 스레드 ID를 알아야 합니다.
  • CLONE_CHILD_CLEARTID에 의해 생성된 스레드가 종료될 때 동일한 위치를 지우는(즉, 0) 데 사용됩니다 clone().

조금 더 나아가자...

ptid/를 통해 반환되는 스레드 ID는 ctid다음과 같습니다.~ 아니다POSIX 스레드 ID( )와 동일 pthread_t하지만 NPTL과 같은 1:1 스레딩 구현에서는 커널 스레드 ID와 POSIX 스레드 ID 간에 일대일 대응이 있습니다. 커널 스레드 ID는 Linux를 사용하여 얻은 ID와 동일합니다.gettid()부르다. 이는 시스템 호출 반환 값으로도 반환되며 , 이는 왜 /가 clone()필요한가 ? 라는 질문을 촉발합니다. 문제는 사용자 공간 측면에서 상황이 다음과 같다는 것입니다.ptidctid

tid = clone(...);

사용자 공간 스레딩 구현의 관점에서 볼 때 여기에는 경쟁이 있습니다 tid.~ 후에 clone()보고. 이는 새 스레드가 작업(예: 종료 등)을 수행하기 전에 해당 정보를 원하는 경우 사용자 공간 스레딩 라이브러리가 특정 문제에 직면할 수 있음을 의미합니다. 을 사용하면 CLONE_PARENT_SETTID새 스레드 ID가 다음이 가리키는 위치에 배치됩니다.ptid ~ 전에 clone()반환하므로 스레딩 라이브러리가 이러한 경쟁 조건을 피할 수 있습니다. ( CLONE_CHILD_SETTID비슷한 효과로 사용할 수도 있습니다.)

/를 CLONE_CHILD_CLEARTID지우는 데 사용되는 이유 는ptidctidpthread_join()스레드가 종료되었는지 확인하려면 다른 스레드를 호출하십시오. 본질적으로 ptid/ ctid위치는푸텍스, 그리고futex()시스템 호출을 사용하여 차단하고 이 위치의 정수가 변경되기를 기다립니다. (자세한 내용은 약간 복잡하지만 glibc 소스 코드 grep의 사용 lll_wait_tid과 내부에서 발생합니다. 궁극적으로 작업이 발생합니다. 대상 주소에서 futex wakeup을 수행하는 위의 내용을 기억하세요.)lll_futex_waitFUTEX_WAITCLONE_CHILD_CLEARTID

답변2

tid"스레드 ID"를 나타냅니다. 매개변수 parent_tidptrchild_tidptr포인트는 각각 상위 프로세스 주소 공간과 하위 프로세스 주소 공간의 사용자 공간 메모리를 가리킵니다. 새로 생성된 스레드의 ID는 포인터가 가리키는 int 변수에 저장됩니다.

자세한 내용은 다음을 참조하세요.clone(2)맨페이지.

관련 정보