【发布时间】:2023-03-20 20:19:01
【问题描述】:
我很好奇单个 NPTL 线程是如何退出的,从实现的角度来看。
我对glibc-2.30的实现的理解是:
- NPTL 线程建立在 Linux 上的轻量级进程之上,附加信息存储在用户堆栈的 pthread 对象中,以跟踪 NPTL 特定信息,例如加入/分离状态和返回的对象指针。
- 当一个 NPTL 线程完成后,它就永远消失了,只有用户堆栈(以及因此)pthread 对象被收集(由其他线程加入),除非它是分离的,在这种情况下空间被直接释放。
-
_exit()syscall 杀死线程组中的所有线程。 -
pthread_create()传入的用户函数实际上被包装到另一个函数start_thread()中,该函数在运行用户函数之前做了一些准备工作,然后进行了一些清理工作。
问题是:
-
包装函数
start_thread()的末尾有如下注释和代码:/* We cannot call '_exit' here. '_exit' will terminate the process. The 'exit' implementation in the kernel will signal when the process is really dead since 'clone' got passed the CLONE_CHILD_CLEARTID flag. The 'tid' field in the TCB will be set to zero. The exit code is zero since in case all threads exit by calling 'pthread_exit' the exit status must be 0 (zero). */ __exit_thread ();但
__exit_thread()似乎在做系统调用_exit()反正:static inline void __attribute__ ((noreturn, always_inline, unused)) __exit_thread (void) { /* some comments here */ while (1) { INTERNAL_SYSCALL_DECL (err); INTERNAL_SYSCALL (exit, err, 1, 0); } }所以我在这里感到困惑,因为它不应该真正执行系统调用
_exit(),因为它会终止所有线程。 -
pthread_exit()应该终止一个线程,所以它应该做一些类似于包装器start_thread()最后所做的事情,但是它调用__do_cancel(),TBH 我在追踪那个函数时迷失了方向。好像和上面的__exit_thread()没有关系,也不叫_exit()。
【问题讨论】:
标签: c linux-kernel pthreads system-calls glibc