%EC%9D%98%20parent_tidptr%20%EB%B0%8F%20child_tidptr%EC%9D%80%20%EB%AC%B4%EC%97%87%EC%9E%85%EB%8B%88%EA%B9%8C%3F.png)
위에링크새로운 프로세스를 생성한다는 것은 무엇 parent_tidptr
을 의미합니까 ?child_tidptr
do_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_SETTID
CLONE_CHILD_CLEARTID
flags
해당 호출에서 및 인수 clone()
도 볼 수 있습니다.ptid
ctid
같은 주소를 가리키세요. (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()
필요한가 ? 라는 질문을 촉발합니다. 문제는 사용자 공간 측면에서 상황이 다음과 같다는 것입니다.ptid
ctid
tid = clone(...);
사용자 공간 스레딩 구현의 관점에서 볼 때 여기에는 경쟁이 있습니다 tid
.~ 후에 clone()
보고. 이는 새 스레드가 작업(예: 종료 등)을 수행하기 전에 해당 정보를 원하는 경우 사용자 공간 스레딩 라이브러리가 특정 문제에 직면할 수 있음을 의미합니다. 을 사용하면 CLONE_PARENT_SETTID
새 스레드 ID가 다음이 가리키는 위치에 배치됩니다.ptid
~ 전에
clone()
반환하므로 스레딩 라이브러리가 이러한 경쟁 조건을 피할 수 있습니다. ( CLONE_CHILD_SETTID
비슷한 효과로 사용할 수도 있습니다.)
/를 CLONE_CHILD_CLEARTID
지우는 데 사용되는 이유 는ptid
ctid
pthread_join()
스레드가 종료되었는지 확인하려면 다른 스레드를 호출하십시오. 본질적으로 ptid
/ ctid
위치는푸텍스, 그리고futex()
시스템 호출을 사용하여 차단하고 이 위치의 정수가 변경되기를 기다립니다. (자세한 내용은 약간 복잡하지만 glibc 소스 코드 grep
의 사용 lll_wait_tid
과 내부에서 발생합니다. 궁극적으로 작업이 발생합니다. 대상 주소에서 futex wakeup을 수행하는 위의 내용을 기억하세요.)lll_futex_wait
FUTEX_WAIT
CLONE_CHILD_CLEARTID
답변2
tid
"스레드 ID"를 나타냅니다. 매개변수 parent_tidptr
및 child_tidptr
포인트는 각각 상위 프로세스 주소 공간과 하위 프로세스 주소 공간의 사용자 공간 메모리를 가리킵니다. 새로 생성된 스레드의 ID는 포인터가 가리키는 int 변수에 저장됩니다.
자세한 내용은 다음을 참조하세요.clone(2)
맨페이지.